Functional programming &引用;无法解析符号“0”;错误

Functional programming &引用;无法解析符号“0”;错误,functional-programming,lisp,clojure,Functional Programming,Lisp,Clojure,当我将此代码粘贴到REPL中时,它可以正常工作: (use 'clojure.contrib.seq-utils) (defn- random-letter [] (char (+ (rand-int 26) 97))) (defn- random-digit [] (rand-int 10)) (defn- random-password "Returns an 8-character password consisting of letters and digits as follows

当我将此代码粘贴到REPL中时,它可以正常工作:

(use 'clojure.contrib.seq-utils)
(defn- random-letter [] (char (+ (rand-int 26) 97)))
(defn- random-digit [] (rand-int 10))
(defn- random-password
  "Returns an 8-character password consisting of letters and digits as follows: aa1aa1aa"
  []
  (let [password (interpose '((random-digit)) (repeat 3 (repeat 2 '(random-letter))))]
    (apply str (flatten (map (fn [coll] (map eval coll)) password)))))
现在,我有了带有
:gen class:implements[my.ServiceInterface]
的代码和一个前缀为
-
的函数来实现接口。我使用Maven/Groovy/TestNG进行单元测试。其他几个接口/Clojure实现都可以正常工作,但在这种特殊情况下,我遇到了以下错误:

java.lang.RuntimeException:
java.lang.Exception: Unable to resolve symbol: random-letter in this context (NO_SOURCE_FILE:32)
我不明白为什么。我唯一能说的是,这个函数与所有其他函数不同,这是我唯一使用引号的地方,即
'((随机数字))
'(随机字母)
。编辑:而且,这是我唯一使用
eval
的地方

我尝试将函数定义为“非私有”(
defn
而不是
defn-
)。我还尝试了顶部的
(声明随机数字随机字母)
。这两种方法都不能解决问题

另外,如果您有更好的方法来实现
随机密码
功能的建议,我洗耳恭听。但我仍然想知道为什么我会犯这个错误,以及如何让它起作用

非常感谢你的帮助。Clojure真是太棒了

编辑:这是完整的代码

(ns fred.hp2010.service.ClojurePoolerService
  (:gen-class :implements [fred.hp2010.service.PoolerService])
  (:use [clojure.contrib.seq-utils :only (flatten)]))

(def dao (fred.hp2010.persistence.Repository/getDao))

(declare find-by is-taken random-password)

(defn -addPooler [this pooler] (. dao insert "POOLER" pooler))
(defn -getPoolers [this] (. dao list "poolers"))
(defn -isEmailTaken [this email] (is-taken {"email" email}))
(defn -isUsernameTaken [this username] (is-taken {"username" username}))
(defn -login [this email password] (. dao findSingle "POOLER" {"email" email "password" password}))

(defn -changePassword [this email new-password]
  (let [updated-pooler (assoc (into {} (find-by {"email" email})) "password" new-password)]
    (. dao update "POOLER" "POOLER_ID" updated-pooler)))

(defn -resetPassword [this email]
  (let [new-password (random-password)]
    (-changePassword this email new-password)
    new-password))

(defn- find-by [params] (. dao findSingle "POOLER" params))
(defn- is-taken [params] (not (nil? (find-by params))))

(defn- random-letter [] (char (+ (rand-int 26) 97)))
(defn- random-digit [] (rand-int 10))
(defn- random-password
  "Returns an 8-character password consisting of letters and digits as follows: aa1aa1aa"
  []
  (let [password (interpose '((random-digit)) (repeat 3 (repeat 2 '(random-letter))))]
    (apply str (flatten (map (fn [coll] (map eval coll)) password)))))

我不知道您为什么在编译
:gen class
时遇到问题,但如果
eval
与此有关,我也不会感到惊讶<代码>评估通常是个坏主意。要尝试的一件事(完全未经测试)是使用
`
(backquote)而不是
(quote),以便您的符号符合命名空间的要求。我不知道这是否有用

不过最好还是去掉
eval
。如果您通过
反复将随机字符函数转换为无限长的惰性序列
,您可以这样做:

(defn- random-letter [] (repeatedly #(char (+ (rand-int 26) 97))))
(defn- random-digit  [] (repeatedly #(rand-int 10)))
(defn- random-password
  "Returns an 8-character password consisting of letters and digits as follows: aa1aa1aa"
  []
  (apply str
         (mapcat (fn [[n f]] (take n (f)))
                 [[2 random-letter]
                  [1 random-digit]
                  [2 random-letter]
                  [1 random-digit]
                  [2 random-letter]])))

在最上面的几行中,我在理解语法方面有点困难。特别是,为什么第7行中有所有的引号?延迟计算所有这些表达式可能对您没有帮助。我猜引用的
”(随机字母)
会破坏你的乐趣

您可能可以编写更简单的代码,同时避免使用
eval
。我将在REPL中尝试它,我希望能很快带着一个改进的版本回来

编辑:

好的,这是有效的:

(apply str (interpose (random-digit) (repeat 3 (apply str (repeat 2 (random-letter))))))
…而且它不需要任何来自
clojure.contrib
:)

str
函数将把所有参数组合成一个字符串。如果参数在列表中,您可以使用
apply
str
走私到列表中

正如你所说,Clojure很酷

编辑:

下面是一个函数,它根据字符串规范生成字母和数字的随机字符串:

(apply str (map (fn [c] (if (= c \a) (random-letter) (random-digit))) "aanaanaa")))

它有点偏离您的规范,但我认为它很酷。

我不知道,但是Clojure,但是在Scheme中使用eval需要一些环境,您得到的错误是我在Scheme中所期望的。但是,唉,我不知道Clojure,所以我无能为力,但也许这会让你走上正确的道路。:)嗯,你可能是对的。这也是我唯一使用“eval”的地方。但是,为什么它在REPL中工作,而在执行单元测试时不工作?@leppie:那么如何在Scheme中解决这个问题呢?:-)我添加了另一个可能的解决方案,希望您喜欢!谢谢,但是您的函数使用了与GGG中相同的字母和数字。我知道我的评论是AAA1AAA,但那是为了显示字母和数字的位置。我仍然希望它们有所不同:)就像在xy5ma8fr中一样。啊,我想知道这是否是故意的!:)但我想我也有办法解决这个问题。这个怎么样?(应用str(使用8(重复使用#)(列表(随机字母)(随机字母)(随机数字‘‘‘‘‘‘‘‘‘‘‘)’)好吧,看起来我们的建议中最好的建议正在合并。谢谢,
`
在使用
defn
公开函数后,确实解决了问题。布莱恩,关于Clojure有什么你不知道的吗?;-)不过,你关于评估是个坏主意的观点是正确的。我想找出一个更优雅的解决方案。我很喜欢有3对字母并在其中插入数字的想法,而不是2-1-2-1-2解决方案。“重复”是我缺少的。这个怎么样<代码>(应用str(取8(展平)(重复#)(列表(随机字母)(随机字母)(随机数字щщщ))
是的,这是另一个好方法。它让我想起了
循环
,我将进行编辑。任何有效的方法都可能很好,除非你生成了10亿个密码,并且需要快速。