10

前段时间学习 Haskell,我爱上了 pointfree 表示法和特别方便的偏函数应用程序 - 只需提供你知道的 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

4 回答 4

7

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

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

相当于:

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

一个微小的区别是%它只意味着一个函数参数,在这种情况下是第一个也是唯一的。

于 2013-09-06T01:38:04.790 回答
5

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

鉴于你有一个功能

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

中定义myapp.coredata_readers.clj您可以在类路径顶部添加以下条目:

{p myapp.core/partial-wrap}

(通常应该在这里使用命名空间限定符号a/p,因为非限定符号是为 Clojure 保留的。尽管非限定符号确实有效,但您需要依赖 Clojure,而不是在未来的版本中覆盖它们)。

这最终允许做几乎你要求的事情:

(map (comp #p[+ 10] #p[* 2]) [1 2 3])
=> (12 14 16)
于 2013-09-06T11:35:50.220 回答
2

我找到了一种方法,可以在我的问题这样的情况下进行部分处理:(map #(+ 10 (* 2 %)) [1 2 3). 使用->>宏:(map #(->> % (* 2) (+ 10)) [1 2 3]. 类似的宏是->..并且doto适用于不同的情况。

于 2013-09-11T20:20:11.450 回答
0

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

syntax keyword clojureFunc partial conceal cchar=$

这会缩短partial读者和作者的屏幕显示时间,但不会给其他人造成混乱。

我使用这个技巧在大多数语言中制作速记符号(例如,匿名函数关键字——fn、lambda 等等——在许多语言中隐藏在希腊字母 lambda 中)。

于 2020-01-23T03:45:31.113 回答