当我将这段代码粘贴到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)我不知道为什么。我能说出的唯一不同于其他函数的是,这是我唯一使用quoting的地方,也就是'((random-digit))和'(random-letter)。编辑:还有,这是我唯一使用eval的地方。
我尝试将函数定义为“非私有”(用defn-代替defn)。我还尝试了顶部的(declare random-digit random-letter)。这些都不能解决问题。
顺便说一句,如果您有关于实现random-password函数的更好方法的建议,我洗耳恭听。但我仍然想知道为什么我会得到这个错误,以及如何让它工作。
非常感谢您的帮助。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)))))发布于 2009-11-22 05:49:22
我不知道为什么你在用:gen-class编译这段代码时会遇到问题,但如果eval与此有关,我也不会感到惊讶。eval通常不是一个好主意。可以尝试的一件事(完全未经测试)是使用` (反引号)而不是' (引号),以便您的符号是名称空间限定的。不知道这有没有帮助。
不过,摆脱eval可能更好。如果你通过repeatedly把你的随机字符函数变成无限的惰性序列,你可以这样做:
(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]])))发布于 2009-11-22 05:59:17
在最上面的几行代码中,我在语法方面遇到了一些问题。特别是,为什么第7行中的所有引号?延迟计算所有这些表达式可能对您没有帮助。我猜引用的'(random-letter)破坏了你的乐趣。
您可以编写更简单的代码,同时避免使用eval。我将在REPL中尝试它,我希望很快带着一个改进的版本回来。
编辑:
好的,这行得通:
(apply str (interpose (random-digit) (repeat 3 (apply str (repeat 2 (random-letter))))))...and它不需要来自clojure.contrib的任何东西:)
str函数将所有参数放到一个字符串中。如果参数在列表中,则可以使用apply将str偷偷带到列表中。
正如您所说,Clojure很酷!
编辑:
下面是一个函数,它根据字符串规范生成一个由字母和数字组成的随机字符串:
(apply str (map (fn [c] (if (= c \a) (random-letter) (random-digit))) "aanaanaa")))它与你的规范有点不同,但我认为它很酷。
https://stackoverflow.com/questions/1776798
复制相似问题