Clojure:直接应用或通过函数应用之间的区别

时间:2015-06-06 18:15:48

标签: clojure

目的是对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)

我不明白为什么编译器异常在直接应用时工作正常。

1 个答案:

答案 0 :(得分:2)

您使用str参数隐藏了clojure.core的{​​{1}}符号。在str的范围内,moving-shift指的是str而不是"I should have known...",因此当您调用clojure.core/str函数时,会得到apply ,声明字符串不是函数。 为字符串参数使用另一个名称。