|
2.6.3 属性
f[x_] = x^2等の定義は,関数に特定の値を指定する.場合によっては,明示的な値は与える必要がないかもしれないが,一般的な関数の性質は指定しなければならないことがある.
関数の性質は,属性で指定することができる.例えば,Flatと呼ばれる属性を関数に付与しておくと,その関数は「平坦」な特性を持つことになる.つまり,引数の部分がネストすれば,自動的にそのネスト部が平坦化され,結合則が適用可能な状態になる.
属性Flatを関数fに割り当てる.
In[1]:= SetAttributes[f, Flat]
ネスト構成が平坦化され,fは結合則が適用可能な関数になる.
In[2]:= f[f[a, b], c]
Out[2]= 
Flatのような属性は評価の仕方だけでなくパターンマッチング等の操作にも影響する.このため,属性の指定は,関数を定義したり,変換規則を適用する前に行う必要がある.
平坦な関数fに関する定義を作る.
In[3]:= f[x_, x_] := f[x]
fは平坦なので,先の定義はすべての引数に自動的に適用される.
In[4]:= f[a, a, a, b, b, b, c, c]
Out[4]= 

シンボルの属性操作
fに割り当てられた属性を確認する.
In[5]:= Attributes[f]
Out[5]= 
属性をすべて取り除く.
In[6]:= Attributes[f] = { }
Out[6]= 

シンボルの属性一覧
組込み関数Plusがどんな属性を持っているか調べる.
In[7]:= Attributes[Plus]
Out[7]= 
重要な属性にListable(リスト可)がある.この属性は,すべての組込み済み数学関数に割り当てられている.この属性の関数に引数をリストとして与えると,関数頭部がリストの各要素に直接かかるように適用される(頭部をfとすると,fが「糸を縫う」ように各リスト要素に分配されることから,この分配操作は英語でスレッド(thread)とも呼ばれる).
組込み関数Logは属性Listableを持つ.
In[8]:= Log[{5, 8, 11}]
Out[8]= 
関数pをListableと定義する.
In[9]:= SetAttributes[p, Listable]
pはリストの各要素に分配される.
In[10]:= p[{a, b, c}, d]
Out[10]= 
多くの属性は,適用先の関数の評価そのものに直接影響を与える.他の属性は評価には影響しないが,他の面で影響を与える.例えば,属性OneIdentityはパターンマッチング(2.3.7を参照)だけに影響する.同様に,属性Constantは微分を計算するときか,微分に依存する操作が必要なときだけに有効になる.
属性Protectedは割当て操作に影響する.プロテクトのかかったシンボルは再定義することができない.2.5.12で説明した関数ProtectとUnprotectを,SetAttributesとClearAttributesの代りに使っても,プロテクトの有効化と解除を行うことができる.2.5.12で触れたが,Mathematicaが起動した時点では,ほとんどの組込み関数はプロテクトがかかっている.このため,ユーザが誤って定義付けをしようとしても,できないようになっている.
関数gを定義する.
In[11]:= g[x_] = x + 1
Out[11]= 
gにプロテクトをかける.
In[12]:= Protect[g]
Out[12]= 
今度は,gの定義は変更することができ ない.
In[13]:= g[x_] = x

Out[13]= 
特定のシンボルに割り当てた定義を参照するには?fと入力する(組込み関数にもこれに関連した機能を提供するものが各種あるので,それらを使ってもよい).参照禁止の属性ReadProtectedを変数や関数に付加しておけば,定義内容が参照できないようにすることができるようになっている.参照不可になっても,関係式自体は有効なままであり,引き続き評価に使うことができる.
gの定義式を変更することはできないが,参照することは可能である.
In[14]:= ?g


属性ReadProtectedを割り当てて,gを参照不可にする.
In[15]:= SetAttributes[g, ReadProtected]
今度は,定義内容は参照することができない.
In[16]:= ?g


SetAttributesやClearAttributesのような関数を使えば,通常,変数や関数の属性をどのようにでも設定変更することができる.ただし,あらかじめ変数や関数に属性Lockedが割り付けられてあるときは,属性の変更はできない.(新たに設けたMathematicaセッションなら,ロックは解除されるので,この限りではない.)属性Lockedを属性Protectedと参照禁止の属性ReadProtectedに組み合せて使うことで,ユーザによる不用意な定義内容の参照や,変更を未然に防ぐことができる.

値と属性の消去
上の例でpに属性Listableを与えたが,ここで,値と属性のすべてを消去する.
In[17]:= ClearAll[p]
属性を取ってしまったので,pは展開することができない.
In[18]:= p[{a, b, c}, d]
Out[18]= 
関数に属性を与えるということは,Mathematicaに対して評価や参照で特別な性質を考慮するよう指示することを意味する.通常,一度与えられた性質は常に有効だが,場合によっては,限られた状況下でだけそれを有効にしたいかもしれない.そのようなときは,属性は直接使わずに,代りに,特殊な関数を呼び出すことで属性のかもし出す性質を兼ね備えた作用形態にすることも可能である.
Threadを直接作用させ,pがListableのときに自動的に行われる変換操作を強制する.
In[19]:= Thread[p[{a, b, c}, d]]
Out[19]= 

属性に関連した変換操作を行うための関数
属性は単一シンボルに対してのみ恒久的に定義される.ただし,属性付きの純関数を構築することで,一時的にしか有効でない属性を備えた関数を定義することは可能である.

属性を備えた純関数
この純関数では,pをリスト全体に適用 する.
In[20]:= Function[{x}, p[x]] [{a, b, c}]
Out[20]= 
属性Listableを加えておくと,pがリストの各要素に分配されるようになる.
In[21]:= Function[{x}, p[x], {Listable}] [{a, b, c}]
Out[21]= 
|