SICP的な状態を共有する複数のクロージャをJavaScriptでどう書くか
某展示会の学術系ブースで、このようなSICP的な状態を共有する複数のクロージャをJavaScriptで書きたいわけだが、
"use strict" var [getVal, setVal] = (function () { var v return [function () { return v }, function (new_v) { v = new_v }] })() setVal(42) console.log(getVal())
(JavaScriptの動作確認には node を使っています)
流石にこのように無名関数をバリバリ書こうとは思わないだろうので、それを解消する提案、というようなものを見ました。
提案されていた手法は、特別な記法でこの例の v のような変数をマークアップし、プリプロセッサのようなもので、もっとプレーンな書き方をしたJavaScriptから、このようなコードに変換する、というものでしたが、それについてはこの記事の本題ではありません。
Pythonで書くと、こんな感じになるでしょうか。
#! /usr/local/bin/python3 def mk_val(): v = None def get_val(): return v def set_val(new_v): nonlocal v v = new_v return get_val, set_val get_val, set_val = mk_val() set_val(42) print(get_val())
Pythonではlamdaがあえてかなり使いにくく設計されており、このように明示的に手続きに名前を付けるスタイルになります*1。
このPythonの場合を踏まえて、最初の例を考えてみると、こういうスタイルが出てきます。
"use strict" function mkVal() { var v function getVal() { return v } function setVal(new_v) { v = new_v } return [getVal, setVal] } var [getVal, setVal] = mkVal() setVal(42) console.log(getVal())
SICP中でも、どうしてもlambdaが必要な場合は使っていますが、それよりもネストしたdefineのほうが自然な場合はそちらが多用されているような気がします。どうでしょうか?