所有,我开始看看Clojure语言,并且对我正在尝试做的事情有几个问题.广义目标是别名序列的功能every?来all?.我确定有一个函数或宏做了别名(或者那些行),但是我想看看到目前为止我知道的一些基本结构是否可行.我的方法是定义一个名为的函数all?,将其参数应用于every?实现.
我很想知道这是否可以不可知,所以我想参数我的别名函数接受两个参数,新名称(作为关键字)和旧名称(作为函数引用).在努力实现这一目标时,我遇到了两个问题.
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)
Run Code Online (Sandbox Code Playgroud)
是否有一个函数将关键字强制转换为IObj,或其他方法来参数化具有一些提供值的新定义函数的名称?(在Ruby中,define_method和其他技术一样)
irb(main)> self.class.instance_eval do
irb(main)* define_method(:foo) { "bar" }
irb(main)> end
=> #<Proc>
irb(main)> foo
=> "bar"
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
感谢您提供的任何帮助!
Mic*_*zyk 17
我将在要点中回答,因为问题可以整齐地分成若干单独的问题.
隐藏在随后的内容中的东西,但也许保证了它自己的子弹:由def&Co.(特别是由defn)创建的顶级对象是Vars.所以你真正想做的是别名Var ; 函数只是常规值,它们实际上没有名称(除非它们可能在其主体内部本地绑定了一个名称;但这与手头的问题无关).
在Clojure中确实有一个"别名宏" - clojure.contrib.def/defalias:
(use '[clojure.contrib.def :only [defalias]])
(defalias foo bar)
; => foo can now be used in place of bar
Run Code Online (Sandbox Code Playgroud)
这样做的好处(def foo bar)是它可以复制元数据(例如docstring); 它甚至似乎与当前HEAD中的宏一起使用,尽管我记得在早期版本中出现了一个阻止它的错误.
Vars以符号命名,而不是关键字.Clojure(和其他Lisps)中的符号文字不以冒号开头(:foo是关键字,而不是符号).因此,要定义一个名为foo你应该写的函数
(defn foo [...] ...)
Run Code Online (Sandbox Code Playgroud)defn是一个帮助器宏,通过允许程序员使用&语法的混合来简化新函数保持Vars 的创建.因此创建具有预先存在的值(可能是函数)的Vars是不可能的,这是创建别名所必需的; 使用或简单地改为.deffndefndefaliasdef
要创建可变参数函数,请使用以下语法:
(fn [x y & args] ...)
Run Code Online (Sandbox Code Playgroud)
x和y将需要的位置参数; 传递给函数的其余参数(任意数量的参数)将被收集到seq中并在名称下可用args.如果不需要,您不必指定任何"必需的位置参数":(fn [& args] ...).
要创建包含可变参数函数的Var,请使用
(defn foo [x y & args] ...)
Run Code Online (Sandbox Code Playgroud)要将函数应用于某些参数,您已将它们组合成一个seqable对象(例如args上面示例中的seq或者vector&c.),请使用apply:
(defn all? [& args]
(apply every? args))
Run Code Online (Sandbox Code Playgroud)如果你想编写一个函数来创建别名-而不是宏-你需要调查的功能intern,with-meta,meta-以及可能的resolve/ ns-resolve,视功能是否接受符号或瓦尔.我将把细节作为练习留给读者.:-)
你需要做的就是绑定每一个?功能全部?符号,通过def完成:
(def all? every?)
Run Code Online (Sandbox Code Playgroud)
有关此内容的更多信息,请参阅Clojure宏以创建函数的同义词
| 归档时间: |
|
| 查看次数: |
2316 次 |
| 最近记录: |