2015-10-31 5 views
1

Я пытаюсь реализовать ленивую последовательность (которая должна сгенерировать одну строку) в REPL, без везения. Исходный код работает отлично:Выполнение ленивой последовательности (строки) Clojure в REPL

(def word_list ["alpha" "beta" "gamma" "beta" "alpha" "alpha" "beta" "beta" "beta"]) 
(def word_string (reduce str (interpose " " word_list))); 
word_string ; "alpha beta gamma beta alpha alpha beta beta beta" 

Но не желая оставить в покое, я задавался вопросом, что еще будет работать, и попытался удалить reduce, думая, что str может иметь тот же эффект. Это не ...

(def word_string (str (interpose " " word_list))) 
word_string ; "[email protected]" 

Я попробовал очевидное, используя reduce снова, но это не сработало. Там в another question о реализации ленивых последовательностей, которые казались многообещающими, но ничего я пытался не работал:

(reduce str word_string) ; "[email protected]" 
(apply str word_string) ; "[email protected]" 
(println word_string)  ; "[email protected]" 
(apply list word_string) ; [\c \l \o \j \u \r \e \. \l \a \n \g \. \L \a \z \y...] 
(vec word_string)   ; [\c \l \o \j \u \r \e \. \l \a \n \g \. \L \a \z \y...] 
(apply list word_string) ; (\c \l \o \j \u \r \e \. \l \a \n \g \. \L \a \z \y...) 
(take 100 word_string)  ; (\c \l \o \j \u \r \e \. \l \a \n \g \. \L \a \z \y...) 

Тот факт, что некоторые из вариантов, дал мне символы в «clojure.lang.LazySeq» также беспокоит меня - сделал Я как-то теряю фактическое значение строки, а моя ссылка имеет значение «clojure.lang.LazySeq»? Если нет, то как я действительно реализую ценность?

Чтобы уточнить: учитывая, что word_string назначен ленивой последовательности, как бы я это понял? Что-то вроде (realize word_string), скажем, если это существовало.

Update: на основе принятого Ответ и как str работы, то получается, что я может получить фактическое значение последовательности, а не только его имя:

(reduce str "" word_string) ; "alpha beta gamma beta alpha alpha beta beta beta" 

Да, это ужасно код , :) Я просто пытался понять, что происходит, почему он ломается, и действительно ли фактическое значение там или нет.

ответ

4

Что вы хотите:

(def word_string (apply str (interpose " " word_list))) 

Посмотрите документацию str:

При отсутствии аргументов, возвращает пустую строку. С одним аргументом x возвращает
x.toString(). (str nil) возвращает пустую строку. С более чем
один аргумент arg возвращает конкатенацию значений str аргументов.

Так вы звоните .toString на последовательности, которая создает представление, что вместо применения str к элементам последовательности в качестве аргументов.

BTW, тем более идиоматический способ сделать то, что вы хотите:

(clojure.string/join " " word_list) 

Кроме того, строка не ленивая последовательность. interpose возвращает ленивую последовательность, и вы вызываете .toString.

+0

Я предполагаю, что я не понял свой вопрос - мне удалось передать полностью реализованную строку в 'word_string', используя' reduce', хотя «apply» может быть лучше. Но учитывая, что 'word_string' _was_ назначен ленивой последовательности, как я это понимаю? Какую операцию я бы применил к 'word_string', например' (реализовать word_string) '? –

+0

Я думаю, вы в замешательстве: второе назначение word_string не означает ленивую последовательность; это строка, которая приводит к вызову .toString в ленивой последовательности. Строковое представление ленивой последовательности не очень полезно и не то, что вы хотите. См. Этот вопрос: http://stackoverflow.com/questions/7946219/why-does-my-string-function-return-a-clojure-lang-lazyseqxxxxxx –

+0

Да, я определенно смущен. :) Есть много странных, ошибочных, неинтуитивных аспектов для Clojure, ленивых последовательностей и т. Д., Что я все еще работаю над пониманием. Однако, я думаю, я вижу, что произошло в этом случае, _str_ не делает то, что я изначально думал. Благодарю. –

1

Вам не нужно ничего делать, чтобы реализовать ленивый seq в clojure, вы просто используете его в любом месте, где ожидается seq.

user=> (def word-list ["alpha" "beta" "gamma" "beta" "alpha" "alpha" "beta" "beta" "beta"]) 
#'user/word-list 
user=> (def should-be-a-seq (interpose " " word_list)) 
#'user/should-be-a-seq 
user=> (class should-be-a-seq) 
clojure.lang.LazySeq 

Итак, мы имеем SEQ, если я использую его в любом случае, что бы пройти через все значения в SEQ, он будет в конечном итоге полностью реализованы. например

user=> (seq should-be-a-seq) 
("alpha" " " "beta" " " "gamma" " " "beta" " " "alpha" " " "alpha" " " "beta" " " "beta" " " "beta") 

Это все еще seq, хотя на самом деле это все тот же объект, что и раньше.

user=> (str should-be-a-seq) 
"[email protected]" 

Как Диего Баш упомянул, называя ул на что-то просто как вызов .ToString, что для метода LazySeq является, по-видимому просто .ToString по умолчанию, который наследуется от Object.

Поскольку это seq, вы можете использовать его как любой seq, независимо от того, было ли это полностью реализовано ранее или нет. например

+0

Если вы используете 'str', как и я, хотя' (def should-be-a-seq (str (interpose "" word_list))) ', он ведет себя по-разному. Я использую 'str', безусловно, правильный вопрос, но я пытаюсь понять, что было назначено' (def word_string (str (interpose "" word_list))) и как его манипулировать. –

+0

@JohnC 'str' возвращает строку. В этом случае это не строка. –