Поиск…


Условные конструкции

В Common Lisp, if это простейшая условная конструкция. Она имеет вид (if test then [else]) , then test else (if test then [else]) и оценивается на then , если test верно и else иначе. Часть else может быть опущена.

(if (> 3 2)
    "Three is bigger!"
    "Two is bigger!")
;;=> "Three is bigger!"

Одно очень важное различие между if в Common Lisp и, if во многих других языках программирования, это CL, if это выражение, а не утверждение. Таким образом, if формы возвращают значения, которые могут быть назначены переменным, используемые в списках аргументов и т. Д .:

;; Use a different format string depending on the type of x
(format t (if (numberp x)
              "~x~%"
              "~a~%")
           x)

Общий Lisp, if можно считать эквивалентным тернарному оператору?: В C # и других языках «фигурных скобок».

Например, следующее выражение C #:

year == 1990 ? "Hammertime" : "Not Hammertime"

Является эквивалентом следующего кода Common Lisp, считая, что year содержит целое число:

(if (eql year 1990) "Hammertime" "Not Hammertime")

cond - еще одна условная конструкция. Он несколько похож на цепочку операторов if и имеет вид:

(cond (test-1 consequent-1-1 consequent-2-1 ...)
      (test-2)
      (test-3 consequent-3-1 ...)
      ... )

Точнее, cond имеет нулевые или более предложения , и каждое предложение имеет один тест, за которым следуют ноль или более последовательных. Вся конструкция cond выбирает первое предложение, тест которого не оценивается в nil и оценивает его последующие порядки. Он возвращает значение последней формы в последующих.

(cond ((> 3 4) "Three is bigger than four!")
      ((> 3 3) "Three is bigger than three!")
      ((> 3 2) "Three is bigger than two!")
      ((> 3 1) "Three is bigger than one!"))
;;=> "Three is bigger than two!"

Чтобы предоставить предложение по умолчанию, чтобы оценить, не оценивает ли другое предложение значение t , вы можете добавить предложение, которое истинно по умолчанию, используя t . Это очень похоже на концепцию SQL CASE...ELSE , но для выполнения задачи используется буквальное логическое значение true, а не ключевое слово.

(cond
    ((= n 1) "N equals 1")
    (t "N doesn't equal 1")
)

Конструкция if может быть записана как cond конструкция. (if test then else) и (cond (test then) (t else)) эквивалентны.

Если вам нужно только одно предложение, используйте, when или unless :

(when (> 3 4)
  "Three is bigger than four.")
;;=> NIL

(when (< 2 5)
  "Two is smaller than five.")
;;=> "Two is smaller than five."

(unless (> 3 4)
  "Three is bigger than four.")
;;=> "Three is bigger than four."

(unless (< 2 5)
  "Two is smaller than five.")
;;=> NIL

Цикл do

Большинство циклов и условных конструкций в Common Lisp на самом деле являются макросами, которые скрывают более основные конструкции. Например, dotimes и dolist построены на do макрос. Форма для do выглядит так:

(do (varlist)
    (endlist)
   &body)
  • varlist состоит из переменных, определенных в цикле, их начальных значений и того, как они меняются после каждой итерации. Часть «изменения» оценивается в конце цикла.
  • endlist содержит конечные условия и значения, возвращаемые в конце цикла. Конечное условие оценивается в начале цикла.

Вот один, который начинается с 0 и идет вверх (не включая) 10.

;;same as (dotimes (i 10)) 
(do (( i (+ 1 i))
    ((< i 10) i)
   (print i))

И вот тот, который перемещается по списку:

;;same as (dolist (item given-list)
(do ((item (car given-list))
     (temp list (cdr temp))
   (print item))

Часть varlist похожа на varlist в инструкции let . Вы можете связывать более одной переменной, и они существуют только внутри цикла. Каждая объявленная переменная находится в своем собственном наборе скобок. Вот один из них, который подсчитывает количество 1 и 2 в списке.

(let ((vars (list 1 2 3 2 2 1)))
  (do ((ones 0)
       (twos 0)
       (temp vars (cdr temp)))
      ((not temp) (list ones twos))
    (when (= (car temp) 1)
      (setf ones (+ 1 ones)))
    (when (= (car temp) 2)
      (setf twos (+ 1 twos)))))
-> (2 3)

И если макрос цикла while не был реализован:

(do ()
    (t)
  (when task-done
    (break)))

Для наиболее распространенных приложений более конкретные dotimes и doloop макросы гораздо более кратки.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow