【问题标题】:Concise syntax for partial in ClojureClojure 中 partial 的简洁语法
【发布时间】:2013-09-06 01:06:55
【问题描述】:

前段时间学习 Haskell,我爱上了 pointfree 表示法和特别方便的偏函数应用程序 - 只需提供你知道的 args。在 Clojure 中,我一直有 partial。我认为有一个用于部分 in reader 的特殊语法会很好。

看示例代码:

; 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])

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

【问题讨论】:

  • *Pointfree notation :) Pointless notation 有不同的含义
  • @demi:你应该试着编辑你的问题,让它更客观一点,少一点关于“好”和“好”的问题。我觉得你的问题很有趣(因为我对 Clojure 知之甚少,但我知道它缺少读取宏,例如,用 Common Lisp 编写类似的东西),但它太自以为是了。在我写这篇文章的那一刻,已经有 2 票赞成关闭它,所以请注意。

标签: clojure pointfree partial-application


【解决方案1】:

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

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

相当于:

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

% 有一点点区别,它只是一个函数参数,在这种情况下是第一个也是唯一一个。

【讨论】:

  • 如果有多个参数,差异不会那么小。或者如果它们的数量在开发过程中发生变化。
  • 这是真的。以上只是为了说明单参数函数。要“玩”真实的东西(应用 .. %&),here 是调整 Clojure [代码] 的危险示例,而 here 是一个更温和的示例 [宏]。
  • @tolitius 哦,哇!我需要这个指向 Disclojure 的链接。我很自豪 Sean 决定使用我提出的相同语法。
  • @demi 是不是有点矫枉过正。如果您的目标是更简洁,为什么不直接定义宏,比如将$ 扩展为partial?然后你可以写($ + a b ...),所以使用宏只需要3个字符,就像你想要的那样。
【解决方案2】:

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

假设你有一个函数

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

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

{p myapp.core/partial-wrap}

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

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

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

【讨论】:

  • 虽然它确实有几个缺点(没有命名空间的“p”和“#p[”是“读取绊脚石”),但演示data_readers.clj的用法真的很酷。跨度>
  • 如果有partial 和comp 的速记符号就好了。例如。 #[] for comp 像 #[inc second vector] 和 ~[] for partial,所以可以做 #[~[+ 10] ~[* 2]]。我的代码库充满了窃取位置的部分内容。
  • “增强”读者的主要作用是不要用这些def compose[G[_]](implicit G0: Foldable[G]): Foldable[({type λ[α] = F[G[α]]})#λ]... :)
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    syntax keyword clojureFunc partial conceal cchar=$
    

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

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

    【讨论】:

      猜你喜欢
      • 2020-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      相关资源
      最近更新 更多