Clojure 학습 5부: 로봇 공장

17570 단어 tutorialclojure
이전 4개 파트에서 우리는 많은 것을 배웠습니다. 이제 조금 더 큰 일을 하고 그 과정에서 새로운 것을 배울 시간입니다.
작은 로봇 조립 공장이 있다고 가정해 봅시다. 우리는 중국에서 모든 부품을 주문하고 있습니다. 쌍으로 제공되는 부품(눈, 손, 다리 등..)이 왼쪽 변형만 주문하는 것이 더 쉽고 저렴하다는 것을 알게 되었고 일치하는 오른쪽 부품을 자체적으로 만듭니다.

올바른 부품을 만드는 코드는 여기에서 우리의 첫 번째 목표입니다.

다음과 같은 부품을 받습니다.

(def robot-parts [
 {:name "head" :price 50}
 {:name "left-eye" :price 15}
 {:name "neck" :price 10}
 {:name "left-hand" :price 20}
 {:name "torso" :price 50}
 {:name "left-leg" :price 20}
])


맵의 벡터이며 각 맵에는 부품 이름과 목표 가격이 있습니다. 나중에 우리는 비용을 계산하기 위해 가격을 합산할 것입니다.

로봇 완성



가장 먼저 해야 할 일은 왼쪽 부분에서 오른쪽 부분을 만드는 것입니다.
다음과 같은 간단한 함수를 만들어 보겠습니다.

(defn make-right-part
 [left-part]
 {
 :name (clojure.string/replace (:name left-part) #"^left-" "right-")
 :price (:price left-part)
 }
)


정규식



여기에서 정규 표현식을 사용했음을 주목하십시오. Clojure 정규식은 다른 언어의 정규식과 거의 유사하게 작동합니다. 정규식 표기법은

#"regular-expression"

re-find 함수를 사용하여 약간의 플레이를 할 수 있습니다.

(re-find #"^left-" "left-eye")
;=> "left-"

(re-find #"^left-" "head")
;=> nil


표현식을 사용하면 "right-eye" 입력에 대해 "left-eye"를 출력하고 왼쪽으로 시작하지 않는 기타 문자열은 그대로 반환됩니다.

(make-right-part {:name "left-hand" :price 1})
;=> {:name "right-hand", :price 1}

(make-right-part {:name "right-hand" :price 1})
;=> {:name "right-hand", :price 1}


확인. 이제 왼쪽 부분에서 오른쪽 부분을 만들 수 있습니다. 로봇을 완성하는 함수를 만들 수 있습니다.

(defn complete-robot
 [parts]
 (loop [remaining parts final []]
 (if (empty? remaining)
 final
 (let [[part & rest] remaining]
 (recur rest (into final (set [part (make-right-part part)]))) 
 )
 )

 )
)


으악. 여기에 새로운 것들이 많이 있습니다. 해보자.

고리



전체 함수의 본체로 loop 함수를 사용하고 있습니다. 루프는 다른 언어의 루프와 다르게 동작합니다. 루프는 재귀를 작성하는 또 다른 방법입니다.

간단한 루프 예제를 수행해 보겠습니다.

(loop [i 0]
 (println (str "i=" i))
 (if (> i 2)
 (println "END")
 (recur (inc i))
 )
)
;i=0
;i=1
;i=2
;i=3
;END


분해해 봅시다. 첫 번째 줄은 루프를 시작하고 초기 값과 함께 i 변수를 도입합니다. 여기서 더 많은 변수를 소개할 수 있습니다.
두 번째 줄은 루프의 본문입니다. 이것이 각 반복마다 수행될 작업입니다. 세 번째 줄은 루프를 종료해야 할 때 루프를 중단하는 조건입니다. 조건의 else 부분에서 recur 함수를 호출합니다. 즉, 루프에 다음 라운드를 수행하도록 지시하고(재귀 계속) 여기에 새 속성 값을 제공합니다.

허락하다



퍼즐의 또 다른 새로운 조각은 let 입니다. 새 범위를 설정하고 값을 이름에 바인딩합니다. 함수에서 할 수 있는 것과 동일한 트릭을 인수에 사용할 수 있습니다.

(let [i 42] i)
;=> 42

(def characters ["Darth Vader" "Yoda" "Obi-Wan"])
(let [[main & rest] characters]
 (str "Main character is " main " rest are " rest)
)
;=> "Main character is Darth Vader rest are (\"Yoda\" \"Obi-Wan\")"


줄이다



지금 우리는 모든 부품을 설명했고 로봇을 완성하기 위한 우리의 기능이 작동합니다.

(complete-robot robot-parts)
;[{:name "head", :price 50}
;{:name "right-eye", :price 15}
;{:name "left-eye", :price 15}
;{:name "neck", :price 10}
;{:name "left-hand", :price 20}
;{:name "right-hand", :price 20}
;{:name "torso", :price 50}
;{:name "right-leg", :price 20}
;{:name "left-leg", :price 20}]


우리가 작성한 코드(시퀀스의 각 요소를 처리하고 결과를 빌드)는 reduce라는 패턴이며 Clojure에는 이에 대한 내장 함수가 있습니다.

간단한 감소 예는 다음과 같습니다.

(reduce + [1 2 3 4 5 6 7 8 9 10])
;=> 55

reduce는 다음과 같이 작동합니다.
  • 제공된 기능을 첫 번째 요소에 적용
  • 결과 및 다음 요소에 함수 적용
  • 요소가 생길 때까지 반복합니다.

  • 선택적 초기 값을 사용할 수도 있습니다.

    (reduce + 10 [1 2 3 4 5 6 7 8 9 10])
    ;=> 65
    

    reduce를 사용하여 전체 로봇 기능의 코드를 줄일 수 있습니다.

    (defn complete-robot
     [parts]
     (reduce
     (fn [final part] (into final (set [part (make-right-part part)])))
     []
     parts
     )
    )
    


    비용 계산



    이제 부품 목록을 가져오는 함수를 만들어 보겠습니다. 맞는 부품을 만듭니다.
    그리고 모든 비용을 요약합니다.

    (defn bill-robot
     [parts]
     (reduce 
     (fn [sum part] (+ sum (:price part)))
     0
     (complete-robot parts)
     )
    )
    
    (bill-robot robot-parts)
    ;=> 220
    


    예. reduce 패턴의 또 다른 예입니다.

    이것은 우리가 Clojure와 함께 작업하는 데 필요한 모든 요소를 ​​알고 있는 부분으로 안내합니다. 다음 시간에는 핵심 Clojure 기능에 대해 알아보겠습니다.


    저를 팔로우하시면 이와 같은 더 많은 콘텐츠를 얻을 수 있습니다.

    좋은 웹페이지 즐겨찾기