Вы передаете последовательность с одним символом в функцию make-str
, а не сам символ.Использование first
вместо take
должно дать желаемый эффект.
Также нет необходимости использовать ссылки.По сути, их использование является грубым злоупотреблением ими.Вы уже используете аккумулятор в своей функции, поэтому вы можете использовать str
напрямую.
(defn make-str-from-chars
"make a string from a sequence of characters"
([chars] (make-str-from-chars chars ""))
([chars result]
(if (zero? (count chars))
result
(recur (drop 1 chars) (str result (first chars))))))
Конечно, count
не очень хорошо в этом случае, потому что он всегда должен пройти всю последовательность довыяснить его длину.Таким образом, вы обходите входную последовательность несколько раз без необходимости.Обычно используется seq
, чтобы определить, когда последовательность исчерпана.Мы также можем использовать next
вместо drop
, чтобы сэкономить некоторые затраты на создание ненужных объектов последовательности.Обязательно запишите возвращаемое значение seq
, чтобы избежать накладных расходов на создание объектов в дальнейшем.Мы делаем это в if-let
.
(defn make-str-from-chars
"make a string from a sequence of characters"
([chars] (make-str-from-chars chars ""))
([chars result]
(if-let [chars (seq chars)]
(recur (next chars) (str result (first chars)))
result)))
функциях, подобных этой, которые просто возвращают аккумулятор при полном использовании его входного сигнала, кричат о reduce
.
(defn make-str-from-chars
"make a string from a sequence of characters"
[chars]
(reduce str "" chars))
уже хорошо и коротко, но в этом конкретном случае мы можем сделать еще немного лучше, используя apply
.Тогда str
может использовать базовый StringBuilder
на полную мощность.
(defn make-str-from-chars
"make a string from a sequence of characters"
[chars]
(apply str chars))
Надеюсь, это поможет.