LINUX.ORG.RU

[CL] функции и макры


0

0

в каком-то эпическом лиспотреде этот вопрос уже поднимался, однако однозначного вывода я что-то не припомню. зачем в CL вообще существует разделение макр и функций? почему функции не являются просто нормальными макрами (макрами нулевого уровня, т.е. неразворачиваемыми во время компиляции)?

и, несколько по касательной к теме,- какой bit syntax вы считаете наиболее удобным? C-style, или какой другой (например, Erlang'овый)?

★★★★★
Ответ на: комментарий от guest-3484-2009

>Почему у сишных макросов нельзя взять адрес?

потому что у них нет адреса. они не попадают в таблицу символов, и не размещаются в сегменте кода процесса в отличие от функций

и что?

jtootf ★★★★★
() автор топика
Ответ на: комментарий от guest-3484-2009

в C функция и указатель на функцию - одно и то же; рантаймом выступает ядро ОС, системное понятие процесса накладывает вышеуказанные ограничения. в CL, насколько я понимаю, всё несколько иначе

короче говоря, можешь показать пример возможных проблем? т.е. CL'ный код, который внезапно перестанет работать от унификации функций и макр

jtootf ★★★★★
() автор топика

Ну как это зачем? Потому что это логические разные сущности.

Функцию можно применить к набору аргументов и получить результат, а макрос нельзя. Если ратуете за объединение, то опишите семантику funcall/apply и macroexpand-1 для макросов и функций. Очень было бы интересно.

Если функции (которые макросы нулевого уровня) не раскрываются во время компиляции, то получается немного непонятная семантика — ведь при компиляции получается AST, узлами в котором являются атомы или списки, в которых первым элементом идет либо function designator, либо специальный оператор. А вы предлагает добавить сюда нераскрытые макросы. Какова будет их семантика?

dmitry_vk ★★★
()
Ответ на: комментарий от jtootf

>пример возможных проблем?

Если объединить макросы и функции, то это сольет два пространства имен (функций и макросов) в одно пространство имен.

dmitry_vk ★★★
()
Ответ на: комментарий от dmitry_vk

>А вы предлагает добавить сюда нераскрытые макросы. Какова будет их семантика?

Да сделать просто: с учётом того, что функции макр возвращают список, фактически разделение идёт по границе: вставить в код вызов функции/вставить в код результат вызова функции во время компиляции. Не пойму - зачем?

yyk ★★★★★
()
Ответ на: комментарий от dmitry_vk

>Если объединить макросы и функции, то это сольет два пространства имен (функций и макросов) в одно пространство имен.

???

yyk ★★★★★
()

>и, несколько по касательной к теме,- какой bit syntax вы считаете наиболее удобным? C-style, или какой другой (например, Erlang'овый)?

а что такое bit syntax применительно к си? Я всегда считал это понятием из ерланга почему-то, да и сейчас погуглив опять все ссылки обнаружил на ерланг

cvb
()
Ответ на: комментарий от cvb

>а что такое bit syntax применительно к си? Я всегда считал это понятием из ерланга почему-то, да и сейчас погуглив опять все ссылки обнаружил на ерланг

операции с битами и байтами. то, что в C реализовано с помощью сдвигов, битовых масок и приведений типов

jtootf ★★★★★
() автор топика
Ответ на: комментарий от yyk

>Не пойму - зачем?

Затем, чтобы была возможность генерировать код во время компиляции.

Вы мне про семантику расскажите.

Вопрос первый. Если функции — это макросы, то что будет делать funcall, если ему передать функцию? И как ему вообще передать функцию, если функция — это макрос? То есть, funcall должен либо работать с произвольными макросами (что есть бред), либо funcall должен распознавать, что переданный ему макрос на самом деле не макрос, а функция (но тогда никакого объединения макросов и функций не происходило).

Вопрос второй. Есть (defun f (x y) (+ x y)), то во что выльется (macroexpand '(f 1 2)) ? И во что выльется (funcall #'f 1 2).

Вопрос третий. Чем будут являться лямбда-выражения? Тоже макросами?

В любом случае, получается ведь ясно, что макросы — совершенно отдельная от функций сущность.

dmitry_vk ★★★
()
Ответ на: комментарий от yyk

>>Если объединить макросы и функции, то это сольет два пространства имен (функций и макросов) в одно пространство имен. > ???

Немного спутал, почему-то показалось, что у символа может быть и макрос, и функция.

dmitry_vk ★★★
()
Ответ на: комментарий от dmitry_vk

>Если функции — это макросы, то что будет делать funcall, если ему передать функцию?

выполнять её, так как она является нормальным макросом, и развернуть её далее уже нельзя. не вижу существенных отличий от редукции в ФП (нормальная форма не редуцируется)

>funcall должен либо работать с произвольными макросами (что есть бред)

почему это бред?

>Есть (defun f (x y) (+ x y)), то во что выльется (macroexpand '(f 1 2)) ? И во что выльется (funcall #'f 1 2).

если унифицировать функции и макры, то никакого отдельного funcall уже не надо. или наоборот, никакого отдельного macroexpand не надо. т.е. пример неудачный

а во что выльется ясно - в вызов функции. во вставку адреса функции в объектный код, скажем так. ибо экспандить нечего. что-то вроде текущего сишного inline получится

>Чем будут являться лямбда-выражения? Тоже макросами?

да

>В любом случае, получается ведь ясно, что макросы — совершенно отдельная от функций сущность.

не, не ясно. во всех остальных языках ясно, а в CL как-то ни разу

jtootf ★★★★★
() автор топика
Ответ на: комментарий от dmitry_vk

>Затем, чтобы была возможность генерировать код во время компиляции.

Макры не справляются? =)

>Вопрос первый. Если функции — это макросы,


нет, почти наоборот - как уже заметили, у макр есть "исполняющие функции", которым, грубо говоря, передаются "заквоченные" аргументы, эти функции возвращают список, этот список заменяет в коде вызов макры.

Побалуйтесь с macroepand-1 (или как там его) - может и увидите что-нибудь "нужное".

yyk ★★★★★
()
Ответ на: комментарий от jtootf

>>В любом случае, получается ведь ясно, что макросы — совершенно отдельная от функций сущность.

>не, не ясно. во всех остальных языках ясно, а в CL как-то ни разу


если вспомнить, что #.(expression...) вычисляется ридером, то вызов макры

(defmacro add(x y)
`(+ ,x ,y))

вида (add x y) можно представить как

#.(funcall (macro-function 'add) '(add x y))

yyk ★★★★★
()
Ответ на: комментарий от yyk

>Макры не справляются? =)

Справляются. А справятся ли только функции? Очевидно, что нет.

> нет, почти наоборот - как уже заметили,

Я знаю, что функции — это не макросы. Я пытаюсь представить гипотетическую ситуацию, представляемую фразой "почему функции не являются просто нормальными макрами".

dmitry_vk ★★★
()
Ответ на: комментарий от dmitry_vk

Фактически макрос это функция, которая вызывается во время обхода(?) AST, и которая манипулирует AST. То есть просто специальный вид функций плюс макрорасширение вместо вызова.

Если ты объеденишь макросы и функции, то:
1] они будут в одном пространстве имен (что довольно неудобно).
2] ты сможешь использовать специфические для макросов конструкции в обычных функциях (а оно надо?).
3] придется ввести спецальную форму чтобы отличать расширение макроса от вызова функции (Oh no, no, please God help me!).

Вобщем объеденение функций и макросов привнесет определенные неудобства, но не даст никаких преимуществ (макросы позволяют вызывать функции).

>>почему функции не являются просто нормальными макрами

1] функции вычисляют свои аргументы.
2] функциям могут использовать свободные переменные.
3] рекурсия, взаимная рекурсия?


Если бы я знал матчасть, то наверное смог бы сказать что то полезное про суперкомпиляцию.

alex4
()
Ответ на: комментарий от dmitry_vk

>пытаюсь представить гипотетическую ситуацию, представляемую фразой "почему функции не являются просто нормальными макрами".

"Почему коровы не летают" было интереснее... "функции не являются просто нормальными макрами" потому, что макры - фактически сахар для вызова функций во время компиляции. А ты хочешь всё с ног на голову поставить.

yyk ★★★★★
()
Ответ на: комментарий от alex4

>Если ты объеденишь макросы и функции, то:
>1] они будут в одном пространстве имен (что довольно неудобно).

А они в разных? Где?

>2] ты сможешь использовать специфические для макросов конструкции в обычных функциях (а оно надо?).

`(,(bla-bla-bla) ,x ,y ,@z) и сейчас работает в теле функций. Или ты о чём-то другом?

>>>почему функции не являются просто нормальными макрами

>3] рекурсия, взаимная рекурсия?

Разве в макрах не работает?

yyk ★★★★★
()
Ответ на: комментарий от yyk

>>А они в разных? Где?

тупи@тормози

>>`(,(bla-bla-bla) ,x ,y ,@z) и сейчас работает в теле функций

надо же

>3] рекурсия, взаимная рекурсия?

а как это может там работать?

alex4
()
Ответ на: комментарий от alex4

точнее работает примерно таким образом:
(defmacro a (&rest x) 
  (let ((hd (first x)) 
	(tl (rest x))) 
    `'(,hd ,@(and tl 
                  (eval `(a ,@tl))))))
eval нужен, поскольку аргументы макроса не вычисляются

вобщем из недостатков объеденения функций и макросов остается только
1] нужен спецальный синтаксис, чтобы различать вызвов функции и расширение макроса

alex4
()
Ответ на: комментарий от alex4

>1] нужен спецальный синтаксис, чтобы различать вызвов функции и расширение макроса

причина? то, что у макроса нормальный порядок вычисления аргументов, а у функции аппликативный? ну давайте потеоретизируем о ленивом лиспе, в котором у функции тоже нормальный порядок

кстати, о хвалёной гибкости лиспа. можно ли средствами CL получить такой вот ленивый диалект? т.е. унифицировать макры и функции в рамках некоего почти-CL'ного eDSL?

jtootf ★★★★★
() автор топика
Ответ на: комментарий от alex4

>хотя, да, конечно может. но смысла наверное в этом нет.

Смысла наверное нет в твоих попытках "скрестить ужа с ежом" =)

yyk ★★★★★
()
Ответ на: комментарий от jtootf

>кстати, о хвалёной гибкости лиспа. можно ли средствами CL получить такой вот ленивый диалект?

Переписав ридер можешь сделать всё что хочешь. Возьмёшься?

yyk ★★★★★
()
Ответ на: комментарий от yyk

>Переписав ридер можешь сделать всё что хочешь. Возьмёшься?

попробую :)

jtootf ★★★★★
() автор топика
Ответ на: комментарий от jtootf

Ха, макросы вообще не вычисляют свои "аргументы".
Кстати, да. Сделать ленивые функции в лиспе было бы интересно.
Я тоже наверное буду делать, когда доучу CL.
И почему это нельзя сделать просто макросами?

alex4
()
Ответ на: комментарий от alex4

>Сделать ленивые функции в лиспе было бы интересно.

Да вроде не так уж и трудно: вызов ленивой функции - с "упаковкой" всех параметров в лямбды; объявление ленивой функции - с "упаковкой" параметров в макро-символы, которые будут вызывать замыкания, которые при первом вызове будут выполнять лямбды, в которые были упакованы параметры, а при повторных вызовах выдавать сохранённое значение (если это надо, или каждый раз "перевычислять" параметры - как сочтёте нужным)

Единственное - придётся переопределить funcall и apply.

yyk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.