14 / 14 / 7
Регистрация: 11.05.2013
Сообщений: 225
|
||||||
1 | ||||||
SETQ не работает для безымянной функции26.08.2013, 23:27. Показов 2380. Ответов 25
Метки нет (Все метки)
В самоучителе по Лиспу нашел, что можно лямбда-функцию присвоить переменной, и вызывать как обычную функцию:
Цитата из самоучителя
Задание: "Определите функцию add5(n), которая увеличивает числовой параметр n на 5, используя синтаксис λ-определения". Мой код и реакция компилятора:
0
|
26.08.2013, 23:27 | |
Ответы с готовыми решениями:
25
Избавляемся от безымянной функции setf setq Вычисление функции не работает для отрицательных чисел Не работает шаблон функции для типа float |
Модератор
|
|||||||||||
26.08.2013, 23:42 | 2 | ||||||||||
Вот в чем дело. В Common Lisp (и в HomeLisp с ядром 13.x.x) так использовать setq-lambda не получится... Нужно так:
0
|
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
|
|
26.08.2013, 23:54 | 3 |
В Common Lisp два пространства имён: для переменных и для функций. В то же время функции - объекты первого класса, так что функция может быть значением переменной. Немного крышесносно.
Всякие "слова", которые вы пишете в программе (x, foo, let, setf и т. п.) - это символы, те самые, которые тип данных. С символом ассоциированы две "ячейки": для значения и для функции (value cell, function cell). Таким образом, символ может отдельно биндиться на значение и на некоторую функцию, которые никак не связаны друг с другом. Принципиальная разница видна из основного правила вычисления списка: при вычислении списка (foo bar baz) для foo берётся значение из функциональной ячейки, для bar и baz - из ячейки-значения. Когда вы используете setq, вы изменяете биндинг (я знаю, что там "ай", но на русский не ложится) ячейки-значения. Соответственно, когда вы пишете (add5 3), получается ошибка: ведь в функциональной ячейке add5 ничего нет! Если вы хотите сделать присваивание функциональной ячейке, можно сделать так: Код
(setf (symbol-function 'add5) #'(lambda ...)) Два пространства имён - это одна из фич CL, которые делают его более громоздким и временами более корявым. Однако если приноровиться, очень удобно.
1
|
14 / 14 / 7
Регистрация: 11.05.2013
Сообщений: 225
|
|
26.08.2013, 23:56 [ТС] | 4 |
К слову о Commo Lisp и HomeLisp. Я забыл сказать, что использую LispWorks. Тоже приношу извинения..
В LispWorks первый способ не работает. Проверил еще в двух онлайн-компиляторах (первый, второй), там тоже не работает. Оба компилятора показывают одну ошибку: FUNCALL: argument (LAMBDA (N) (SETQ N (+ N 5))) is not a function. To get a function in the current environment, write (FUNCTION ...). To get a function in the global environment, write (COERCE '... 'FUNCTION)
0
|
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
|
|
27.08.2013, 00:06 | 5 |
В схеме, конечно, set! (или define, если на верхнем уровне), и не нужна кавычка перед lambda.
Добавлено через 9 минут Когда setq-ите, пишите #'(lambda ... ). Шарп-кавычка обозначает взятие функционального содержимого. Впрочем, для лямбды можно и вовсе без кавычек. Кстати, setq морально устарел. А вы задумались, как на самом деле работает ваша функция?
0
|
Модератор
|
|
27.08.2013, 00:09 | 6 |
- естественно, т.к. LW - это Common Lisp
Добавлено через 1 минуту - но работает... - "... никакого самого дела нет" (В. Пелевин)
0
|
14 / 14 / 7
Регистрация: 11.05.2013
Сообщений: 225
|
||||||
27.08.2013, 00:17 [ТС] | 7 | |||||
Если я правильно понял, в одной переменной/символе могут лежать и значение переменной, и функция?
Не очень понимаю что вы имеете в виду, но скорее всего ответ "нет". Чуть изменил ваш вариант. Такой код
0
|
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
|
|
27.08.2013, 00:42 | 8 |
Точно. Например, вы определяете функцию
Код
(defun node ...) Когда вы вызываете функцию, внутри неё n биндится на аргумент: например, на 3. А присваиванием вы перебинживаете его на 8. Зачем??? К счастью, оператор присваивания в лиспе возвращает значение, которое и получается значением функции. То есть вы пишете присваивание, которое совсем не нужно и не используется, а пользуетесь только тем, что при присваивании возвращается "правая часть". Гораздо естественнее ту же функцию записать в виде Код
(lambda (n) (+ n 5)) Непонятно, почему. Кавычкой вы превратили список из лямбда-выражения в обычный список с символами и пр. - в данные.
1
|
Заблокирован
|
||||||
27.08.2013, 00:44 | 9 | |||||
я setq только с рекурсивными лямбдами применяю, когда лень функции писать
0
|
4486 / 2721 / 485
Регистрация: 28.04.2012
Сообщений: 8,590
|
|
27.08.2013, 01:21 | 10 |
На самом деле больше. То ли у Грэма, то ли в PCL был список, в общей сложности около семи.
В CL есть label для этого.
1
|
27.08.2013, 10:54 | 12 | |||||
Но почему, интересно же?! Ответ, что это не функция, меня не полностью устраивает. Добавлено через 19 минут Пока что остается успокоиться на том, что apply можно применять только к символу, который ранее определен как имя функции...
1
|
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
|
|
27.08.2013, 12:19 | 14 |
Ну так это и не функция. А список. С помощью большего числа кавычек, ваше значение add5 можно записать ('lambda ('n) ('setq 'n ('+ 'n 5))). То есть при выполнении присваивания ни lambda, ни + не имеют специального значения и выступают просто как символы.
Добавлено через 55 секунд И да, если вы вынуждены использовать eval, вероятно, вы что-то делаете не так.
2
|
Модератор
|
||||||
27.08.2013, 12:35 | 15 | |||||
Еще пару слов (HomeLisp-13)
1
|
14 / 14 / 7
Регистрация: 11.05.2013
Сообщений: 225
|
||||||
27.08.2013, 22:26 [ТС] | 18 | |||||
1.
В задании написано "увеличивает параметр на 5", вот я и сделал точно то, что написано в задании. Хотя я мог неправильно понять формулировку. И согласен, что так буквально не стоило воспринимать, тоже не вижу смысла в таком присваивании.
2. Что значит этот ответ компилятора? Возвращает адрес функции в памяти? "#<anonymous interpreted function 21BD975A>" Он отвечает так на вариант helter'а:
3. Всегда возвращает T. Возможно, разница в версиях? У меня 6.1.1 4. В "варианте LispWorks без #" мне тоже не нравится eval. Всем спасибо.
0
|
helter
|
27.08.2013, 22:31
#19
|
0
|
14 / 14 / 7
Регистрация: 11.05.2013
Сообщений: 225
|
||||||
27.08.2013, 22:37 [ТС] | 20 | |||||
Вы ведь сами уже ответили:
"первый способ" - это я писал про ваш способ в самом первом сообщении:
CLisp пробовал, не понравилась стилизация под командную строку)). LispBox не знаю что такое, но LispWorks меня пока вполне устраивает. Может как-нибудь посмотрю LispBox.
0
|
27.08.2013, 22:37 | |
27.08.2013, 22:37 | |
Помогаю со студенческими работами здесь
20
Работает ли onClick Input'a для вызова функции в коде бехайнд? Не работает нахождение СПМ для разной длинны окна (выделяющей функции) Составить программу для вычисления значения следующей функции, код работает некорректно Почему не работает программа-пример для демонстрации работы функции strcmp (из книги Шилдта)? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |