(partial apply str) 和 clojure 中的 apply-str ->

发布于 2024-08-27 20:39:20 字数 414 浏览 6 评论 0原文

如果我执行以下操作:

user=> (-> ["1" "2"] (partial apply str)) 
#<core$partial__5034$fn__5040 clojure.core$partial__5034$fn__5040@d4dd758>

...我会恢复部分功能。但是,如果我将它绑定到变量:

user=> (def apply-str (partial apply str))
#'user/apply-str
user=> (-> ["1" "2" "3"] apply-str)       
"123"

...代码将按我的预期工作。我认为它们是同一件事,但显然情况并非如此。有人可以解释为什么这对我来说吗?

If I do the following:

user=> (-> ["1" "2"] (partial apply str)) 
#<core$partial__5034$fn__5040 clojure.core$partial__5034$fn__5040@d4dd758>

...I get a partial function back. However, if I bind it to a variable:

user=> (def apply-str (partial apply str))
#'user/apply-str
user=> (-> ["1" "2" "3"] apply-str)       
"123"

...the code works as I intended it. I would assume that they are the same thing, but apparently that isn't the case. Can someone explain why this is to me?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

混浊又暗下来 2024-09-03 20:39:21

->是一个宏,因此它不必遵循您在应用方面期望的规则。宏在评估表单之前转换源。尝试宏扩展形式:

user> (macroexpand '(-> ["1" "2"] (partial apply str)))
(partial ["1" "2"] apply str)

您想通过使用“->”来实现什么目的宏?

编辑:请注意:

user> ((partial apply str) ["1" "2"])
"12"

-> is a macro, so it doesn't have to follow the rules you would expect in terms of application. The macro transforms the source before the forms are evaluated. Try macroexpanding the forms:

user> (macroexpand '(-> ["1" "2"] (partial apply str)))
(partial ["1" "2"] apply str)

What are you trying to achieve here by using the '->' macro?

EDIT: Note that:

user> ((partial apply str) ["1" "2"])
"12"
不及他 2024-09-03 20:39:21

你根本不必这样做。

(->> ["1" "2" "3"] (apply str))

为什么不这样做呢?

You don't have to do that at all.

(->> ["1" "2" "3"] (apply str))

Why not do that instead?

平定天下 2024-09-03 20:39:21

第一个表达式 (-> ["1" "2"] (partial apply str)) 扩展为:

(partial ["1" "2"] apply str)< /code> 基本上意味着:

使用 Vars apply< 从 ["1" "2"] 创建一个函数(这也是一个函数,因为向量是索引键的函数!) /code> 和 str 已作为前两个参数提供。该函数被打印为奇怪的 # 字符串。
仅当调用此函数时,您才会收到 IllegalArgumentException,因为向量仅采用一个整数参数,而不是两个 Var 参数。

The first expression, (-> ["1" "2"] (partial apply str)), expands into:

(partial ["1" "2"] apply str) which basically means:

Create a function from ["1" "2"] (which is also a function, since vectors are functions of index keys!) with the Vars apply and str already supplied as the first two arguments. This function gets printed as the weird #<core$partial...> string.
Only when this function will be called will you get an IllegalArgumentException since vectors only take one integer argument, not two Var arguments.

傲性难收 2024-09-03 20:39:21

-> 将 expr 作为第二个参数穿过表单。在您的情况下,最终扩展为:(partial ["1" "2"] apply str),创建基于向量的 parital 函数。

但是您想要调用基于线程表达式上的 apply 和 str 的 parital 函数,因此需要:

(-> ["1" "2"] ((partial apply str)))

嗯:这段代码非常令人困惑,而且不是惯用的 Clojure。

The Macro -> Threads the expr through the forms as second argument. In your case ends up in expanding to: (partial ["1" "2"] apply str), creating a parital function based on vector.

But you want to invoke a parital function based on apply and str on the threaded expr and thus need:

(-> ["1" "2"] ((partial apply str)))

Well: this code i quite confusing and not idiomatic Clojure.

水中月 2024-09-03 20:39:21

-> 宏在第二个版本中的 apply-str 周围添加了括号,这就是宏扩展为最终调用您的函数的代码的原因。查看->的源代码,您可以看到:

(defmacro ->
  "Threads the expr through the forms. Inserts x as the
  second item in the first form, making a list of it if it is not a
  list already. If there are more forms, inserts the first form as the
  second item in second form, etc."
  ([x] x)
  ([x form] (if (seq? form)
              (with-meta `(~(first form) ~x ~@(next form)) (meta form))
              (list form x)))
  ([x form & more] `(-> (-> ~x ~form) ~@more)))

相关部分是当它处理两个参数时,xform。如果 form 是一个 seq,则 x 将作为第二个参数插入到该列表中。否则,宏会将 formx 放入列表本身。这样您就可以使用一个裸符号作为包含一个符号的列表的简写。

user> (macroexpand '(-> 123 (foo)))
(foo 123)
user> (macroexpand '(-> 123 foo))
(foo 123)

The -> macro adds parens around apply-str in your second version, that's why the macro expands to code that ends up calling your function. Look at the source code for -> and you can see:

(defmacro ->
  "Threads the expr through the forms. Inserts x as the
  second item in the first form, making a list of it if it is not a
  list already. If there are more forms, inserts the first form as the
  second item in second form, etc."
  ([x] x)
  ([x form] (if (seq? form)
              (with-meta `(~(first form) ~x ~@(next form)) (meta form))
              (list form x)))
  ([x form & more] `(-> (-> ~x ~form) ~@more)))

The relevant part is when it's dealing with two arguments, x and form. If form is a seq, x is inserted as the second argument in that list. Otherwise, the macro puts form and x it into a list itself. This is so you can use a bare symbol as shorthand for a list containing one symbol.

user> (macroexpand '(-> 123 (foo)))
(foo 123)
user> (macroexpand '(-> 123 foo))
(foo 123)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文