Clojure-명명 된 인수


78

Clojure에 명명 된 인수가 있습니까? 그렇다면 작은 예를 들어 주시겠습니까?

답변:


119

Clojure 1.2에서는 rest맵을 해체하는 것처럼 인수를 해체 할 수 있습니다. 즉, 명명 된 비 위치 키워드 인수를 수행 할 수 있습니다. 다음은 예입니다.

user> (defn blah [& {:keys [key1 key2 key3]}] (str key1 key2 key3))
#'user/blah
user> (blah :key1 "Hai" :key2 " there" :key3 10)
"Hai there10"
user> (blah :key1 "Hai" :key2 " there")
"Hai there"
user> (defn blah [& {:keys [key1 key2 key3] :as everything}] everything)
#'user/blah
user> (blah :key1 "Hai" :key2 " there")
{:key2 " there", :key1 "Hai"}

아무것도 위의 그림과 같이 Clojure의 맵을 destructuring 동안 당신이 할 수있는 함수의 인수 목록에서 수행 할 수 있습니다. : or를 사용하여 다음과 같은 인수의 기본값을 정의하는 것을 포함합니다.

user> (defn blah [& {:keys [key1 key2 key3] :or {key3 10}}] (str key1 key2 key3))
#'user/blah
user> (blah :key1 "Hai" :key2 " there")
"Hai there10"

그러나 이것은 Clojure 1.2에 있습니다. 또는 이전 버전에서는 다음과 같이 동일한 작업을 시뮬레이션 할 수 있습니다.

user> (defn blah [& rest] (let [{:keys [key1 key2 key3] :or {key3 10}} (apply hash-map rest)] (str key1 key2 key3)))
#'user/blah
user> (blah :key1 "Hai" :key2 " there")
"Hai there10"

일반적으로 동일한 방식으로 작동합니다.

또한 키워드 인수 앞에 오는 위치 인수를 가질 수도 있습니다.

user> (defn blah [x y & {:keys [key1 key2 key3] :or {key3 10}}] (str x y key1 key2 key3))
#'user/blah
user> (blah "x" "Y" :key1 "Hai" :key2 " there")
"xYHai there10"

이는 선택 사항이 아니므로 제공해야합니다.

restClojure 컬렉션처럼 인수를 실제로 분해 할 수 있습니다 .

user> (defn blah [& [one two & more]] (str one two "and the rest: " more))
#'user/blah
user> (blah 1 2 "ressssssst")
"12and the rest: (\"ressssssst\")"

Clojure 1.1에서도 이런 일을 할 수 있습니다. 그러나 키워드 인수에 대한 맵 스타일 구조 해제는 1.2에서만 제공되었습니다.


34

Raynes의 탁월한 답변 외에도 clojure-contrib 에는 삶을 더 쉽게 만들어주는 매크로 가 있습니다 .

user => ( '[clojure.contrib.def : only [defnk]] 사용)
무
사용자 => (defnk foo [ab : c 8 : d 9] 
         [abcd])
# 'user / foo
사용자 => (foo 1 2)
[1 2 8 9]
사용자 => (foo 1 2 3)
java.lang.IllegalArgumentException : 키에 제공된 값 없음 : 3 (NO_SOURCE_FILE : 0)
사용자 => (foo 1 2 : c 3)
[1 2 3 9]

7
나는 그것을 언급하는 것을 잊었다! 나는 Clojure가 물건을 분해 할 수있는 1 만 가지 방법을 보여주는데 사로 잡혔다. : p
— Rayne

1
clojure-contrib는 더 이상 사용되지 않으며 현재 대안을 찾을 수 없습니다. 어떤 아이디어?
— Lstor

2
@Lstor : 체크 아웃 defnk 에 프리즘 / 배관
— 이안

4

Clojure 버전 1.8에서 키워드 지원은 여전히 ​​약간 meh .

다음과 같이 키워드 인수를 지정할 수 있습니다.

(defn myfn1
  "Specifying keyword arguments without default values"
  [& {:keys [arg1 arg2]}]
  (list arg1 arg2))

호출의 예 :

(myfn1 :arg1 23 :arg2 45)  --> evaluates to (23 45)
(myfn1 :arg1 22)           --> evaluates to (22 nil)

이러한 키워드 인수에 대한 기본값을 지정하려면 다음을 수행하십시오.

(defn myfn2
  "Another version, this time with default values specified"
  [& {:keys [arg1 arg2] :or {arg1 45 arg2 55}}]
  (list arg1 arg2))

이것은 두 번째 경우에 예상되는 일을 수행합니다.

(myfn2 :arg1 22)           --> evaluates to (22 55)

각 언어의 각 부분에는 장단점이 있지만 비교를 위해 Common Lisp에서 동일한 작업을 수행하는 방법은 다음과 같습니다.

(defun myfn3
    (&key arg1 arg2)
    "Look Ma, keyword args!"
    (list arg1 arg2))

(defun myfn4
    (&key (arg1 45) (arg2 55))
    "Once again, with default values"
    (list arg1 arg2))

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.