Clojure中部分的简明语法

时间:2013-09-06 01:06:56

标签: clojure pointfree partial-application

前一段时间学习Haskell,我感觉爱上了无点符号,特别方便的部分功能应用 - 只需提供你知道的args。在Clojure中,我一直有partial。我认为在阅读器中使用特殊语法会很好。

查看示例代码:

; Notation with points:
(map (+ 10 (* % 2)) [1 2 3])

; With partial:
(map (comp (partial + 10) (partial * 2)) [1 2 3])

; Let #[] syntax means partial application in reader:
(map (comp #[+ 10] #[* 2]) [1 2 3])

这太好了!有这样的事吗?是否有可能定义自定义阅读器宏?

4 个答案:

答案 0 :(得分:6)

匿名函数语法#(...)可以与您尝试执行的操作类似地使用:

user=> (map (comp (partial + 10) (partial * 2)) [1 2 3])
(12 14 16) 

相当于:

user=> (map (comp #(+ 10 %) #(* 2 %)) [1 2 3])
(12 14 16)

微小的差别是%,这只是一个函数参数,在这种情况下是第一个和唯一的。

答案 1 :(得分:5)

我非常喜欢你使用#[]文字的部分函数表示法的想法。 不幸的是,Clojure不允许我们直接增强#()表示法,但我们可以为部分应用程序定义一个像#p这样的宏。

鉴于你有一个功能

(defn partial-wrap
  [args]
  (concat '(partial) args))

myapp.core中定义。 您可以将以下条目添加到类路径顶部的data_readers.clj中:

{p myapp.core/partial-wrap}

(通常应该使用名称空间限定符号,例如a/p,因为不合格的符号是为Clojure保留的。但是不合格的符号确实有用,你需要依赖Clojure在未来的版本中不覆盖它们。) / p>

这最终几乎可以满足您的要求:

(map (comp #p[+ 10] #p[* 2]) [1 2 3])
=> (12 14 16)

答案 2 :(得分:2)

我发现了一种在我的问题中有部分情况的方法:(map #(+ 10 (* 2 %)) [1 2 3)。使用->>宏:(map #(->> % (* 2) (+ 10)) [1 2 3]。类似的宏->..doto适用于不同的情况。

答案 3 :(得分:0)

如果您在vim中编写代码,请将以下代码放在等效于~/.vim/after/syntax/clojure.vim的位置,然后通过将conceallevel设置为2来隐藏:

syntax keyword clojureFunc partial conceal cchar=$

这会缩短阅读器和写入器在屏幕上的partial,但不会给其他人带来麻烦。

我使用此技巧在大多数语言中创建速记符号(例如,在许多语言中,希腊字母lambda都隐含了匿名函数关键字-fn,lambda等)。