3

関数内から、関数外で定義された var の名前を取得したいと思います。名前は、実際に名前を使用しようとしているネストされたバインディングではなく、元の定義のスコープで使用した名前にする必要があります。

だから私は(学術的な例)のようなことをしたいと思います:

(defn f1 [x1] (println "hello, you passed var name >>" (get-var-name x1) "<<")
(defn f2 [x2] (f1 x2))
(defn f3 [x3] (let [zzz x3] (f2 zzz))
(def my-var 3.1414926)
(f3 my-var)
user> hello, you passed var name >>my-var<<

私が見つけたいくつかのものに基づいて、このマクロを実行できます。

(defmacro get-var-name [x]
  `(:name (meta (var ~x))))

これは、たとえば REPL から呼び出された場合に機能しますが、「内部」スコープから呼び出された場合、コンパイラはチョークします。

(defn another-func [y]
  (get-var-name y))

コンパイラは、「変数 y を解決できないと言っています」と言います。 (macroexpand...)は、現在の名前空間の元の変数ではなく、現在の名前空間でローカル変数 y を見つけようとしていることを示しています。) は名前空間変数のみを(var...検索するため、マクロが関数内またはlet.

変数を定義し、それを追加のパラメーターとして渡すのと同じスコープから変数名を手動で取得する必要があることに行き詰まっていると思います。変数名情報をバインディングのチェーンを介して、それが使用されるポイントに渡すよりエレガントな方法はありますか? それはまずいでしょう。

ありがとう

4

3 に答える 3

1

#'以下に示すように、リーダー マクロを使用して、var で解決された値ではなく、実際の var を関数に渡すことができます。

user=> (defn f1 [x1] (println "hello, you passed var name >>" (:name (meta x1)) "<<"))
#'user/f1
user=> (defn f2 [x2] (f1 x2))
#'user/f2
user=> (defn f3 [x3] (let [zzz x3] (f2 zzz)))  
#'user/f3
user=> (def my-var 3.1414926)
#'user/my-var
user=> (f3 #'my-var)
hello, you passed var name >> my-var <<

変数にバインドされた値が必要な場合は、var-get関数を使用してそうすることができます。

于 2012-08-08T04:23:31.313 に答える
0

(get-var-name _symbol-here_)本体内で var 名を使用したい関数に渡さないのはなぜですか? たとえば、上で示したget-var-namef2f3、 とまったく同じ定義を使用します (ただし、わずかにmy-var変更されています)。f1

(defmacro get-var-name [x]
  `(:name (meta (var ~x))))
(defn f1 [x1] (println "hello, you passed var name >>" x1 "<<"))
(defn f2 [x2] (f1 x2))
(defn f3 [x3] (let [zzz x3] (f2 zzz)))
(def my-var 3.1414926)
=> (f3 (get-var-name my-var))
hello, you passed var name >> my-var <<
=> nil

場合によっては、関数本体でシンボルが参照する値も参照したい場合があります。たとえば、f1その var 名によって参照される値も出力したいとします。これを行う方法は次のとおりです。

(defn f1 [x1] (println "hello, you passed var name >>" x1 "<<"
                       "\nwhich refers to value >>" @(resolve x1) "<<"))
=> (f3 (get-var-name my-var))
hello, you passed var name >> my-var << 
which refers to value >> 3.1414926 <<
=> nil

@(resolve x1)--this は、参照する値を返すものであることに注意してくださいmy-var(そして、my-varによって参照される値ですx1)。

get-var-nameまた、渡された引数がシンボルではないか、シンボルであるが、現在値にバインドされていない場合、現在の実装は例外をスローすることにも言及したいと思います。これはあなたが望む動作ですか?

私が提案したことがあなたの質問に答えない場合、最終的に var 名を使用する可能性のある関数に渡す必要がないように思われますが何らかの理由でfrom within(get-var-name _symbol-here_)を本当に実行できるようにしたい(get-var-name ...)関数本体。もしそうなら、なぜそのようにできるようになりたいのですか?または、他の理由で私があなたの質問に答えていないと思われる場合、その理由は何ですか?

于 2012-08-08T03:35:13.333 に答える