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.