構造的演算 †
純関数 †
さて、これまであるシンボル f に対して関数 f[...] を定義する方法を述べてきましたが、SAD にはこのようなシンボル f を使わなくても定義できる関数の形式があります。これを純関数 pure function と呼びます。純関数は構造的演算に際して多用されます。
純関数1 演算子 & とSlot †
- (式1)& は純関数を表わします。式1は Slot (#, #n, ##, ##n) を含む式です。純関数の引き数はこの Slot を通して受け渡されます。
- (式1)&[引き数1, 引き数2, ..] は純関数を引き数1, ...に対して適用します。式1が、その引き数をこの Slot を通して受け渡されつつ評価され、その結果が返されます。
- # は引き数1を表わします。
- #n は引き数n を表わします。
- ## は引き数全体の系列を表わします。
- ##n は引き数n 以降の系列を表わします。
例えば、(Sin[#] / Cos[#2])&[a, b] ⇒ Sin[a] / Cos[b] など。
純関数それ自身は評価されても形を変えません。
純関数の中で純関数を含む式を多重に使用することは可能です。ただし、その場合、Slot と引き数の対応がわかりにくくなることが避け難いので、なるべくならば With により純関数に名前をつけるなどの工夫が望ましいでしょう。また、場合によっては Slot ではどうしても引き数の対応ができない場合も発生します。
純関数2 Function †
純関数の多重使用により、Slot による対応が不可能なときには Function を用いて Slot によらない引き数の対応をおこなう純関数を定義できます。
- Function[{シンボル1, ...}, 式1] は純関数で、その引き数はシンボル1, ...に対応します。式1はシンボル1, ...を含む式で、純関数の胴体です。
- Function[{x, y}, Sin[x] / Cos[y]][a, b] ⇒ Sin[a] / Cos[b]。
- 引き数のシンボルは純関数の胴体に露に書かれたもののみが対応する値に置き換わります。
構造的演算とは †
SAD では個々の原子、リストの要素に対しては勿論様々な演算が可能ですが、それ以上にあるリストや式の全体に対して一度に演算をすることができます。例えば、算術演算はリストに対してはその要素に並列に作用することは既に述べました。実は一般の関数に対してもそのような演算が可能です。ここではリストや式の全体に作用させる演算を「構造的演算」と呼ぶことにします。構造的演算の代表的なものが Map (演算子 /@)と Apply (演算子 @@) です。これらは SAD ではきわめて多用されるため、特別な演算子まで与えられています。
いま、ある2階のリスト l があるとして、その各要素の長さを要素とするリストを造りたいとしましょう。この問題は Map(/@) を使えば、
Length /@ l
だけで書くことが出来ます。一般にある関数 f に対して、f /@ {a_1, a_2, ...} は {f[a_1], f[a_2], ...} を実行します。
次に、数値を要素とするあるリスト l に対して、その合計、平均値、2 乗平均値を求めたいとします。これらは Apply(@@) を使って、それぞれ
Plus @@ l
Plus @@ l / Length[l]
Plus @@ (l^2) / Length[l]
と書かれます。一般にある関数 f に対して、f @@ {a_1, a_2, ...} は f[a_1, a_2, ...] を実行します。
この様に、構造的演算により、複雑な演算をきわめて簡潔に書くことが出来ます。構造的演算は単に簡潔さだけでなく、実行速度の向上にも寄与します。しかし、構造的演算を一つの式の中で幾重にも重ねますと、プログラムの可読性は低下してしまいますので注意してください。
様々な構造的演算 †
以下において演算の作用するリストは必ずしも頭部が List である必要はありません。
これらの内、Map, MapAll, MapIndexed, Apply, Scan, Cases, DeleteCases に対しては、階数指定子 (Level を参照) により演算の範囲を指定できます。
Map, /@ †
- f /@ リスト1 はリスト1 の各要素に関数 f を作用させます。
- Map[f, リスト1, 階数指定子1] はリスト1の階数指定子1 (Levelを参照) で指定される階の各要素に関数 f を作用させます。
- f /@ リスト1 と Map[f, リスト1] は Map[f, リスト1, {1}] と同値です。
MapAll, //@ †
- f //@ リスト1 はリスト1 のすべての階 (0 階を含む) の全要素に関数 f を作用させます。
- f //@ リスト1 はMap[f, リスト1, {0, Infinity}] と同値です。
- 結果の頭部はもとの式の頭部になります。
- MapAll[f, リスト1, Heads -> True] はリスト1のすべての階の全要素と頭部に関数 f を作用させます。
MapIndexed †
- MapIndexed[f, リスト1] はリスト1 の各要素に関数 f を作用させますが、そのときその要素のリスト1のなかでの位置を第二引き数として f に渡します。
- MapIndexed[f, リスト1, 階数指定子1] はリスト1 の階数指定子1 (Level を参照) で指定される階の各要素に関数 f を作用させますが、その要素のリスト1 のなかでの位置を第二引き数として f に渡します。
Apply, @@ †
- f @@ リスト1 はリスト1 の全要素からなる系列を引き数として関数 f を評価します。
- Apply[f, リスト1, 階数指定子1] はリスト1の階数指定子1 (Level を参照) で指定される階の全要素からなる系列を引き数として関数 f を評価します。
- f @@ リスト1 と Apply[f, リスト1] は Apply[f, リスト1, {0}] と同値です。
- 結果の頭部は、その階に Apply が作用していなければ、もとの式の頭部が保存されます。例えば、Apply[f, g[h[1, 2], h[3, 4]], {1}] ⇒ g[f[1, 2], f[3, 4]]。
Scan †
ScanThread †
Position †
- Position[式1, パターン式1] は式1の全部分式の中でパターン式1に照合するものの位置達をリストにして返します。
- Position[式1, パターン式1, 階数指定子1] は階数指定子1 (Levelを参照) で指定される階数の、パターン式1に照合する部分式の位置達を返します。
- Position[式1, パターン式1, 階数指定子1, n1] は階数指定子1で指定される階数の、パターン式1に照合する部分式の位置達の内の最初の n1 個を返します。
Count †
- Count[式1, パターン式1] は式1の全部分式の中でパターン式1に照合するものの個数を返します。
- Count[式1, パターン式1, 階数指定子1] は階数指定子1 (Level を参照) で指定される階数の、パターン式1に照合する部分式の個数を返します。
- Count[式1, パターン式1, 階数指定子1, n1] は階数指定子1で指定される階数の、パターン式1に照合する部分式の位置達の内の最初の n1 個の部分式の個数を返します。
Cases †
- Cases[リスト1, パターン式1] はリスト1 の要素の中でパターン式1 に照合するもの達をリストにして返します。
- Cases[リスト1, パターン式1, 階数指定子1] は階数指定子1 (Level参照) で指定される階数の、パターン式1に照合する部分式達を返します。
- Cases[リスト1, パターン式1, 階数指定子1, n1] は階数指定子1 で指定される階数の、パターン式1に照合する部分式達の内の最初の n1 個を返します。
- 上記のパターン式1を パターン式1 -> 変更値1のように書くと、結果に対してこの規則による置換が行われます。
DeleteCases †
- DeleteCases[リスト1, パターン式1] はリスト1 の要素の中でパターン式1 に照合するもの達を除いたリストを返します。
- DeleteCases[リスト1, パターン式1, 階数指定子1] は階数指定子1 (Level を参照) で指定される階数の、パターン式1 に照合する部分式達を除いたリストを返します。
MapAt †
- MapAt[関数1, リスト1, n1] はリスト1のn1 番目の位置に関数1 を適用し、その結果に置き換えたリストを返します。
- MapAt[関数1, リスト1, {n1, n2, ... }] はリスト1の {n1, n2, ...} の位置
(リスト1[[n1, n2, ...]])
に関数1 を適用し、その結果に置き換えたリストを返します。
- MapAt[関数1, リスト1, {{n1, ...}, {n2, ... }}] はリスト1 の幾つかの位置達に関数1 を適用し、その結果に置き換えたリストを返します。
MapThread †
- MapThread[f, {{a_1, a_2, ...},{b_1, b_2, ...}, ...}] は {f[a_1, a_2, ...], f[b_1, b_2, ...], ...} を返します。
- MapThread[関数1, {式1, 式2, ...}, 階数指定子1] は階数指定子1 で指定される式1, 式2, ... の部分式達に関数1 を適用します。
Nest †
- Nest[関数1, 式1, n] は式1 に関数1 を n回適用した結果を返します。
- Nest[f, x, 3] ⇒ f[f[f[3]]] 。
Select †
- Select[リスト1, 関数1] はリスト1の各要素に関数1を適用し、その結果が True (非0) になるもの達から成るリストを返します。
- Select[リスト1, 関数1, n1] はリスト1の各要素に関数1を適用し、その結果が True (非0) になるもの達の内、最初の n1 個から成るリストを返します。
SwitchCases †
- SwitchCases[リスト1, {パターン式1, パターン式2, ...}] はリスト1の各要素をパターン式1, パターン式2, ...に照合するものに分類したリストを返します。
- SwitchCases[{1, "a", x, 4}, {_Real, _String}] ⇒ {{1, 4}, {"a"}}。
- もしどれにも分類されないものも結果に必要な場合はパターン式のリストの最後に\_を加えれば済みます。
SelectCases †
- SelectCases[リスト1, {関数1, 関数2, ...}] はリスト1の各要素を、関数1, 関数2, ...を適用した結果が True (非0) になるものに分類したリストを返します。
- SelectCases[{1, 2, 3, 4}, {(#<2)&, (#>=3)&}] ⇒ {{1}, {3, 4}}。
- もしどれにも分類されないものも結果に必要な場合は関数のリストの最後に True& を加えれば済みます。