Особенности Common Lisp

Jan 21, 2010 05:56



О намерениях. Данная компиляция не стремиться убедить вас использовать
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

Буду также очень благодарен всем, кто исправит ошибки.

lisp

Previous post Next post
Up