Skip to content

Instantly share code, notes, and snippets.

@kohyama
Last active October 23, 2017 02:41
Show Gist options
  • Save kohyama/5964548 to your computer and use it in GitHub Desktop.
Save kohyama/5964548 to your computer and use it in GitHub Desktop.
外部から文字列で与えた式を, 内部に出て来る変数を実行時に決まる値で束縛した状態で評価したい. I want evaluate a expression which comes from outside as a string with some variables binded to values determined at runtime.
(def s "(- a b)"))

のような文字列があるとき, 実行時に決まる値で a や b を束縛して, この式を評価したいとする.

(let [a 4 b 3] (eval (read-string s)))

CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:2:1)

といった例外で失敗する.

引数に a や b を受け取る関数を eval に返させて, それを実行時に適用することで, 所望の動作を実現できる.

((eval (read-string (str "(fn [a b] " s ")"))) 4 3) ; -> 1

eval による関数の生成と, その適用を分けて書けば以下のようになる.

(let [f (eval (read-string (str "(fn [a b] " s ")")))]
  (f 4 3))
; -> 1

参考: [Clojure Google Group 「(let [a 0] (eval 'a))」] (https://groups.google.com/forum/#!topic/clojure/eAo_vjQartU)


When given a string

(def s "(- a b"))

, I want to evaluate the expression with a and b binded with values determined at runtime.

(let [a 4 b 3] (eval (read-string s)))

fails with an exception like

CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:2:1)

You can do what you want to do with letting eval return a function which receives a and b as arguments, and applying the function at runtime.

((eval (read-string (str "(fn [a b] " s ")"))) 4 3) ; -> 1

You can write it with a generation of function and the application separated.

(let [f (eval (read-string (str "(fn [a b] " s ")")))]
  (f 4 3))
; -> 1

reference: [Clojure Google Group: "(let [a 0] (eval 'a))"] (https://groups.google.com/forum/#!topic/clojure/eAo_vjQartU)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment