получить стандартный ввод и сохранить его как строку в lisp - PullRequest
3 голосов
/ 29 марта 2011

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

(setq answer (string (read)))

и

(setq answer 0)
(format answer "~s" (read))

и

(setq answer (read))

, когда я пытаюсь оценить

(if (stringp answer) 
    (princ "works")
    (princ "failed"))

на любом извышеупомянутые попытки это всегда выходит неудачей.

что я делаю не так?

Ответы [ 2 ]

20 голосов
/ 29 марта 2011

Или вы можете просто сделать:

(setq answer (read-line))

Это дает вам строку прямо там.

[1]> (setq answer (read))
3
3
[2]> (type-of answer)
(INTEGER 0 16777215)
[3]> (setq answer (read-line))
3
"3"
[4]> (type-of answer)
(SIMPLE-BASE-STRING 1)
[5]>
5 голосов
/ 29 марта 2011

Запустите новый REPL, затем попробуйте проверить возвращаемое значение каждого из ваших шагов:

T1> (read)
foo
FOO
T1> (read)
1
1
T1> (type-of (read))
foo
SYMBOL
T1> (type-of (read))
1
BIT

Теперь обратите внимание, что STRING не будет работать на всех типах ввода:

T1> (string 'foo)
"FOO"
T1> (string 1)

Также обратите внимание, что, в отличие от setq, (format foo ...) не будет устанавливать foo, а записывать в него, если это поток или строка с указателем заполнения .Посмотрите на документацию , и вы увидите:

строка управления форматом назначения и остальные аргументы => результат

[...]

destination --- nil, t, поток или строка с указателем заполнения. Формат

[...]

полезен для создания красиво отформатированного текста,создание красивых сообщений и так далее.Формат может генерировать и возвращать строку или вывод к месту назначения.

Если место назначения - это строка, поток или t, то результатом будет ноль.Иначе, результатом будет строка, содержащая `output. '

Попробуйте это так:

T1> (setq *answer*
          (with-output-to-string (s)
            (format s "~s" (read))))
1
"1"
T1> *answer*
"1"

Или вот так:

T1> (setq *answer* (make-array 20 :element-type 'character :fill-pointer 0))
""
T1> (format *answer* "~s" (read))
1
NIL
T1> *answer*
"1" 

Теединственные важные ошибки, которые я мог найти в вашем коде.Это определенно возвращает "works" в каждом соответствующем CL (вы также можете использовать prin1-to-string):

T1> (defvar *answer*)
*ANSWER*
T1> (setq *answer* (format nil "~s" (read)))
1
"1"
T1> (if (stringp *answer*)
        (princ "works")
        (princ "failed"))
works
"works"

Если вы не попали в перепутанный пакет (попробуйте (in-package cl-user) перед оценкой кода), илипереопределен базовый функционал, это будет работать.Дайте более точные описания ошибок, если это все еще не произойдет.

ED:

Прочитав ответ Билла, который правильно указал на read-line как более короткое решение, я, возможно, должен упомянуть, чтоЯ не пытался показать в своем ответе самые лучшие, краткие или идиоматические подходы, и что они будут варьироваться в зависимости от того, что вы действительно пытаетесь сделать.(Самое короткое из возможных решений было бы "works" :) Это всего лишь примеры, которые должны помочь объяснить, почему ваш код вышел из строя.

Еще одна вещь, которую я забыл сказать, это то, что вы должны помнить, что этот уровень выше setq s для переменных, не определенных с помощью defvar или defparameter, как правило, следует избегать ни в чем, кроме как вмешиваться в REPL, поскольку последствия не определены.Кроме того, эти переменные, по соглашению, заключены в звездочки (также называемые earmuffs ), чтобы предотвратить ошибки, вызванные путаницей спецпредложений с переменными лексической области.

...