代码之家  ›  专栏  ›  技术社区  ›  one-zero-zero-one

clojure-命名的论点

  •  75
  • one-zero-zero-one  · 技术社区  · 14 年前

    clojure有命名的论点吗?如果是这样,您能提供一个小例子吗?

    4 回复  |  直到 6 年前
        1
  •  114
  •   Rayne    14 年前

    在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映射的同时在函数的参数列表中进行,如上图所示。包括使用:或为如下参数定义默认值:

    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"
    

    这些不是可选的,必须提供。

    你可以破坏 休息 争论就像你会收集任何法律法规。

    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中出现。

        2
  •  33
  •   Alex Taggart    14 年前

    除了Raynes出色的回答之外,还有 a macro in clojure-contrib 这使生活更容易:

    user=> (use '[clojure.contrib.def :only [defnk]])
    nil
    user=> (defnk foo [a b :c 8 :d 9] 
             [a b c d])
    #'user/foo
    user=> (foo 1 2)
    [1 2 8 9]
    user=> (foo 1 2 3)
    java.lang.IllegalArgumentException: No value supplied for key: 3 (NO_SOURCE_FILE:0)
    user=> (foo 1 2 :c 3)
    [1 2 3 9]
    
        3
  •  0
  •   Abel    14 年前

    你是说 命名参数 ?这些不是直接提供的,但您可以 use this vectors approach 如果你愿意,这可以给你想要的。

    At RosettaCode 关于如何使用破坏来实现这一点有一个更深入的解释。

        4
  •  0
  •   agam    6 年前

    从Clojure 1.8版开始,关键字支持似乎还有点 无聊的 .

    可以这样指定关键字参数:

    (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)
    

    每种语言的每一部分都有利弊,但为了进行比较,这就是您在普通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))