Подтвердить что ты не робот

Почему моя строковая функция возвращает clojure.lang.LazySeq @xxxxxx?

Я определил следующие 3 функции, используя leiningen REPL:

(defn rand-int-range [floor ceiling] (+ floor (rand-int (- ceiling floor))))

(defn mutate-index
  "mutates one index in an array of char and returns the new mutated array"
  [source idx]
  (map
    #(if (= %1 idx)
       (char (+ (int %2) (rand-int-range -3 3)))
       %2)
    (iterate inc 0)
    source))

(defn mutate-string
  [source]
  (str
    (mutate-index
      (.toCharArray source)
      (rand-int (alength (.toCharArray source))))))

Когда я запускаю (mutate-string "hello"), вместо REPL печатает измененную строку, он печатает clojure.lang.LazySeq @xxxxxx, где "xxxxx" представляет собой случайную последовательность чисел и букв. Я бы ожидал, что вместо этого он напечатает что-то вроде "hellm". Это действительно возвращает мне строку, как я думаю? Если да, как я могу заставить REPL показать мне эту строку?

4b9b3361

Ответ 1

1) Чтобы преобразовать последовательность символов (что возвращает mutate-index) в строку, используйте apply str, а не только str. Последний действует на объекты, а не на последовательности.

(str [\a \b \c])
=> "[\\a \\b \\c]"

(apply str [\a \b \c])
=> "abc"

2) Строки могут быть разделены, что означает, что вы можете использовать функции последовательности, такие как map и filter, без них, например, .toCharArray.

3) С помощью map-indexed или StringBuilder попробуйте выполнить то, что вы пытаетесь сделать:

(apply str (map-indexed (fn [i c] (if (= 3 i) \X c)) "foobar"))
=> "fooXar"

(str (doto (StringBuilder. "foobar") (.setCharAt 3 \X)))
=> "fooXar"

Ответ 2

Это происходит потому, что функция map возвращает ленивую последовательность, которая представляет собой просто имя класса и хеш (clojure.lang.LazySeq @xxxxxx).

Чтобы получить исходную работу, вам нужно сначала оценить ленивую последовательность. Используя (примените str...), как утверждает Джастин, это должно произойти, и вы должны получить правильный результат.

В противном случае, если вы видите похожие проблемы из-за отсутствия ленивой последовательности, вы должны попробовать функцию doall, которая заставляет evalutation ленивой последовательности

Ответ 3

Всякий раз, когда я хочу получить строковое значение ленивой последовательности, я использую clojure.core/pr-str:

user=> (clojure.tools.logging/infof "This is a lazy seq [%s]" (take 5 (range 100)))
INFO  user - This is a lazy seq [[email protected]]
nil
user=> (clojure.tools.logging/infof "This is a lazy seq [%s]" (pr-str (take 5 (range 100))))
INFO  user - This is a lazy seq [(0 1 2 3 4)]
nil