Я имею в виду это так:
<?php
$number1 = 5; // (Type 'Int')
$operator1 = +; // (Type non-existent 'Operator')
$number2 = 5; // (Type 'Int')
$operator2 = *; // (Type non-existent 'Operator')
$number3 = 8; // (Type 'Int')
$test = $number1 $operator1 $number2 $operator2 $number3; //5 + 5 * 8.
var_dump($test);
?>
Но и так:
<?php
$number1 = 5;
$number3 = 9;
$operator1 = <;
if ($number1 $operator1 $number3) { //5 < 9 (true)
echo 'true';
}
?>
Не похоже, что у каких-либо языков есть это - есть ли веская причина, почему они этого не делают?
programming-languages
variables
operators
kgongonowdoe
источник
источник
(+)
являетсяNum a => a -> a -> a
IIRC. Вы также можете определить функции, чтобы они могли быть записаны с инфиксом (a + b
вместо(+) a b
)Ответы:
Операторы - это просто функции под смешными именами с определенным синтаксисом.
Во многих языках, таких как C ++ и Python, вы можете переопределять операторы, переопределяя специальные методы вашего класса. Затем стандартные операторы (например
+
) работают в соответствии с логикой, которую вы предоставляете (например, объединение строк или добавление матриц или что-то еще).Поскольку такие функции, определяющие операторы, являются просто методами, вы можете передавать их как функцию:
Другие языки позволяют напрямую определять новые операторы как функции и использовать их в инфиксной форме.
К сожалению, я не уверен, что PHP поддерживает что-то подобное, и если это будет полезно, было бы хорошо. Используйте простую функцию, это более читабельно, чем
$foo $operator $bar
.источник
$
оператором, который устраняет скобки (особенно множественные вложенные) - но это может работать только с -вариантные функции, исключая, например, Python и Java. OTOH может быть сделано с помощью унарной функции .operator
модуль, который позволит вам писатьaction = operator.add
и работать с любым типом, который определяет+
(не толькоint
).+
работает с классом типов Num, поэтому вы можете реализовать его+
для любого нового типа данных, который вы создаете, но так же, как вы делаете что-либо еще, например, fmap для функтора. Для Haskell вполне естественно допустить перегрузку операторов, им придется много работать, чтобы не допустить этого!$operator1 = +
а затем использовать выражение, вам вообще не нужно использовать перегрузку операторов !Есть много языков, которые допускают какое-то метапрограммирование . В частности, я удивлен, что нет ответа, говорящего о семействе языков Lisp .
Из википедии:
Далее в тексте:
Лисп языки
Краткое введение в Lisp следует.
Один из способов просмотра кода - это набор инструкций: сделайте это, затем сделайте это, затем сделайте это другое ... Это список! Список вещей для программы, чтобы сделать. И, конечно, вы можете иметь списки внутри списков для представления циклов и так далее.
Если мы представим список , содержащий элементы а, Ь, с, d , как это: (ABCD) , мы получаем то , что выглядит как вызов функции Лиспа, где
a
есть функция, иb
,c
,d
являются аргументы. Если факт типичный "Hello World!" Программа может быть написана так:(println "Hello World!")
Конечно
b
,c
илиd
могут быть списки, которые также оценивают что-то. Следующее:(println "I can add :" (+ 1 3) )
напечатало бы «Я могу добавить: 4».Итак, программа - это серия вложенных списков, а первый элемент - это функция. Хорошей новостью является то, что мы можем манипулировать списками! Таким образом, мы можем манипулировать языками программирования.
Преимущество Лисп
В Лиспе не только намного проще создавать новые операторы, но также практически невозможно написать некоторые операторы на других языках, потому что аргументы оцениваются при передаче в функцию.
Например, на C-подобном языке, скажем, вы хотите написать
if
оператор самостоятельно, что-то вроде:my-if(condition, if-true, if-false)
my-if(false, print("I should not be printed"), print("I should be printed"))
В этом случае оба аргумента будут оценены и напечатаны в порядке, зависящем от порядка вычисления аргументов.
В Лиспе написание оператора (мы называем это макросом) и написание функции примерно одинаково и используются одинаково. Основное отличие состоит в том, что параметры макроса не оцениваются перед передачей в качестве аргументов в макрос. Это важно, чтобы иметь возможность писать некоторые операторы, как указано
if
выше.Языки реального мира
Здесь показано, как именно это немного выходит за рамки, но я призываю вас попробовать программирование на одном Лиспе, чтобы узнать больше. Например, вы можете взглянуть на:
Да, и, кстати, Lisp означает LISt Processing.
Что касается ваших примеров
Я собираюсь привести примеры, используя Clojure ниже:
Если вы можете написать
add
функцию в Clojure(defn add [a b] ...your-implementation-here... )
, вы можете назвать ее+
так(defn + [a b] ...your-implementation-here... )
. Это на самом деле то, что делается в реальной реализации (тело функции немного сложнее, но определение по сути такое же, как я писал выше).Как насчет инфиксной записи? Ну, Clojure использует
prefix
(или польскую) нотацию, поэтому мы могли бы создатьinfix-to-prefix
макрос, который превратил бы префиксный код в код Clojure. Что на самом деле удивительно легко (на самом деле это одно из макро упражнений в clojure koans)! Это также можно увидеть в дикой природе, например, см. Макрос Incanter$=
.Вот самая простая версия из объяснения коанов:
Чтобы продвинуться дальше, некоторые цитаты из Lisp :
источник
if
, но вы должны обернутьthen
иelse
аргументы с лямбды. PHP и JavaScript имеютfunction()
, C ++ имеет лямбды, и существует расширение Apple для C с лямбдами.В большинстве языковых реализаций есть шаг, на котором парсер анализирует ваш код и строит из него дерево. Так, например, выражение
5 + 5 * 8
будет проанализировано какблагодаря знаниям компилятора о приоритетах. Если вы передадите ему переменные вместо операторов, он не будет знать правильный порядок операций перед запуском кода. Для большинства реализаций это было бы серьезной проблемой, поэтому большинство языков не допускают этого.
Конечно, вы могли бы придумать язык, в котором анализатор просто анализирует вышеприведенное как последовательность выражений и операторов, которые будут отсортированы и оценены во время выполнения. Предположительно, просто не так много приложений для этого.
Многие языки сценариев позволяют оценивать произвольные выражения (или, по крайней мере, произвольные арифметические выражения, как в случае
expr
) во время выполнения. Там вы можете просто объединить свои числа и операторы в одно выражение и позволить языку оценить это. В PHP (и многих других) эта функция вызываетсяeval
.Есть также языки, которые позволяют генерировать код во время компиляции. На мой взгляд приходит миксиновское выражение в D , где я думаю, что вы могли бы написать что-то вроде
Здесь
operator1
иoperator2
должны быть строковые константы, которые известны во время компиляции, например параметры шаблона.number1
,number2
Иnumber3
были оставлены в качестве обычных переменных во время выполнения.В других ответах уже обсуждались различные способы, которыми оператор и функция являются более или менее одинаковыми в зависимости от языка. Но обычно существует синтаксическая разница между символом типа встроенного инфиксного оператора
+
и именованным вызываемым символомoperator1
. Я оставлю детали для тех других ответов.источник
eval()
языковой конструкцией » ... Технически это дает именно тот результат, который задан в вопросе.eval
не отвечает этому аспекту, поскольку дляeval
операторов это просто строки. Поэтому я начал с объяснения причин, по которым переменные операторного типа могут вызывать проблемы, прежде чем приступить к обсуждению альтернатив.У Алгола 68 была именно эта особенность. Ваш пример в Алголе 68 будет выглядеть так:
Ваш второй пример будет выглядеть так:
Вы заметите, что символы оператора определены и назначены тела методов, которые содержат желаемую операцию. Все операторы и их операнды напечатаны, и операторам могут быть назначены приоритеты, чтобы оценка происходила в правильном порядке. Вы также можете заметить, что есть некоторая небольшая разница в шрифтах между символом оператора и символом переменной.
На самом деле, хотя язык написан с использованием шрифтов, машины того времени не могли обрабатывать шрифты (бумажная лента и перфокарты), и использовалась обрезка . Программа, вероятно, будет введена как:
Вы также можете играть в интересные игры на языке, когда вы можете определить свои собственные символы для операторов, которые я использовал однажды, много лет назад ... [2].
Рекомендации:
[1] Неформальное введение в Алгол 68 Ч. Л. Линдси и С. Г. ван дер Мейленом, Северная Голландия, 1971 .
[2] Фразы Алгола 68, Инструмент для помощи в написании компилятора в Алголе 68 , BC Tompsett, Международная конференция по применению Алгола 68, в Университете Восточной Англии, Норвич, Великобритания, 1976 .
источник