私が有効なのClojure/ClojureScriptフォームを含む、以下の文字列を持っている場合:私は、このフォームの最初の「ステップ」を評価する方法をClojureフォームの最初のステップを評価するにはどうすればよいですか?
"(+ 1 (+ 2 (/ 6 3)))"
を?
"(+ 1 (+ 2 2))"
してから、このことに対応した形状を回す:あなたは再帰を使用
"(+ 1 4)"
私が有効なのClojure/ClojureScriptフォームを含む、以下の文字列を持っている場合:私は、このフォームの最初の「ステップ」を評価する方法をClojureフォームの最初のステップを評価するにはどうすればよいですか?
"(+ 1 (+ 2 (/ 6 3)))"
を?
"(+ 1 (+ 2 2))"
してから、このことに対応した形状を回す:あなたは再帰を使用
"(+ 1 4)"
言い換えれば、どのように私はこれに上記のフォームをオンにします。したがって
(evaluate '(+ 1 (+ 2 (/ 6 3))))
これは次のように扱われるべきである。..
あなたが自分自身に番号を評価する関数を持っている必要がありますが、それは番号がない場合は、引数の評価に操作を適用する必要があります。
(+ (evaluate '1) (evaluate '(+ 2 (/ 6 3))))
最初の手順を開始すると、いくつかの手順で結果が完了するのを待っています。
注意私はリスト構造を使用していますが、文字列ではありません。文字列では、それを解析するためにいくつかの関数を使う必要があります。
以下は、あなたが探しているものを実行する非常に基本的な実装です。フォーム全体をevalに、より一般的だろうが、あなただけの最も内側の式を簡素化したいとしているので、これはない:
(defn leaf?
[x]
(and (list? x)
(symbol? (first x))
(not-any? list? (rest x))))
(defn eval-one
[expr]
(cond
(leaf? expr) (apply (-> (first expr) resolve var-get)
(rest expr))
(list? expr) (apply list (map eval-one expr))
:default expr
))
(read-string "(+ 1 (+ 2 (/ 6 3)))")
=> (+ 1 (+ 2 (/ 6 3)))
(eval-one *1)
=> (+ 1 (+ 2 2))
(eval-one *1)
=> (+ 1 4)
(eval-one *1)
=> 5
これはナイーブおよび例示を目的とするものであり、そうでないようにしてください本当の評価がこのように機能するという印象の下で。
リーフは、最初の要素がシンボルであり、評価可能な他のリストを含まないリストとして定義します。次にフォームを処理し、リーフ式を評価し、リストである非リーフ式を再帰的に評価し、他のものについては結果の式に挿入するだけです。その結果、私たちの定義にしたがって、評価できる最も内側の式が評価されます。
他の回答は、コードをステップごとに実行する場合に最適ですが、この評価はデバッガを使用して視覚化することもできます。アクションでCider's debugger以下を参照してください。
cider-debug-defun-at-point
を使用することにより、我々はevaluate
にブレークポイントを追加します。次に、evaluate
の定義が評価されると、ブレークポイントがヒットし、next
を繰り返し押してコードをステップ実行します。
デバッガは、フォームの「ステップ」を評価するときに非常に便利です。ここでは、他の偉大な答えに追加するには
ああ、私はそれについても考えていませんでしたが、デバッガは私が探しているものです。 –
私はemacsのインストールでcider-debug-defun-at-pointを持っていないようです。新しいですか? –
@LincolnBergeson設定にCiderを追加しましたか?それは(含まれている)(https://github.com/clojure-emacs/cider/blob/master/cider-debug.el#L743)。私はSpacemacsを[Clojure layer](https://github.com/syl20bnr/spacemacs/tree/master/layers/%2Blang/clojure)で追加しました。そうすれば 'dotspacemacs-configuration-layers'リストに' clojure'を追加するだけでした。 –
は、与えられた文字列に評価するための最初のフォームを返す必要があります簡単な関数である:
(defn first-eval [form-str]
(let [form (read-string form-str)
tree-s (tree-seq sequential? identity form)]
(first (filter #(= % (flatten %)) tree-s))))
は使用方法:
(first-eval "(+ 1 (+ 2 (/ 6 3)))") ;; returns (/ 6 3)
tree-seq
かなり限られていますそれはすべてのフォームを評価する能力ですが、それはスタートです。
私の基本的なケースは何ですか?どのようにして(/ 6 3)が最初に評価されるべきであると私は決めることができますか? –
ベースケースは数値式です。 「6」は「6」と評価される。したがって、 '(evaluate '(/ 6 3)); ==>((get-fun '/)(evaluate' 6)(evaluate '3)) '。評価者が常に依存関係を最初に実行するため、これを決定する必要はありません。 – Sylwester