R: 関数のリストと環境

投稿者: | 2018年1月4日

概要

  • 複数の関数を自動的に生成してリストで管理したい
  • 生成時に変数の値を関数毎に異なる値に設定したい
  • そのために、関数毎に異なる環境を設定する

関数のリスト

R では関数をオブジェクトとして扱うことができますね。
そのため、変数を並べたリストと同じように、
関数を並べたリスト、関数のリストを作ることができます。

例えば、引数をそのまま返す関数 f1 と、
引数を二乗して返す関数 f2 を順に並べた
関数のリスト lf は次のように生成できます。

lf の 1 番目の要素はf1 で、
2 番目の要素は f2 になっており、 lf[[1]](2) は 2 を、
lf[[2]](2)\(2^2 = 4\) を返します。

関数の自動生成(失敗例)

関数のリストを使えば、
for 文などで、複数の関数を生成して、
それをリストでひとまとめに管理できそうですね。

例えば、引数を1乗、2乗、3乗… する関数 f_1,f_2,f_3,...
をリストとして並べた関数のリストlfを次のように作れそうです。

ところが、このリストに格納された関数を使ってみると、
もともと意図していたような動作をしてくれないことが分かります。

このように全て引数を3乗する関数になってしまいます。

関数の環境

なぜこのような動作になるのでしょうか。

この理由は、関数内のx^iiがグローバル変数として扱われるからです。
for 文を実行した際に最終的にiの値は3となっており、
リスト内のどの関数もx^3の計算を行います。

関数内の変数はグローバル変数

実際、グローバル変数iの値を2に変更してから、
リスト内の関数を適用すると、

このように、すべて2乗する関数に変わります。

関数にローカルな変数を持たせる

もともとの意図としては、
関数内のiの値は関数を生成した際のiの値に固定して欲しいのですが、
そのような挙動をさせるにはどうすれば良いのでしょうか。

実は、R では関数毎に環境を持たせることができます。
そのローカルな環境の中で i を定義すれば、
グローバルな i とは異なる値を関数毎に持つことができます。

まずは、リストではなく普通の関数で実際に試してみましょう。

下のコードでは、普通に生成した関数global_fと、
ローカルな環境を持たせたlocal_fを生成しています。

new.env()で新しい環境を生成し、
assignで変数i に今の変数i=3の値を割り当て、
その環境をlocal_fの環境に設定しています。

この状態では、global_f,local_fのどちらも、
引数を3乗する関数として働きます。

では、グローバル変数iの値を2に変更するとどうなるでしょうか。

このように、global_fの方はi=2になったことで、
引数を2乗する関数に変わっていますが、
local_fの方は、グローバル変数の値が変更された後でも、
ちゃんと3乗する関数として働いていることが分かります。

これで、関数の中でローカルに変数の値を持たせることができました。

関数の自動生成(成功例)

それでは、先ほど上手くいかなかった関数のリストの生成を、
関数に環境を持たせながらやってみましょう。

そして、リスト内の関数を使ってみます。

ちゃんと、1乗、2乗、3乗の関数になっています。

まとめ

複数の関数をリストで管理したいという
ちょっと変わった使い方の紹介でした。

当然、リストを使わなくても、
引数を増やせば同じようなことができますね。
こんな感じに、

なので、必ずしもリストで管理する必要はないかもしれませんが、
もし使う機会があったらという程度の小技みたいなものでしょうか。


 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です