代码之家  ›  专栏  ›  技术社区  ›  Evan Senter

Clojure元编程问题(初学者!)

  •  11
  • Evan Senter  · 技术社区  · 16 年前

    好吧,我开始看一下Clojure语言,有几个问题是关于我要做的事情。广义的目标是对序列函数进行别名 every? all? . 我肯定有一个函数或宏可以实现别名化(或者类似的东西),但是我想看看我目前所知道的一些基本构造是否可以实现别名化。我的方法是定义一个函数 全部? 它的论点适用于 每一个? 实施。

    我很想知道这是否可以成为不可知的,所以我想参数化我的alias函数以获取两个参数,新名称(作为关键字)和旧名称(作为函数引用)。为了实现这个目标,我遇到了两个问题。

    1) 用关键字定义命名函数会引发错误。显然它想要 clojure.lang.IObj .

    user=> (defn :foo "bar")     
    java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to clojure.lang.IObj (NO_SOURCE_FILE:0)
    

    irb(main)> self.class.instance_eval do
    irb(main)* define_method(:foo) { "bar" }
    irb(main)> end
    => #<Proc>
    irb(main)> foo
    => "bar"
    

    2) 将函数的所有参数收集到单个变量中。甚至基本功能,如 (+ 1 2 3 4) 接受可变数量的参数。到目前为止,我所看到的所有函数定义技术都使用特定数量的参数,无法将列表中的所有内容聚合起来,以便在函数体中进行处理。再一次,我要用Ruby做的是这样的:

    irb(main)> def foo(*args)
    irb(main)> p args
    irb(main)> end
    => nil
    irb(main)> foo(1, 2, 3)
    [1, 2, 3]
    => nil
    

    3 回复  |  直到 16 年前
        1
  •  17
  •   Michał Marczyk    16 年前

    我将用要点来回答,因为这些问题可以整齐地分为若干独立的问题。

    • 隐含地包含在后面的东西中的东西,但它可能保证了它自己的一个项目符号:由 def &公司(尤其是 defn )是VAR。所以你真正想做的是给 变量

    • clojure.contrib.def/defalias :

      (use '[clojure.contrib.def :only [defalias]])
      (defalias foo bar)
      ; => foo can now be used in place of bar
      

      这比 (def foo bar) 它通过元数据(如docstring)进行复制;它甚至可以在当前的头中使用宏,尽管我记得在早期版本中有一个bug阻止了它。

    • 变量是用符号命名的,而不是关键字。Clojure(和其他lisp)中的符号文字不以冒号开头( :foo 是关键字,不是符号)。因此要定义一个函数 foo

      (defn foo [...] ...)
      
    • 定义 是一个帮助宏,用于轻松创建 新的 & fn 定义 不可能用预先存在的值(可能是函数)创建变量,因为这是创建别名所必需的;使用 defalias 定义 相反。

    • (fn [x y & args] ...)
      

      x 和 y 将是必需的位置参数;传递给函数的其余参数(任意数量)将被收集到一个seq中,并在名称下可用 args . 如果不需要,则不必指定任何“必需的位置参数”: (fn [& args] ...)

      要创建包含可变函数的Var,请使用

      (defn foo [x y & args] ...)
      
    • 要将函数应用于某些参数,您必须将其组装到seqable对象中(例如 参数 在上述示例中,或者可能是向量&c、 ),使用 apply

      (defn all? [& args]
        (apply every? args))
      
    • 功能 要创建别名(而不是宏),需要研究函数 intern , with-meta , meta --还有可能 resolve / ns-resolve

        2
  •  6
  •   Community Mohan Dere    9 年前

    你要做的就是把每一个都绑起来?对所有人起作用?符号,通过def完成:

    (def all? every?)
    

    更多信息,请参见 Clojure macro to create a synonym for a function

        3
  •  3
  •   j-g-faustus    16 年前

    我不认为我可以在这里对现有的解释做太多补充,除了在Ruby Traveler's dictionary中填写几个关于参数收集和分解的空白:

    (defn foo [& args]                 ; Ruby: def foo(*args)
      (println args))    
    user=> (foo 1 2 3)
    (1 2 3)
    
    (defn foo [& args] 
      (+ args))   
    user=> (foo 1 2 3)
    java.lang.ClassCastException       ; + takes numbers, not a list
    
    (defn foo [& args] 
      (apply + args))                  ; apply: as Ruby proc.call(*args)
    user=> (foo 1 2 3)
    6
    
    (defn foo [& args]
      (let [[a b & other] args]        ; Ruby: a, b, *other = args
        (println a b other)))
    user=> (foo 1 2 3)
    1 2 (3)
    
    推荐文章