如何读心理Lisp / Clojure代码 [英] How to read mentally Lisp/Clojure code

查看:72
本文介绍了如何读心理Lisp / Clojure代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

非常感谢所有美丽的答案!

p>我是功能编程的新手,虽然我可以读取功能编程中的简单功能,例如计算一个数的阶乘,我发现很难读大功能。
部分原因是因为我无法弄清楚函数定义中较小的代码块,也部分是因为我很难匹配()在代码中。



如果有人可以带我阅读一些代码,并给我一些如何快速解密一些代码的提示,这将是巨大的。



注意:我可以理解这段代码,如果我盯着它10分钟,但我怀疑,如果这个代码是用Java写的,我10分钟。所以,我觉得在Lisp风格的代码感觉舒适,我必须做的更快



注意:我知道这是一个主观的问题。我不是在这里寻求任何可证明正确的答案。

 (defn concat 
([](lazy-seq nil))
([x](lazy-seq x))
([xy]
(lazy-seq
s(seq x)]
(如果s
(如果(chunked-seq?s)
(chunk-cons(chunk-first s) )
(cons(first s)(concat(rest s)y)))
y))))
([xy& zs]
cat [xys zs]
(lazy-seq
(let [xys(seq xys)]
(if xys
(if(chunked-seq?xys)
(chunk-first xys)
(cat(chunk-rest xys)zs))
(cons(first xys)(cat(rest xys)zs)))
当zs
(cat(第一个zs)(下一个zs)))))))]
(cat(concat xy)zs)))


解决方案

由于常规语法,Lisp代码甚至比其他函数式语言更难阅读。 Wojciech给了一个好的答案,以提高你的语义理解。这里是一些语法帮助。



首先,在阅读代码时,不要担心括号。担心缩进。一般规则是相同缩进级别的事物是相关的。所以:

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

其次,如果你不能把一切都放在一行,缩进下一行一小部分。这几乎总是有两个空格:

 (defn concat 
(lazy -seq nil));这两个符合
([x](lazy-seq x));所以没有包裹
([xy];但是这里
(lazy-seq; -seq缩进两个空格
(let [s(seq x)]; as(let [s(seq x)]

第三,如果一个函数的多个参数不能在一行上排列,请在第一个开始括号下面排列第二个,第三个等参数,许多宏都有类似的规则,允许重要部分先显示。

 ;适合一行
(chunk-cons (chunk-first xys)
(chunk-first xys)

(b)如果你写一个C-for宏,把前三个参数放在一行$ b(b)(b)(b)(b)(b)(b) $ b;那么剩余缩进两个空格
(c-for(i 0)((副作用!)
$ b(get-your(side-effects!)here))






这些规则帮助你在代码中找到块:如果你看到

 (chunk-cons s)

不要计算括号!检查下一行:

 (chunk-cons s)
(concat(chunk-rest s)y))

你知道第一行不是一个完整的表达式,因为下一行在它下面缩进。



如果你从上面看到 defn concat ,你就知道你有三个块,因为同一层有三个东西,



以下是Scheme 的样式指南。我不知道Clojure,但大多数规则应该是相同的,因为没有其他Lisps变化很大。


Thanks a lot for all the beautiful answers! Cannot mark just one as correct

Note: Already a wiki

I am new to functional programming and while I can read simple functions in Functional programming, for e.g. computing the factorial of a number, I am finding it hard to read big functions. Part of the reason is I think because of my inability to figure out the smaller blocks of code within a function definition and also partly because it is becoming difficult for me to match ( ) in code.

It would be great if someone could walk me through reading some code and give me some tips on how to quickly decipher some code.

Note: I can understand this code if I stare at it for 10 minutes, but I doubt if this same code had been written in Java, it would take me 10 minutes. So, I think to feel comfortable in Lisp style code, I must do it faster

Note: I know this is a subjective question. And I am not seeking any provably correct answer here. Just comments on how you go about reading this code, would be welcome and highly helpful

(defn concat
  ([] (lazy-seq nil))
  ([x] (lazy-seq x))
  ([x y]
    (lazy-seq
      (let [s (seq x)]
        (if s
          (if (chunked-seq? s)
            (chunk-cons (chunk-first s) (concat (chunk-rest s) y))
            (cons (first s) (concat (rest s) y)))
          y))))
  ([x y & zs]
     (let [cat (fn cat [xys zs]
                 (lazy-seq
                   (let [xys (seq xys)]
                     (if xys
                       (if (chunked-seq? xys)
                         (chunk-cons (chunk-first xys)
                                     (cat (chunk-rest xys) zs))
                         (cons (first xys) (cat (rest xys) zs)))
                       (when zs
                         (cat (first zs) (next zs)))))))]
       (cat (concat x y) zs))))

解决方案

Lisp code, in particular, is even harder to read than other functional languages because of the regular syntax. Wojciech gives a good answer for improving your semantic understanding. Here is some help on syntax.

First, when reading code, don't worry about parentheses. Worry about indentation. The general rule is that things at the same indent level are related. So:

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

Second, if you can't fit everything on one line, indent the next line a small amount. This is almost always two spaces:

(defn concat
  ([] (lazy-seq nil))  ; these two fit
  ([x] (lazy-seq x))   ; so no wrapping
  ([x y]               ; but here
    (lazy-seq          ; (lazy-seq indents two spaces
      (let [s (seq x)] ; as does (let [s (seq x)]

Third, if multiple arguments to a function can't fit on a single line, line up the second, third, etc arguments underneath the first's starting parenthesis. Many macros have a similar rule with variations to allow the important parts to appear first.

; fits on one line
(chunk-cons (chunk-first s) (concat (chunk-rest s) y))

; has to wrap: line up (cat ...) underneath first ( of (chunk-first xys)
                     (chunk-cons (chunk-first xys)
                                 (cat (chunk-rest xys) zs))

; if you write a C-for macro, put the first three arguments on one line
; then the rest indented two spaces
(c-for (i 0) (< i 100) (add1 i)
  (side-effects!)
  (side-effects!)
  (get-your (side-effects!) here))


These rules help you find blocks within the code: if you see

(chunk-cons (chunk-first s)

Don't count parentheses! Check the next line:

(chunk-cons (chunk-first s)
            (concat (chunk-rest s) y))

You know that the first line is not a complete expression because the next line is indented beneath it.

If you see the defn concat from above, you know you have three blocks, because there are three things on the same level. But everything below the third line is indented beneath it, so the rest belongs to that third block.

Here is a style guide for Scheme. I don't know Clojure, but most of the rules should be the same since none of the other Lisps vary much.

这篇关于如何读心理Lisp / Clojure代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆