읽을 수있는 Clojure 코드를 작성하는 방법?


13

Clojure를 처음 사용합니다. 작성한 코드를 이해할 수 있지만 나중에 이해하기가 너무 어려워집니다.
괄호를 일치시키기가 어렵습니다.

다양한 상황에서 명명 규칙 및 들여 쓰기와 관련하여 따라야 할 일반적인 규칙은 무엇입니까?

예를 들어 이해하기 위해 샘플 구조 해제 예제를 작성했지만 두 번째로 완전히 읽을 수없는 것처럼 보입니다.

(defn f [{x :x y :y z :z [a b c] :coll}] (print x " " y  " " z " " a " " b " " c)) 

구조 해제의 경우 매개 변수 수준에서 직접 수행하거나 let 양식을 시작한 다음 계속 진행하는 것이 더 낫습니까?


3
스택 오버플로의 가독성에 대한 좋은 대답이 있습니다. 당신은 그것을 확인할 수 있습니다. stackoverflow.com/a/1894891/1969106
yfklon

2
읽을 수있는 Lisp 코드를 작성하는 것은 일반적으로 어렵습니다. 그들은 "불필요한 괄호 안에 잃어버린"(Lost In Superfluous Parenthesis)이라는 백론을 발명했다.
메이슨 휠러

답변:


23

명명 규칙

  • 함수를 소문자로 유지
  • 사용 -(다른 언어 밑줄이나 낙타의 경우 일 것입니다 무슨) 하이픈.

    (defn add-one [i] (inc i))

  • 술어 (즉, true 또는 false를 리턴하는 함수)는 ? 예제로 끝납니다 .odd? even? nil? empty?

  • 상태 변경 절차는로 끝납니다 !. 당신은 기억 set!나요? 또는swap!

  • 도달 범위에 따라 짧은 가변 이름 길이를 선택하십시오. 즉, 보조 변수가 매우 작은 경우 종종 한 글자로 된 이름 만 사용할 수 있습니다. (map (fn [[k v]] (inc v)) {:test 4 :blub 5})필요에 따라 더 긴 변수 이름을 선택하십시오. 특히 많은 코드 행에 사용되며 목적을 즉시 추측 할 수없는 경우 더욱 그렇습니다. (나의 의견).

    저는 많은 클로저 프로그래머들이 일반적인 이름과 짧은 이름을 사용하는 경향이 있다고 생각합니다. 그러나 이것은 물론 객관적인 관찰이 아닙니다. 요점은 많은 클로저 함수가 실제로 매우 일반적이라는 것입니다.

람다 함수

  • 실제로 람다 함수의 이름을 지정할 수 있습니다. 이것은 디버깅 및 프로파일 링에 편리합니다 (여기서 ClojureScript 사용 경험).

    (fn square-em [[k v]] {k (* v v)})

  • #()편리한 인라인 람다 함수 사용

공백

  • Parens 전용 행이 없어야합니다. 즉, 괄호를 즉시 닫습니다. 편집자와 컴파일러를위한 parens가 있다는 것을 기억하십시오. 들여 쓰기는 당신을위한 것입니다.

  • 함수 매개 변수 목록이 새 줄로 이동

   (정의 단점
     [ab]
     (목록 ab))

doc 문자열에 대해 생각하면 의미가 있습니다. 함수 이름과 매개 변수 사이에 있습니다. 다음 doc 문자열은 아마 가장 현명하지 않습니다.)

   (정의 단점
     "물건 꾸미기"
     [ab]
     (목록 ab))
  • 페어링을 유지하는 한 페어링 된 데이터를 새 줄로 분리 할 수 ​​있습니다.
  (정의 f 
    [{x : x 
      y : y 
      z : z  
      [abc] : coll}] 
    (인쇄 x ""y ""z ""a ""b ""c)) 

(원하는 ,대로 입력 할 수도 있지만이 방법은 독특합니다.)

  • 들여 쓰기를 위해 충분히 좋은 편집기를 사용하십시오. 몇 년 전에 이것은 lisp 편집을위한 이맥스였으며, vim도 오늘 훌륭합니다. 일반적인 clojure IDE도이 기능을 제공해야합니다. 임의의 텍스트 편집기를 사용하지 마십시오.

    명령 모드의 vim에서는 명령을 사용하여 =제대로 들여 쓸 수 있습니다 .

  • 명령이 너무 길어지면 (중첩 등) 첫 번째 인수 뒤에 줄 바꿈을 삽입 할 수 있습니다. 이제 다음 코드는 의미가 없지만 식을 그룹화하고 들여 쓰는 방법을 보여줍니다.

(+ (if-let [나이 (: 개인 연령 콜)]
     (만 18 세 이상인 경우)
       나이
       0))
   (개수 (범위 (-3b))
                 (감소 + 
                         (범위 b 10)))))

들여 쓰기가 잘되어 있으면 대괄호를 세지 않아도됩니다. 괄호는 컴퓨터 용입니다 (소스 코드를 해석하고 들여 쓰기). 들여 쓰기는 쉽게 이해하기위한 것입니다.

고차 함수 대 fordoseq형태

Scheme 배경에서 왔을 때 나는 이해 map하고 람다 함수 등을 알게 된 것을 자랑스럽게 생각했습니다 .

(map (fn [[k x]] (+ x (k data))) {:a 10 :b 20 :c 30})

이것은 읽기가 매우 어렵습니다. for형태는 방법 좋네요 :

(for [[k x] {:a 10 :b 20 :c30}]
  (+ x (k data)))

`map은 많은 용도를 가지고 있으며 명명 된 함수를 사용한다면 정말 좋습니다. 즉

(map inc [12 30 10]

(map count [[10 20 23] [1 2 3 4 5] (range 5)])

스레딩 매크로 사용

스레딩 매크로 사용 ->->>뿐만 아니라 doto경우에 적용한다.

요점은 스레딩 매크로가 소스 코드를 함수 구성보다 선형으로 보이게한다는 것입니다. 다음 코드는 스레딩 매크로없이 읽을 수 없습니다.

   (f (g (h 3) 10) [10 3 2 3])

~와 비교하다

   (-> 
     (h 3)
     (g 10)
     (f [10 3 2 3]))

스레딩 매크로를 사용하면 일반적으로 한 번만 사용되는 임시 변수를 피할 수 있습니다.

다른 것들

  • 문서화 문자열 사용
  • 기능을 짧게 유지
  • 다른 클로저 코드 읽기

디스트 럭처링 기능은 들여 쓰기로 아름답게 보입니다!
Amogh Talpallikar

기능을 짧게 유지하려면 +1입니다. 많은 작은 기능들이 훨씬 더 자기 문서화입니다
Daniel Gratzer

1
나는 강하게 조차 "짧은 도달"기능에, 짧은 변수 이름을 사용하는 좋은 아이디어 있다고 동의하지 않는다. 좋은 변수 이름은 가독성에 중요하며 키 입력을 제외하고 비용이 들지 않습니다. 이것은 Clojure 커뮤니티에 대해 가장 귀찮게하는 것 중 하나입니다. 설명 변수 이름에 거의 적대적인 저항을 가진 사람들이 많이 있습니다. Clojure 코어에는 함수 인수에 대한 1 글자 변수 이름이 포함되어있어 언어를 배우기가 훨씬 어렵습니다 (예 : 실행 중 doc또는 sourceREPL에서). 탁월한 답변을위한 맹렬한 종말
Nathan Wallace

@NathanWallace 나는 당신과 동의하지만 어떤 측면에서는 그렇지 않습니다. 긴 이름은 때때로 기능을 지나치게 구체적으로 만드는 경향이 있습니다. 따라서 일부 일반적인 필터 작업은 실제로 일반적인 반면 인수가 apples대신에 xs사과에 대한 것이라고 생각할 수 있습니다. 그런 다음 함수 인수 이름이 for 루프 변수보다 더 도달하는 것으로 간주합니다. 필요한 경우 더 오래 가질 수 있습니다. 마지막 생각으로 : "이름 코드 값이 아님" concatenative.org/wiki/view/Concatenative%20language/…
wirrbel

개인 대 공용 인터페이스와 같은 단락을 추가 할 수 있습니다. 특히 도서관에 관해서. 그것은 충분히 이야기되지 않은 코드 품질의 한 측면이며 그 대답을 작성한 이후로 이것에 대해 많은 것을 배웠습니다.
wirrbel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.