О намерениях. Данная компиляция не стремиться убедить вас использовать
Common Lisp. Не хотите - не используйте. Нам же лучше.
Адресовано в большей степени программистом, которые хотят понять, что
в лиспе есть такого, чего нет в других языках. Буду теперь посылать их
всех сюда.
## Синтаксис.
Он отличается, то что вы пишете как
function add(x, y) {
return x+y
}
в Common Lisp записывается как
(defun add (x y)
(+ x y))
К этому можно быстро привыкнуть, а вознаграждение в том, что такая
запись позволяет легко и удобно заниматься метапрограммированием.
## Арифметика.
(+ 5/9 3/4) будет равно 47/36 а не 1.30555556
Это позволяет избегать многих ошибок округления. Разрядная сетка
увеличивается автоматически.
## Places
Forms и places можно рассматривать как если бы они были конкретными,
изменяемыми переменные и присваивать им значения. Проиллюстрирую это
на алгол-подобном языке
a = ['red' 'green' 'blue'];
first(a); // выведет 'red'
first(a) = 'yellow';
first(a); // теперь выведет 'yellow'
На лиспе это записывается так:
(defvar *colours* (list "red" "green" "blue"))
(first *colours*) ;; выведет "red"
(setf (first *colours*) "yellow")
(first *colours*) ;; выведет "yellow"
## Множественные значения
Изучая ассемблер, в частности соглашения о вызовах си-функций, я
недоумевал - кто это решил, что функция должна возвращать только одно
значение? Никаких аппаратных ограничений на это ведь нет. В Common
Lisp функция может возвращать сколько угодно значений. В переводе на
алгол-подобный язык это было бы так:
func(param) {
return (param*3) (param*6)
}
a, b = func(5)
а на Common Lisp это будет вот так
(defun func (param)
(values (* 3 param) (* 6 param)))
(multiple-value-bind (a b)
(func 5))
Теперь не нужно строить структуру данных, когда вы просто хотите
возвратить чуточку больше чем собирались ранее.
## Макросы
Макрос в Common Lisp это функция, возвращающая код, который после
возврата будет немедленно скомпилирован и исполнен в контексте вызова
макроса. Думаю не нужно объяснять, какие возможности это открывает при
умелом применении для метапрограммирования.
## Функции как сущности первого класса
На практике это означает, что можно создавать функции динамически,
передавать их в качестве аргументов и возвращать их из других
функций. Экономит кучу времени и ресурсов мышления.
## Анонимные функции и лексические замыкания
Это функции без имени, объявленные и использованные в контексте
объявления. Например вот так мог бы выглядеть некий вызвов функции
сортировки слов, где мы создаем анонимную функцию, прямо в контексте
вызова, которая возвращает true или false в зависимости от результата
сравнения a и b:
sort_words("one two alfa beta",
create_function(a, b)
{...});
А на лиспе это еще проще:
(sort-words "one two alfa beta"
(lambda (a b)
...))
## Необязательные и именованные параметры
Вы можете использовать не только необязательные параметры в своих
функциях, но и именованные параметры, как если бы вы писали так:
func(a, b="default value", с:key="alfa") {
...
}
Здесь a - обязательный параметр, b - необязательный, а c -
именованный. Если вы вызовете функцию так:
func(1, key:2)
то внутри функции a будет равно 1, b - "default value", а c - 2. На
лиспе это будет выглядеть вот так:
(defun func (a &optional b &key (key "alfa"))
...)
Указывать значения по умолчанию для ключевых параметров
необязательно. Вы так же можете создавать функци и с неопределенным
количеством параметров, добавляя модификатор &rest - все параметры
сверх попадут в него:
(defun func (a &optional b &key (key "alfa") &rest other-args)
...)
Использование ключевых параметров повышает читабельность, сравните эти
два вызова:
(xf86InitValuatorAxisStruct device, 0, 0, -1, 1, 0, 1))
и
(xf86-init-valuator-axis-struct :dev device :ax-num 0
:min-val 0 :max-val -1
:min-res 0 :max-res 1
:resolution 1)
Многое еще осталось неупомянутым, но сегодня я уже не нахожу в себе
силы закончить. Продолжение следует, а самые нетерпеливые могут
обратиться к первоисточнику тут:
http://abhishek.geek.nz/docs/features-of-common-lisp Буду также очень благодарен всем, кто исправит ошибки.