Clojure映射函数以什么方式?

Arn*_*rne 5 function clojure

Rich Hickey 在他的演讲“也许不是”中指出:

映射是(数学)函数!

在Clojure中,我们可以直接编写并调用

({:a 1:b 2}:b)=> 2

但是我觉得它们实际上不是一流的Clojure函数,或者是吗?

我可以使用关键字或其他方式调用地图:

user=> (:b {:a 1 :b 2 :c 3})
2
user=> ({:a 1 :b 2 :c 3} :b)
2
Run Code Online (Sandbox Code Playgroud)

但是我似乎无法使用Apply的任何一种方式:

user=> (apply #(:b %) {:a 1 :b 2 :c 3})
ArityException Wrong number of args (3) passed to: user/eval1762/fn--1763  clojure.lang.AFn.throwArity (AFn.java:429)

user=> (apply #({:a 1 :b 2 :c 3} %) :b)
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword  clojure.lang.RT.seqFrom (RT.java:542)
Run Code Online (Sandbox Code Playgroud)

而且我也不能直接将关键字应用于地图:

user=> (apply {:a 1 :b 2 :c 3} :b)
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword  clojure.lang.RT.seqFrom (RT.java:542)
Run Code Online (Sandbox Code Playgroud)

那么,它们是仅在数学意义上起作用,还是在应用类似于“正常” clojure函数的关键字意义上发挥更多作用?

Tay*_*ood 9

就像您的前两个示例一样,映射键的功能。地图实现的IFn接口就像“常规” Clojure函数一样。

apply在您的示例中不起作用的原因是由于在第二个位置传递了“序列”参数。

(apply #(:b %) {:a 1 :b 2 :c 3})
Run Code Online (Sandbox Code Playgroud)

在该示例中,地图参数正在变成键/值矢量/元组序列,因此它们可以被施加#(:b %)(这不会无论如何工作,因为该匿名函数只需要一个参数)。这是地图变成序列并用作函数参数时的外观:

user=> (seq {:a 1 :b 2 :c 3})
([:a 1] [:b 2] [:c 3])
Run Code Online (Sandbox Code Playgroud)

第二个示例不起作用,因为:b它不是序列-它是一个关键字。这可以工作:

user=> (apply {:a 1 :b 2 :c 3} [:b])
2
Run Code Online (Sandbox Code Playgroud)

注意,使用apply和关键字序列调用map-as-function 并没有实际意义。


Thu*_*ail 8

数学函数是一组有序对,使得不存在明显的对与相同的第一元件。这样定义的数学函数仅需一个参数。

Clojure映射是不言而喻的数学函数,因为不存在具有相同键的不同键/值对。此外,Clojure映射具有有限域(的集合keys)和范围/共域(的集合values)。

正如@TaylorWood所说,Clojure映射是Clojure函数,因为它们实现了clojure.lang.IFn。他们这样做是因为运算符会产生给定键的值,因此与其对数学函数的解释一致。

您的apply语法错误。你可以写

user=> (apply {:a 1, :b 2} [:a])
1
Run Code Online (Sandbox Code Playgroud)

要么

user=> (apply {:a 1, :b 2} :a []) 
1
Run Code Online (Sandbox Code Playgroud)

您可以为该函数(的第一个参数apply)内联提供一些参数。其余部分是序列的最后一个参数apply。由于此处仅存在一个参数,因此我们可以在终端序列中将其内联或单独使用。

类似的考虑也适用于使用关键字作为参数。


回复@AlanThompson的评论

  1. 我已听过并阅读了该问题所指的Rich的演讲。我对函数的定义与他的一致。

  2. 我的说法如此定义的数学函数仅需一个参数”,这显然是正确的。

  3. 您可以争辩说,我的定义不是传统的定义。但是,那是错误的。如果您阅读了我们都引用的Wikipedia文章的Multivariate_function部分,则会发现

更正式地说,n个变量的函数是一个域为n个元组的函数

...

使用函数符号时,通常会省略元组周围的括号,f(x1 , x2)而不是f((x1 , x 2))

换句话说,(数学)函数采用多个参数的想法是一种无害的非正式性,允许使用更简单的表示法。

那把编程语言留在哪里呢?它们中的大多数都具有任意Arity的功能:对于Clojure而言,任何有限的Arity集,包括无限的Arity。

考虑Clojure函数的最简单方法是,它们采用内联参数序列,也许是空参数。可以用这种方式来表达数学函数:从事物序列到事物的映射。但这并没有完成