[function] Clojure에서 함수 인수에 대한 기본값을 작성하는 방법

나는 이것과 함께 온다 :

(문자열 정의-> 정수 [str & [base]]
  (정수 / 분석 구문 (if (nil? base) 10 base)))

(문자열-> 정수 "10")
(문자열-> 정수 "FF"16)

그러나이를 수행하는 더 좋은 방법이어야합니다.



답변

서명이 서로 다른 경우 함수는 여러 서명을 가질 수 있습니다. 이를 사용하여 기본값을 제공 할 수 있습니다.

(defn string->integer 
  ([s] (string->integer s 10))
  ([s base] (Integer/parseInt s base)))

가정 false하고 nil둘 다 값이 아닌 것으로 간주 하면을 (if (nil? base) 10 base)단축하거나을 (if base base 10)더 단축 할 수 있습니다 (or base 10).


답변

restClojure 1.2 [ ref ] 이후로 인수를 맵으로 재구성 할 수도 있습니다 . 이를 통해 함수 인수의 이름을 지정하고 기본값을 제공 할 수 있습니다.

(defn string->integer [s & {:keys [base] :or {base 10}}]
    (Integer/parseInt s base))

이제 전화 할 수 있습니다

(string->integer "11")
=> 11

또는

(string->integer "11" :base 8)
=> 9

https://github.com/Raynes/clavatar/blob/master/src/clavatar/core.clj (예 🙂 에서이를 확인할 수 있습니다.


답변

이 솔루션은 원래 솔루션정신에 더 가깝지만 조금 더 깨끗합니다.

(defn string->integer [str & [base]]
  (Integer/parseInt str (or base 10)))

유사한 패턴 편리한 사용을 할 수 있습니다 or와 함께let

(defn string->integer [str & [base]]
  (let [base (or base 10)]
    (Integer/parseInt str base)))

이 경우 더 자세한 정보를 제공하지만 다른 입력 값에 따라 기본값 을 설정하려는 경우 유용 할 수 있습니다 . 예를 들어 다음 기능을 고려하십시오.

(defn exemplar [a & [b c]]
  (let [b (or b 5)
        c (or c (* 7 b))]
    ;; or whatever yer actual code might be...
    (println a b c)))

(exemplar 3) => 3 5 35

이 접근법은 M. Gilliar의 솔루션에서 와 같이 명명 된 인수 로 작업하도록 쉽게 확장 할 수 있습니다 .

(defn exemplar [a & {:keys [b c]}]
  (let [b (or b 5)
        c (or c (* 7 b))]
    (println a b c)))

또는 더 많은 융합을 사용하십시오.

(defn exemplar [a & {:keys [b c] :or {b 5}}]
  (let [c (or c (* 7 b))]
    (println a b c)))


답변

고려해야 할 또 다른 접근법이 있습니다 : 부분 함수. 이것들은 아마도 기능에 대한 기본값을 지정하는 더 “기능적”이고 더 유연한 방법입니다.

필요한 경우 기본 매개 변수로 제공하려는 매개 변수가있는 함수를 작성하여 (필요한 경우) 시작하십시오.

(defn string->integer [base str]
  (Integer/parseInt str base))

Clojure의 버전 partial에서는 함수 정의에 나타나는 순서대로 “기본”값을 제공 할 수 있기 때문에 수행 됩니다. 원하는대로 매개 변수를 주문한 후 함수를 사용하여 “기본”버전의 함수를 작성할 수 있습니다 partial.

(partial string->integer 10)

이 함수를 여러 번 호출 할 수있게하려면 다음을 사용하여 var에 넣을 수 있습니다 def.

(def decimal (partial string->integer 10))
(decimal "10")
;10

다음을 사용하여 “로컬 기본값”을 만들 수도 있습니다 let.

(let [hex (partial string->integer 16)]
  (* (hex "FF") (hex "AA")))
;43350

부분 함수 접근 방식은 다른 함수에 비해 한 가지 중요한 이점이 있습니다. 함수 소비자 는 함수 정의를 수정하지 않고도 함수 생성자 대신 기본값을 결정할 수 있습니다 . 이것은 기본 기능 이 내가 원하는 것이 아니라고 결정한 예제와 함께 설명됩니다 .hexdecimal

이 접근 방식의 또 다른 장점은 기본 기능에 더 설명적이고 다른 범위 (var, local) 일 수있는 다른 이름 (10 진수, 16 진수 등)을 지정할 수 있다는 것입니다. 원하는 경우 부분 기능을 위의 방법 중 일부와 혼합 할 수도 있습니다.

(defn string->integer 
  ([s] (string->integer s 10))
  ([base s] (Integer/parseInt s base)))

(def hex (partial string->integer 16))

(이 응답의 맨 위에 주어진 이유로 매개 변수의 순서가 바뀌 었으므로 이것은 Brian의 답변과 약간 다릅니다.)


답변

https://clojuredocs.org/clojure.core/fnil을 볼 수도 있습니다.(fnil)


답변