目的是对Caesar密码进行略微修改。 首先是移动角色的功能:
(defn move-char [c shift idx encode-or-decode]
(let [ch (int c) val (mod (* encode-or-decode (+ shift idx)) 26)]
(cond
(and (>= ch (int \A)) (<= ch (int \Z))) (char (+ (mod (+ val (- (int ch) (int \A))) 26) (int \A)))
(and (>= ch (int \a)) (<= ch (int \z))) (char (+ (mod (+ val (- (int ch) (int \a))) 26) (int \a)))
:else c)))
然后是一个将最后一个映射到字符串的函数:
(defn move-shift-aux [str shift encode-or-decode]
(map-indexed (fn [idx item] (move-char item shift idx encode-or-decode)) str))
`(move-shift-aux "I should have known..." 1 1)` returns
(\J \space \v \l \t \a \s \l \space \r \l \h \r \space \z \d \f \o \g \. \. \.)
如果我写:
(apply str (move-shift-aux "I should have known..." 1 1))
我得到了我想要的东西:
"J vltasl rlhr zdfog..."
但如果我定义:
(defn moving-shift [str shift]
(apply str (move-shift-aux str shift 1)))
(moving-shift "I should have known..." 1)
我明白了:
CompilerException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn, compiling:(caesar\core.clj:29:44)
我不明白为什么编译器异常在直接应用时工作正常。
答案 0 :(得分:2)
您使用str
参数隐藏了clojure.core
的{{1}}符号。在str
的范围内,moving-shift
指的是str
而不是"I should have known..."
,因此当您调用clojure.core/str
函数时,会得到apply
,声明字符串不是函数。
为字符串参数使用另一个名称。