統計解析R たぶんpart3くらい (587レス)
統計解析R たぶんpart3くらい http://mevius.5ch.net/test/read.cgi/tech/1340339592/
上
下
前次
1-
新
通常表示
512バイト分割
レス栞
抽出解除
必死チェッカー(本家)
(べ)
自ID
レス栞
あぼーん
リロード規制
です。10分ほどで解除するので、
他のブラウザ
へ避難してください。
471: デフォルトの名無しさん [] 2023/02/26(日) 00:14:58.50 ID:Qcp1BikG 上のコード`uncertainly`の挙動を"プロミスの罠"と書くことにする。 ここでの"プロミス"は、JSの"プロミス"ではなくて、Rでの"変数"の 実装方法を指す。 * [6 Functions | Advanced R](https://adv-r.hadley.nz/functions.html) この記事には次の一節がある。 > You cannot manipulate promises with R code. Promises are like a **quantum state:**: ... 多分、ここでの"量子状態"はハイゼンバグと同じ現象を指しているんだと思う。 観測すると、状態が変化してしまう。 関数`do.call`自体はプロミスの罠と関係しないと思う。 ``` {r a_28697, dependson = ""} do.call (`+`, list (1L, 2L)) ``` Pythonだと次のコードに対応する。 ``` {python a_10786, dependson = ""} (lambda x, y: x + y) (* range (1, 3)) ``` 殆どのプログラミング言語で、関数の引数リストは [一級市民](https://en.wikipedia.org/wiki/First-class_citizen) でないように思う。一級市民でない代わりに、一級市民の配列からの変換が 用意されている。Pythonでは`*`という関数がビルトインで用意されている。 Rでは引数リストを直接作れるかもしれないが、`do.call`で配列から 変換するのが一般的だと思う。 http://mevius.5ch.net/test/read.cgi/tech/1340339592/471
472: デフォルトの名無しさん [] 2023/02/26(日) 23:03:36.96 ID:Qcp1BikG 書けるかな? http://mevius.5ch.net/test/read.cgi/tech/1340339592/472
473: デフォルトの名無しさん [] 2023/02/26(日) 23:09:42.38 ID:Qcp1BikG 自分の知る限り、プロミスの罠にハマるのは次のパターンに限られる。 ~~~ {.r} x = "hello" g = f (x) x = "world" g () ~~~ "関数を返す関数"`f`に、"変数"`x`を代入した時にプロミスの罠が可能性が 出てくる。Rの評価戦略はHaskellと同じ [コールバイニード](https://en.wikipedia.org/wiki/Evaluation_strategy) に分類されている。上の例では、次の場合にプロミスの罠が発生する。 1. 関数`f (x)`の中で引数`x`がニードにならず、 1. 返り値の関数`g`に渡される。 次の例はプロミスの罠が発生する。 ``` {r a_20914, dependson = ""} rude = with (new.env (), { const = \(x) \(...) x x = "hello" g = const (identity (x)) x = "world" g () |> print () }); ``` 関数への代入はニードでないので(by definition)、関数適用の連鎖 `const (identity (x))`の中にはニードがない。そのために、最終的に`g ()`が コールされるまで引数`x`は評価されない。コード`g ()`がコールされた時点で 引数`x`の定義を探しに行くので、プロミスの罠にハマる。 http://mevius.5ch.net/test/read.cgi/tech/1340339592/473
474: デフォルトの名無しさん [] 2023/02/26(日) 23:11:33.81 ID:Qcp1BikG コールバイニードを実現するためには、コンパイラーが内部的に次のように 書き換える必要があると思う。 ``` {r a_1451, dependson = ""} polite = with (new.env (), { const = \(x) \(...) x x_1 = "hello" g = const (identity (x_1)) x_2 = "world" g () |> print () }); ``` [静的単一代入](https://en.wikipedia.org/wiki/Static_single-assignment_form) と呼ばれる操作と同じだと思う。この書き換えはループ処理では必須になる。 コード`rude`はアカン奴として切り捨てることができるかもしれないが、 ループ処理では変数の多重定義が避けられない。Rでは、何らかの理由で、 この書き換えが省略されているために、プロミスの罠が発生するのかな?と 思っている。 コード`rude`からコード`polite`への書き換えを上とは異なる形で行ってみる。 Rではできないので、Pythonを使う。 http://mevius.5ch.net/test/read.cgi/tech/1340339592/474
475: デフォルトの名無しさん [] 2023/02/26(日) 23:12:32.78 ID:Qcp1BikG ``` {python a_14213, dependson = ""} ##| cache: false # def none (): id = lambda a: a const = lambda x: lambda * y: x def lhs (): x = "hello" g = const (id (x)) x = "world" return g () def rhs (): return (lambda x: (lambda g: (lambda x: g ()) ("world")) (const (id (x)))) ("hello") assert lhs () == rhs () none (); ``` 関数`lhs`から関数`rhs`への書き換え規則は次のようになる。[rule]{#rule} ~~~ {.python} y = f (x) z = g (x, y) rest (x, y, z) == (lambda y: z = g (x, y) rest (x, y, z) ) (f (x)) == (lambda y: (lambda z: rest (x, y, z)) (g (x, y))) (f (x)) ~~~ http://mevius.5ch.net/test/read.cgi/tech/1340339592/475
476: デフォルトの名無しさん [] 2023/02/26(日) 23:25:12.65 ID:Qcp1BikG この書き換え規則を適用した結果、関数`rhs`では、静的単一代入への変換は、 [ラムダ計算](https://en.wikipedia.org/wiki/Lambda_calculus)のアルファ変換 に置き換わる。この意味では、静的単一代入とアルファ変換は同じことになる。 実際のコードでは、分岐、ループ、副作用が入ってくるので、こんな単純は 話では済まないと思うが、極度に単純化すると、静的単一代入とアルファ変換は、 単に、方言の違いということになる。 Rの場合は、書き換え規則[rule](#rule)は等価な変換にならない可能性がある。 特に、プロミスの罠が現れた場合は、挙動が変わると思う。 余談だが、書き換え規則[rule](#rule)をモナドに拡張したものがHaskellの [do-記法](https://en.wikibooks.org/wiki/Haskell/do_notation)になっている。 ~~~ {.python} y <- f (x) z <- g (x, y) rest (x, y, z) == kleisli-extension (lambda y: z <- g (x, y) rest (x, y, z) ) (f (x)) ~~~ モナドが恒等関数の場合に[rule](#rule)に一致するので、do-記法を [rule](#rule)の拡張と言って差し支えないと思う。 おしまい http://mevius.5ch.net/test/read.cgi/tech/1340339592/476
メモ帳
(0/65535文字)
上
下
前次
1-
新
書
関
写
板
覧
索
設
栞
歴
スレ情報
赤レス抽出
画像レス抽出
歴の未読スレ
AAサムネイル
Google検索
Wikipedia
ぬこの手
ぬこTOP
0.034s