Сегодня небольшой обзор переменных, областей видимости и типов данных. Не смотря на то, что lisp это динамически-типизированный язык и, по сути все переменные это ссылки на значения, у значений есть тип. А значит стоит об этом знать. Теперь обо всё по порядку.
Переменные и области видимости
Переменные бывают глобальные, лексические и динамические. Глобальные объявляются так:
(defvar *a* 1) (defparameter *b* 2)
Разница тут в том, что если *b* была объявлена, то её значение поменяется, а у *a* оно изменится лишь в случае если *a* не было ранее.
Лексические переменные объявляются так:
(let ((var1 value1) (var2 value2)) body) (let* ((var1 value1) (var2 var1)) body)
Разница здесь в том, что в let со звёздочкой первые переменные видны следующим. Как будто это много вложенных let.
И, наконец, динамические. Это тоже что и лексические, но называться они будут так как глобальные.
(defvar *a* 5) (defun foo () (print *a*)) (defun baz () (foo) (let ((*a* 12)) (foo)) (foo))
Данный код выведет 5, 12, 5. Что было бы удивительно в других языках. Т.е. переменная в let скрывает глобальную. Когда мы выходим из let, то глобальную снова видно. Вот такая магия.
Ещё одна магия это замыкания:
(let ((count 5)) #'(lambda () (incf count)))
Данный блок возвращает анонимную функцию, которая работает с переменной count. Как ни странно, из блока мы вышли, а доступ к ней всё ещё есть. Это не баг, а фича функциональных языков.
Константы
Константы в lisp тоже есть, а как же без них! Задаются довольно просто:
(defconstant +name+ (init-form) "Description")
Символы плюса — это менее строгое соглашение по именованию констант. Строку с описанием можно опускать.
Переменные и типы данных
Кратко про типы данных. Числа могут быть рациональными или с плавающей точкой. Примеры:
;;Рациональные 10 ;10 1/2 ;1/2 #xA ;10 #o12 ;10 #b1010 ;10 #9r11 ;10 2-36r ;;С плавающей точкой 1d0 ;1.0d0 123d20 ;1.23d+22 .12 ;0.12 123e-3 ;0.123
Для чисел с плавающей точкой есть несколько префиксов — s(single), f(float), d(double), l(long), e(default = single). Эти префиксы задают точность.
Ещё один тип чисел — комплексные задаются через #c
#c(1 2) ;#c(1 2) #c(1d 2.1d) ;#c(1.0d0 2.1d0)
Математические операции
Над числами можно совершать математические операции, сразу напишу примеры для базовых операций и операций округления. Функции высшей математики синусы/косинусы тоже есть, но их перечень давать трудозатратно.
(+ 10 15) ;сложение (- 10 15) ;вычитание (* 10 15) ;умножение (/ 10 15) ;деление ;;округление (floor (/ 7 6)) ;1 (ceiling (/ 7 6)) ;2 (truncate (/ 7 6)) ;1 (round (/ 7 6)) ;1 ;;модуль и остаток (mod 7 6) ;1 (rem 7 6) ;1 (mod -7 6) ;5 (rem -7 6) ;-1
я могу именовать глобальные переменные без звёздочек?
Да, это только соглашение, которое не является обязательным. Однако, лучше ему следовать, для большего порядка в программах