Вы имеете в виду мета-циклические оценщики, как в SICP? Будучи в состоянии написать свой собственный DSL? Если вы создадите свой собственный «тип функции», вам придется самостоятельно позаботиться о его «применении».
Например, вы можете создать свою собственную "функцию" в C, например, с помощью справочной таблицы, содержащей указатели на функции, и использовать целые числа в качестве функций. Конечно, для таких «функций» вам придется предоставить собственную функцию «вызова»:
void call( unsigned int function, int data) {
lookup_table[function](data);
}
Возможно, вам также понадобятся некоторые средства для создания более сложных функций из примитивных, например, использование массивов целых чисел, чтобы обозначить последовательное выполнение ваших "примитивных функций" 1, 2, 3, ...
и в итоге вы придумаете для себя совершенно новый язык.
Я думаю, что ранние ассемблеры не могли создавать вызываемые "макросы" и должны были использовать GOTO.
Вы можете использовать trampolining для имитации вызовов функций. У вас может быть только глобальное хранилище переменных, возможно, с поверхностное связывание . В таком языке «функции» были бы определяемыми, хотя и не примитивного типа.
Таким образом, наличие функций на языке не является необходимым, хотя это удобно .
В Common Lisp defun
- это не что иное, как макрос, связывающий имя и вызываемый объект (хотя lambda
все еще является встроенным). Изначально в AutoLisp вообще не было специального типа функции, и функции представлялись непосредственно в кавычках списков s -выражений, с первым элементом в arguments list. Вы можете создать свою функцию, используя функции cons
и list
, непосредственно из символов в AutoLisp:
(setq a (list (cons 'x NIL) '(+ 1 x)))
(a 5)
==> 6
Некоторые языки (например, Python) поддерживают более одного примитивного типа функции, каждый со своим протоколом вызова, а именно, генераторы поддерживают множественный повторный ввод и возврат (даже если синтаксически с использованием одного и того же ключевого слова def
). Вы можете легко представить себе язык, который позволил бы вам определять собственный протокол вызова, создавая новые типы функций.
Редактировать: в качестве примера рассмотрим работу с несколькими аргументами в вызове функции, выбор между автоматическим каррированием или автоматическими необязательными аргументами и т. Д. В Common LISP, например, вы можете легко создать себе два разных call
макросы для непосредственного представления двух протоколов вызова. Рассмотрим функции, возвращающие множественные значения не через кучу агрегатов (кортежей в Haskell), а непосредственно в назначенные переменные / слоты получателя. Все это разные типы функций.