Лисп/Функции: различия между версиями

17 байт добавлено ,  3 года назад
викификация, орфография
({{BookCat}})
(викификация, орфография)
<div style="max-width:60em;margin:1em auto 0 4%;">
Если вы уже знакомы с каким-нибудь алголоподобным языком типа [[Язык Си в примерах|Си]] или Пёрла, то понятие '''функции''' в Лиспе может показаться странным, но оно значительно ближе к математическому явлению функции, чем «функции» Си, которые вернее бы назвать более процедурами. Функция в Лиспе есть однозначное отображение множества исходных данных на множество её значений. У функции может быть произвольно много аргументов,  — от нуля до любого конечного числа,  — но обязательно должно быть хотя бы одно значение. Обычная для многих языков префиксная запись вызова функций:
<source lang=c>plus(2,2)</source>
несколько видоизменяется в силу отсутствия синтаксиса: идентификатор ("«имя"» функции, спецоператора или [[Лисп/Макросы|макровызова]]) становится головным элементом… да, списка:
<source lang=lisp>(plus 2 2)</source>
 
В чистом функциональном лиспе (являющемся строгим подмножеством любого из диалектов) функции не должны обладать [[w:Побочный_эффект_Побочный эффект (программирование)|побочным эффектом]], то есть изменять значения переменных с нелокальным состоянием. В противном случае, при нескольких вызовах одной функции могут быть получены разные значения, что запутывает любую сложную программную систему, и чего стремится избежать [[w:функциональное_программированиефункциональное программирование|функциональное программирование]].
 
Определение функции основано на [[w:Лямбда-исчисление|лямбда-исчислении]]. Исходный вариант записи лямбда-выражения, предложенный его автором [[w:Алонзо Чёрч|Чёрчем]], выглядит как
<math>\lambda(x_1,x_2...)fn</math>. Лисп-запись выглядит так: <code>(lambda (x1 x2 ...) fn)</code>. x1, x2 ... -… — свободные параметры, и, так, могут быть безболезненно заменены на другие без изменении значения лямбда-выражения.
 
Например, сумму квадратов на языке лямбда-выражений можно определить как <code>(lambda (x y) (+ (* x x) (* y y)))</code>. Вызов лямбда-функции с конкретными значениями <code>((lambda (x y) (+ (* x x) (* y y))) 2 3) => (+ (* 2 2) (* 3 3)) => 13</code> может быть сделан единожды, при желании вызвать такую функцию еще раз необходимо повторить запись еще раз. Это неудобно. Было бы удобнее написать нечто типа (сумма-квадратов 2 3). Это возможно, если вы предварительно определите функцию сумма-квадратов.
x y))
</source>
…но не пугайтесь: для удбстваудобства эта запись может быть сокращена до
<source lang="lisp">
(defun сумма-квадратов (x y)
(block сумма-квадратов (+ (* x x) (* y y)))>
</source>
Штрих перед названием функции поставлен неслучайно. В Лиспе любое имя соответствует некоторому символу. Имя функции - — не исключение, то есть значение символа «<code>сумма-квадратов</code>» - — не определение функции; оно неопределено, пока не будет присвоено вручную (например, через <code>setq</code>.) Штрих - — это сокращенная запись спецоператора <code>quote</code>, сообщающая интерпретатору, что нужно вывести имя данного символа без вычисления его значения.
<source lang="lisp">
>> (symbol-function сумма-квадратов) ; это выдаст ошибку: переменной сумма-квадратов не присвоено значение
93

правки