fox*_*nut 5 lisp functional-programming 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: aa1aa1aa"
[]
(let [password (interpose '((random-digit)) (repeat 3 (repeat 2 '(random-letter))))]
(apply str (flatten (map (fn [coll] (map eval coll)) password)))))
Run Code Online (Sandbox Code Playgroud)
现在,我有这个代码: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)
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚为什么.我能告诉的唯一一点就是这个函数与所有其他函数的不同之处在于,这是我使用引用的唯一地方,即'((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)))))
Run Code Online (Sandbox Code Playgroud)
我不知道你为什么要编译这个问题,:gen-class
但如果eval
与它有关,我也不会感到惊讶. eval
通常是一个坏主意.尝试(完全未经测试)的一件事是使用`
(反引号)而不是'
(引用),以便您的符号是名称空间限定的.不知道这是否有帮助.
可能更好地摆脱eval
它.如果您将随机字符函数转换为无限延迟seqs,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]])))
Run Code Online (Sandbox Code Playgroud)