2016-08-20 41 views
0

我是clojure的新手。我想使用Clojure中的报价方式如下:如何在clojure中引用参数

首先,我定义一个变量:

(DEF狗 “动物”)

然后一个功能::

(定义什么是[名称]

('name(str“是一个”名称)))

如果我调用该函数什么,是与可变作为参数: (什么 - 是狗)

结果应该是:

USER >>狗动物

在这里,我回到我传递给函数什么,是,而不是其价值的参数的名称:

我得到的却是:

是动物

没有提到的参数这里的。

再次什么我找的就是重复“字面意思是”我传递给函数,这个模板参数的名称:

(乜为x)=> x是..

谢谢。

回答

4

这不是你可以用函数做的事情。一个函数只接收运行时值,而不是被评估生成这些值的代码。如果你想定义的一段代码,使得实际使用中的源代码,而不是运行时的值,你可以使用一个macro

(defmacro what-is [x] 
    `(str '~x " is an " ~x)) 

(what-is dog) 
;;=> "dog is an animal" 

正如你所看到的,这个what-is宏看起来不同,您的what-is功能;它使用了Clojure的语法引用阅读器宏。这个宏不是在运行时用一个字符串作为输入调用并返回一个字符串作为输出,而是在编译时用一段代码(x)在编译时调用,并返回另一段代码,然后将对它进行评估。您可以使用macroexpand-1功能,看看到底是什么代码what-is宏返回:

(macroexpand-1 '(what-is dog)) 
;;=> (clojure.core/str (quote dog) " is an " dog) 

如果你愿意,你可以评估这个扩展的代码一块地看到,它提供了相同的结果:

(clojure.core/str (quote dog) " is an " dog) 
;;=> "dog is an animal" 
+0

谢谢@Sam Estep。这就是我要找的。 – omar

+0

为什么一个引用的运算符像'('name 5); ==> nil'在Clojure中工作? – Sylwester

+0

@Sylwester是;请参阅我对[此问题]的回答(http://stackoverflow.com/q/35541931/5044950)。 'Symbol'类提供['invoke']的实现(https://github.com/clojure/clojure/blob/clojure-1.8.0/src/jvm/clojure/lang/Symbol.java#L125-L127 )相当于['get'](https://clojuredocs.org/clojure.core/get)。 –

2

这是另一种做我认为你想做的事的方法。不要将变量的类别定义为其值,请使用Clojure映射。例如使用基本{}地图语法:

(def what-is-map {"dog" "animal" 
        "cat" "animal" 
        "Fiat" "auto" 
        "flu" "illness"}) 

(defn what-is [thing] 
    (str thing " is an " (what-is-map thing))) 

最后一个表达式工作,因为地图可以像在许多情况下函数中使用。

(what-is "dog") ;=> "dog is an animal" 
(what-is "flu") ;=> "flu is an illness" 

您还可以为地图中未包含的东西提供默认值。这里有一种方法:

(defn what-is [thing] 
    (let [what-it-is (what-is-map thing)] 
    (if what-it-is 
     (str thing " is a " what-it-is) 
     (str "I don't know what a " thing " is")))) 

if作品,因为当钥匙未在地图中找不到,则返回nil。 (nil是假的价值观之一。另一种是false。)

(what-is "fish") ;=> I don't know what a fish is" 

还有其他的,也许是更好的方法来写这些功能,但我想保持基本的东西。

+0

@火星感谢您的回答。你期待着另一件我想实现的事情:对事物有多种定义。所以地图是最好的数据结构。 – omar

+0

@ Mars有没有一种方法可以将函数调用的是参数,而不是以字符串的形式传递。什么是狗,而不是什么是“狗”?再次感谢 – omar

+0

Omar,因为你需要一个宏,就像Sam Estep的回答一样。然而,通常使用关键字,例如':dog'作为地图的关键字,而不是字符串或其他对象。在我的例子中,我只使用字符串作为键,因为我不想一次性将太多东西扔进答案。通常情况下,我会使用'{:狗“动物”:猫“动物”等等,或者“{:狗:动物:猫:动物...}”或类似的东西,就像我的地图一样。 – Mars