Eu falo assim:
<?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);
?>
Mas também desta maneira:
<?php
$number1 = 5;
$number3 = 9;
$operator1 = <;
if ($number1 $operator1 $number3) { //5 < 9 (true)
echo 'true';
}
?>
Parece que nenhum idioma tem isso - há uma boa razão para que eles não o façam?
programming-languages
variables
operators
kgongonowdoe
fonte
fonte
(+)
éNum a => a -> a -> a
IIRC. você também pode definir funções para que eles possam ser escritos infixada (a + b
em vez de(+) a b
)Respostas:
Operadores são apenas funções sob nomes engraçados, com alguma sintaxe especial por aí.
Em muitas linguagens, tão variadas quanto C ++ e Python, você pode redefinir os operadores substituindo métodos especiais da sua classe. Os operadores padrão (por exemplo
+
) trabalham de acordo com a lógica que você fornece (por exemplo, concatenando cadeias ou adicionando matrizes ou o que for).Como essas funções de definição de operador são apenas métodos, você pode transmiti-las como faria com uma função:
Outros idiomas permitem definir diretamente novos operadores como funções e usá-los no formato infix.
Infelizmente, não tenho certeza se o PHP suporta algo assim, e se o suporte seria uma coisa boa. Use uma função simples, é mais legível que
$foo $operator $bar
.fonte
$
operador que evita parênteses (especialmente vários aninhados) - mas isso só pode funcionar com não -variáveis, excluindo, por exemplo, Python e Java. A composição da função unária da OTOH pode ser bem feita .operator
módulo padrão que permite escreveraction = operator.add
e que funcione para qualquer tipo que defina+
(não apenasint
).+
funciona na classe Typ, para que você possa implementar+
qualquer novo tipo de dados criado, mas da mesma maneira que qualquer outra coisa, por exemplo, fmap para um functor. É um ajuste tão natural para Haskell permitir sobrecarregar o operador que eles teriam que trabalhar duro para não permitir!$operator1 = +
e usar uma expressão, você não precisa sobrecarregar o operador !Existem muitos idiomas que permitem algum tipo de metaprogramação . Surpreende-me, em particular, por não encontrar respostas sobre a família de idiomas Lisp .
Da wikipedia:
Mais adiante no texto:
Línguas Lisp
Uma rápida introdução inventada para Lisp segue.
Uma maneira de ver o código é como um conjunto de instruções: faça isso, depois faça isso e faça outra coisa ... Esta é uma lista! Uma lista de coisas para o programa fazer. E é claro que você pode ter listas dentro de listas para representar loops e assim por diante.
Se nós representamos uma lista contendo os elementos a, b, c, d como este: (ABCD) obtemos algo que se parece com uma chamada de função Lisp, onde
a
é a função, eb
,c
,d
são os argumentos. Se fato o típico "Olá Mundo!" programa poderia ser escrito assim:(println "Hello World!")
Obviamente
b
,c
oud
podem ser listas que avaliam algo também. O seguinte:(println "I can add :" (+ 1 3) )
imprimiria "" posso adicionar: 4 ".Portanto, um programa é uma série de listas aninhadas e o primeiro elemento é uma função. A boa notícia é que podemos manipular listas! Para que possamos manipular linguagens de programação.
A vantagem do Lisp
Isso não é apenas muito mais fácil no Lisps para criar novos operadores, também é quase impossível escrever alguns operadores em outros idiomas porque os argumentos são avaliados quando passados para a função.
Por exemplo, em uma linguagem C, digamos que você queira escrever um
if
operador, algo como:my-if(condition, if-true, if-false)
my-if(false, print("I should not be printed"), print("I should be printed"))
Nesse caso, os dois argumentos serão avaliados e impressos, em uma ordem dependente da ordem de avaliação dos argumentos.
No Lisps, escrever um operador (chamamos de macro) e escrever uma função são sobre a mesma coisa e são usados da mesma maneira. A principal diferença é que os parâmetros para uma macro não são avaliados antes de serem passados como argumentos para a macro. Isso é essencial para poder escrever alguns operadores, como o
if
acima.Idiomas do mundo real
Mostrando exatamente como está um pouco fora do escopo aqui, mas encorajo você a tentar programar em um Lisp para saber mais. Por exemplo, você pode dar uma olhada em:
Ah, a propósito, Lisp significa LISt Processing.
Em relação aos seus exemplos
Vou dar exemplos usando o Clojure abaixo:
Se você pode escrever uma
add
função no Clojure(defn add [a b] ...your-implementation-here... )
, pode nomeá-la+
assim(defn + [a b] ...your-implementation-here... )
. Na verdade, é isso que é feito na implementação real (o corpo da função é um pouco mais envolvido, mas a definição é essencialmente a mesma que escrevi acima).E a notação infix? Bem, o Clojure usa uma
prefix
notação (ou polonesa), para que pudéssemos criar umainfix-to-prefix
macro que transformasse o código prefixado em código Clojure. O que é surpreendentemente fácil (na verdade, é um dos exercícios de macro nos koans do clojure)! Também pode ser visto na natureza, por exemplo, veja a macro Incanter$=
.Aqui está a versão mais simples dos koans explicados:
Para aprofundar ainda mais, algumas citações do Lisp :
fonte
if
, mas seria necessário agrupar os argumentosthen
eelse
com lambdas. PHP e JavaScript possuemfunction()
, C ++ possui lambdas e existe uma extensão da Apple para C com lambdas.A maioria das implementações de idiomas possui uma etapa em que um analisador analisa seu código e cria uma árvore a partir dele. Por exemplo, a expressão
5 + 5 * 8
seria analisada comograças ao conhecimento do compilador sobre precedências. Se você alimentasse variáveis no lugar de operadores, ele não saberia a ordem correta das operações antes de executar o código. Para a maioria das implementações, isso seria um problema sério; portanto, a maioria dos idiomas não permite isso.
É claro que você poderia conceber uma linguagem em que o analisador apenas analise o acima como uma sequência de expressões e operadores, para ser classificado e avaliado em tempo de execução. Presumivelmente, não há muita aplicação para isso.
Muitas linguagens de script permitem a avaliação de expressões arbitrárias (ou pelo menos expressões aritméticas arbitrárias, como no caso de
expr
) em tempo de execução. Lá, você pode combinar seus números e operadores em uma única expressão e deixar o idioma avaliar isso. No PHP (e muitos outros), essa função é chamadaeval
.Existem também idiomas que permitem a geração de código em tempo de compilação. A expressão mixin em D vem à minha mente, onde acredito que você poderia escrever algo como
Aqui
operator1
eoperator2
teria que haver constantes de string conhecidas em tempo de compilação, por exemplo, parâmetros do modelo.number1
,number2
Enumber3
foram deixados como variáveis de tempo de execução normais.Outras respostas já discutiram as várias maneiras pelas quais um operador e uma função são mais ou menos a mesma coisa, dependendo do idioma. Mas geralmente há uma diferença sintática entre um símbolo de operador de infixo interno
+
e um nome de chamada chamadooperator1
. Deixarei os detalhes para essas outras respostas.fonte
eval()
construção da linguagem " ... Tecnicamente, ele fornece exatamente o resultado desejado solicitado na pergunta.eval
não responde a esse aspecto, poiseval
os operadores são apenas strings. Portanto, comecei com uma explicação de por que variáveis do tipo operador causariam problemas antes de começar a discutir alternativas.Algol 68 tinha exatamente essa característica. Seu exemplo em Algol 68 ficaria assim:
Seu segundo exemplo ficaria assim:
Você notará que os símbolos do operador são definidos e são atribuídos corpos de método que contêm a operação desejada. Os operadores e seus operandos são todos digitados e os operadores podem ter prioridades atribuídas para que a avaliação ocorra na ordem correta. Você também pode notar que há uma pequena diferença na fonte entre o símbolo do operador e um símbolo variável.
Na verdade, embora o idioma seja escrito usando fontes, as máquinas do dia não podiam lidar com as fontes (fita de papel e cartões perfurados), e o uso de stropping era usado. O programa provavelmente seria inserido como:
Você também pode jogar jogos interessantes com a linguagem quando pode definir seus próprios símbolos para operadores, que eu explorei uma vez, há muitos anos ... [2].
Referências:
[1] Introdução informal a Algol 68 por CHLindsey e SG van der Meulen, Holanda do Norte, 1971 .
[2] Algol 68 Phrases, Uma ferramenta para auxiliar na redação de compiladores em Algol 68 , BC Tompsett, Conferência Internacional sobre Aplicações de Algol 68, na Universidade de East Anglia, Norwich, Reino Unido, 1976 ..
fonte