【发布时间】:2009-11-21 21:12:50
【问题描述】:
当我将此代码粘贴到 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)
我不知道为什么。我唯一能说的是这个函数与所有其他函数的不同之处在于,这是我唯一使用引用的地方,即'((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)))))
【问题讨论】:
-
我不知道 Clojure,但是在 Scheme 中使用 eval 需要一些环境,而您得到的错误是我在 Scheme 中所期望的。但是,唉,我不知道 Clojure,所以我无能为力,但也许这会让你走上正确的道路。 :)
-
嗯,你可能是对的。这也是我唯一使用“eval”的地方。但是为什么它在 REPL 中起作用,而不是在执行单元测试时呢?
-
@leppie:那么你将如何在 Scheme 中解决这个问题? :-)
-
我添加了另一个可能的解决方案,希望你喜欢!
标签: functional-programming lisp clojure