Лисп: Помогите НЕ вернуть значение? - PullRequest
4 голосов
/ 26 марта 2011

Я написал функцию, которая принимает список строк и печатает их построчно.

(defun print-to-lines (slist)
    (cond
        ((null slist) slist)
        (t (let ((empty (write-line (car slist)))) (print-to-lines (cdr slist))))))

Это прекрасно работает, за исключением того, что есть дополнительное возвращаемое значение (в данном случае NIL)в конце вывода (при запуске в окне отладки):

CG-USER(16): (print-to-lines '("adam" "emilio" "eoln"))
adam
emilio
eoln
NIL

Я понимаю, откуда взялся этот дополнительный NIL (это возвращаемое значение моей функции), но я хочу, чтобы этого не былотам.Мое назначение диктует, что этого нет.Есть ли способ «подделать» его или отключить?

Ответы [ 5 ]

6 голосов
/ 27 марта 2011

Я хочу анализировать и улучшать ваш код, одновременно отвечая на ваши вопросы.

Стандартный отступ - два пробела.

(defun print-to-lines (slist)
  (cond
    ((null slist) slist)
    (t (let ((empty (write-line (car slist)))) (print-to-lines (cdr slist))))))

Вам разрешено создавать новые строки между любыми двумя токенами.

(defun print-to-lines (slist)
  (cond
    ((null slist) slist)
    (t (let ((empty (write-line (car slist))))
         (print-to-lines (cdr slist))))))

Вещество после условия в cond форме оценивается в неявный progn. Вам не нужно называть значение, которое выбрасывается все равно прочь.

(defun print-to-lines (slist)
  (cond
    ((null slist) slist)
    (t (write-line (car slist))
       (print-to-lines (cdr slist)))))

Чтобы ничего не возвращать, используйте values. Обратите внимание, что это обычно необязательно, так как возвращаемое значение не является частью вывода; это просто отображается с помощью REPL (в среде подсветки синтаксиса, программный вывод и вывод REPL обычно имеют разные цвета). Заметка кроме того, values также может использоваться для возврата нескольких значений.

(defun print-to-lines (slist)
  (cond
    ((null slist) (values))
    (t (write-line (car slist))
       (print-to-lines (cdr slist)))))

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

(defun print-to-lines (slist)
  (dolist (string slist)
    (write-line string)))

(defun print-to-lines (slist)
  (mapcar #'write-line slist))

(defun print-to-lines (slist)
  (format t "~{~a~%~}" slist))
5 голосов
/ 26 марта 2011

Вы можете использовать values без аргументов для возврата значений, т. Е. (values).

Более идиоматические версии вашей функции могут быть написаны с mapc или dolist вместо явной рекурсии (но вам все равно понадобится (values), потому что mapc возвращает список, а dolist возвращает nil) .

3 голосов
/ 26 марта 2011
1 голос
/ 26 марта 2011

Во-первых, в этом случае это не дополнительное возвращаемое значение. Вы печатаете на *STDOUT*, а repl также печатает на *STDOUT*, поэтому все выглядит так, как есть. Если бы ваша функция печатала вместо *FILE*, у вас не было бы этой проблемы.

ваш код возвращает ноль из-за третьей строки

1: (defun print-to-lines (slist)
2:   (cond
3:     ((null slist) slist)
4:     (t (let ((empty (write-line (car slist)))) (print-to-lines (cdr slist))))))

В случае, если slist равен нулю, вы возвращаете slist, следовательно, возвращаемое значение nul. Вы можете переписать функцию так, чтобы вместо возврата нулевого списка она возвращала другое значение (например, вызов функции для write-line или что-то подобное).

Дополнительно посмотрите в формате функцию .

0 голосов
/ 26 марта 2011

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

(defun print-to-lines (slist)
    (cond
        ((null (cdr slist)) (write-line (car slist)))
        (t (let ((empty (write-line (car slist)))) (print-to-lines (cdr slist))))))

Вот ссылка на него работает: http://ideone.com/tzZrm

Надеюсь, это поможет,

Jason

...