【问题标题】:Clojure operators in higher-order functions高阶函数中的 Clojure 运算符
【发布时间】:2019-09-06 22:37:26
【问题描述】:

我整理了一个高阶函数,在某些情况下调用函数参数,但根据函数的不同,它似乎有不同的效果。我能够通过一个简单的函数重现相同的行为:

(defn foo [f a b] (f a b))

对于“正常”功能,它可以正常工作:

user=> (foo list 2 3)
(2 3)
user=> (foo cons 1 '(2 3))
(1 2 3)
user=> (foo println 2 3)
2 3
nil

但是对于操作符来说,它没有,它似乎只是返回了最后一个元素:

user=> (foo '+ 2 3)
3
user=> (foo '* 2 3)
3
user=> (foo '- 2 3)
3

为什么会这样?

【问题讨论】:

  • 作为一个有趣的事实,为什么“它似乎只是返回最后一个元素”,请参阅here(给定的第二个参数是默认值,它是默认值)。我不知道您为什么需要这样做,但它可以让您执行类似 ('+ {'+ 2}) 的操作返回 2。
  • @Carcigenicate 当然,出于同样的原因,您希望对关键字执行此操作。有时,无论出于何种原因(例如,实现解释器时的词法环境),您可能只是有一个以符号为键的映射,并且希望能够使用符号作为函数来查找自己并不疯狂。
  • @amalloy 是的。我只是认为我从来没有需要进行这样的查找。

标签: clojure


【解决方案1】:
user=> (foo '+ 2 3)
3

为什么会这样?

当您需要 + 函数值本身时,

'(或 quote)正在创建+符号https://clojure.org/guides/weird_characters#_quote

(quote foo) => foo ;; symbol
'foo => foo ;; symbol

所以总是返回第二个参数的行为来自符号(如关键字)也充当函数的事实,通常用作关联结构(如映射)上get 的简写,因此它们在功能上是等效的:

('foo 1 2) => 2
(get 1 'foo 2) => 2

当在关联结构中找不到键时,2 恰好位于用于 默认 值的位置。

如果您有一个带有符号键的地图,这将很有用,就像关键字一样:

('foo {'foo 1}) => 1
({'foo 1} 'foo) => 1
('foo {'bar 1} 2) => 2

【讨论】:

  • 疯了!我从来没有听说过这个。我会认为它是“陷阱”而不是“功能”。
【解决方案2】:

在 clojure 中,像 + 这样的“运算符”只是普通函数。不要使用单引号,它会正常工作。

(ns tst.demo.core
  (:use tupelo.core tupelo.test))

(defn foo [f a b] (f a b))

(dotest
  (spyx (foo list 2 3))
  (spyx (foo println 2 3))
  (spyx (foo + 2 3))
  (spyx (foo * 2 3))
  (spyx (foo - 2 3)) )

结果:

(foo list 2 3) => (2 3)

2 3                        ; result of (println 2 3)
(foo println 2 3) => nil   ; println always returns `nil`

(foo + 2 3) => 5
(foo * 2 3) => 6
(foo - 2 3) => -1

辅助函数spyx 只是打印一个表达式,然后是它的值。

【讨论】:

    猜你喜欢
    • 2011-07-16
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    相关资源
    最近更新 更多