如何使clojure程序结构更容易识别?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使clojure程序结构更容易识别?相关的知识,希望对你有一定的参考价值。

作为Lisp方言的Clojure继承了Lisp的同音性。同源性使元编程更容易,因为代码可以被视为数据:语言中的反射(在运行时检查程序的实体)依赖于单个同构结构,并且它不必处理复杂语法中出现的几种不同结构[1]

更加同质的语言结构的缺点是语言结构(例如循环,嵌套ifs,函数调用或开关等)彼此更相似。

在clojure中:

   ;; if:
   (if (chunked-seq? s)
     (chunk-cons (chunk-first s) (concat (chunk-rest s) y))
     (cons (first s) (concat (rest s) y)))

   ;; function call:
   (repaint (chunked-seq? s)
     (chunk-cons (chunk-first s) (concat (chunk-rest s) y))
     (cons (first s) (concat (rest s) y)))

两个结构之间的区别只是一个词。用非同性语言:

// if:
if (chunked-seq?(s))
    chunk-cons(chunk-first(s), concat(chunk-rest(s), y));
else
   cons(first(s), concat(rest(s), y));

// function call:
repaint(chunked-seq?(s),
        chunk-cons(chunk-first(s), concat(chunk-rest(s), y)),
        cons(first(s), concat(rest(s), y));

有没有办法让这些程序结构在Clojure中更容易识别(更显眼)?也许一些推荐的代码格式或最佳实践?

答案

除了使用支持不同情况的语法突出显示的IDE之外,没有,实际上没有办法在代码本身区分它们。

您可以尝试使用格式来区分函数调用和宏:

(for [a b]
  [a a])

(some-func [a b] [a a])

但是那会妨碍你使用for使用单行列表理解;有时它们可​​以整齐地放在一条线上。这也可以防止您将大型函数调用分解为多行。除非预先定义了还原功能,否则我对reduce的大多数调用采用以下形式:

(reduce (fn [a b] ...)
        starting-acc
        coll)

有太多场景试图限制调用格式的方式。那些像cond这样更复杂的宏呢?

我认为要理解的关键是表单的操作完全取决于表单中的第一个符号。而不是依靠特殊的语法来区分它们,训练你的眼睛捕捉到表格中的第一个符号,并在你的头脑中快速“查找”。

实际上,只有少数情况需要考虑:

  • iflet(实际上是let*)这样的特殊形式。这些是语言的基本结构,因此您将不断地接触它们。 我不认为这些会造成问题。当你看到if时,你的大脑应该立即知道发生了什么。 There are so few special forms认为普通记忆是最好的路线。
  • 具有“不寻常”行为的宏,如线程宏和cond。在某些情况下,我会查看某人的代码,并且因为他们使用的是我不太熟悉的宏,所以我需要花一点时间来弄清楚代码的流程。 这可以通过对宏进行一些练习来解决。无论如何,学习一个新的宏可以在编写Clojure时扩展你的能力,所以应该始终考虑这一点。与特殊形式一样,实际上没有那么多令人费解的宏,所以记住主要的宏(基本的线程宏和条件宏)很简单。
  • 功能。如果它不是上述任何一个,它必须是一个函数并遵循典型的函数调用语法。

以上是关于如何使clojure程序结构更容易识别?的主要内容,如果未能解决你的问题,请参考以下文章

关于如何构建 Go 代码的思考

VS2015 代码片段整理

如何编写宏使跨平台编译更容易? [复制]

如何使查询和php值更容易获得?

我如何帮助 Clojure 理解 0 是最小的自然数?

重构——程序猿的艺术