Considere o seguinte:
if(a == b or c)
Na maioria dos idiomas, isso precisa ser escrito como:
if(a == b or a == c)
que é um pouco complicado e repete as informações.
Sei que minha sintaxe de amostra acima é um pouco desajeitada, mas tenho certeza de que existem maneiras melhores de transmitir a ideia.
Por que mais idiomas não oferecem isso? Há problemas de desempenho ou sintaxe?
a == b or c
, e nem mesmo parece bom com o IMHO.Respostas:
O problema da sintaxe é - que requer sintaxe.
Qualquer que seja a sintaxe do seu idioma, as pessoas que o usam precisam aprender. Caso contrário, eles correm o risco de ver o código e não saber o que ele faz. Portanto, geralmente é considerado bom se um idioma tiver uma sintaxe simples que lide com muitos casos.
No seu exemplo específico, você está tentando pegar um operador infix (uma função que aceita dois argumentos, mas está gravada
Argument1 Operator Argument2
) e tentando estendê-lo para vários argumentos. Isso não funciona de maneira muito limpa, porque todo o ponto dos operadores de infix, na medida em que existe um, é colocar o operador entre os dois argumentos. A extensão para(Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)
não parece acrescentar muita clarezaEquals(Arg1,Arg2,...)
. O Infix também é normalmente usado para emular convenções matemáticas com as quais as pessoas estão familiarizadas, o que não seria verdade para uma sintaxe alternativa.Não haveria nenhum problema específico de desempenho associado à sua ideia, além do fato de o analisador precisar lidar com uma gramática com outra regra de produção ou duas, o que pode ter um pequeno efeito na velocidade da análise. Isso pode fazer alguma diferença para uma linguagem interpretada ou compilada pelo JIT, mas provavelmente não uma grande diferença.
O maior problema com a idéia é que fazer muitos casos especiais em um idioma tende a ser uma má idéia .
fonte
.
. Então eles seriam escritos comoarg1 op (arg2, arg3)
. Não é exatamente bonito, mas é necessário em alguns lugares no contexto dessa linguagem.if my_var in (a, b)
então? isso não é mais uma questão de usar a ferramenta certa para o trabalho?a == b or c
enquanto outros querema == b or c but not d
. A IMO é onde as funções / bibliotecas utilitárias vêm em socorro.f().Equals(a,b,c)
; pode ser avaliado como(var temp=f(); temp.Equals(a)||temp.Equals(b)||temp.Equals(c))
essa sintaxe seria perfeita, mas se for avaliado comoint[] arr = {a,b,c}; f().Equals(arr);
isso não seria tão bom, especialmente se um novo array tiver que ser criado para cada chamada.Porque não é um problema, e resolvê-lo traz basicamente nenhum benefício, mas sua implementação traz um custo diferente de zero.
As funções existentes baseadas em intervalo e que praticamente todos os idiomas oferecem podem funcionar perfeitamente bem nessa situação se forem dimensionadas para um tamanho em
a == b || a == c
que não serão cortadas.fonte
in_array($a, [$b, $c, $d, $e, $f])
. : PAlguns idiomas possuem esses recursos. Por exemplo, no Perl6, podemos usar junções , que são "superposições" de dois valores:
As junções nos permitem expressar operações de um conjunto de dados de maneira bastante sucinta, semelhante à maneira como as operações escalares distribuem as coleções em alguns idiomas. Por exemplo, usando Python com numpy, a comparação pode ser distribuída por todos os valores:
No entanto, isso funciona apenas para tipos primitivos selecionados.
Por que as junções são problemáticas? Como as operações em uma junção distribuem sobre os valores contidos, o próprio objeto de junção se comporta como um proxy para chamadas de método - algo que poucos sistemas de tipos, além da digitação com patos, podem lidar.
Problemas no sistema de tipos podem ser evitados se tais junções forem permitidas apenas como sintaxe especial em torno dos operadores de comparação. Mas, neste caso, eles são tão limitados que não agregam valor suficiente para serem adicionados a qualquer linguagem sã. O mesmo comportamento pode ser expresso usando operações definidas ou explicitando manualmente todas as comparações, e a maioria dos idiomas não acredita em adicionar sintaxe redundante se já houver uma solução perfeitamente adequada.
fonte
2 in [1, 2, 3]
. Por outro lado, se numpy tem um.all()
ou algo assim, o python simples equivalente não é tão conciso.==
operador, também podemos usar<
- onde está o seuin
agora? As junções são mais gerais do que os testes de associação definidos, porque as operações na junção são distribuídas por todos os membros - ou(x|y).foo
sejax.foo|y.foo
, até que a junção seja finalmente recolhida para um único valor. O código NumPy fornecido mostra uma tradução exatamente equivalente, mas mais detalhada, das junções Perl6, assumindo tipos primitivos.Em idiomas com macros, é fácil adicionar algo assim se ainda não estiver lá. Considere Raquete
Em outros idiomas sem metaprogramação, talvez você possa reformular isso como verificação de associação de conjunto / lista, talvez:
fonte
Em alguns idiomas (populares), o
==
operador não é transitivo. Por exemplo, no JavaScript0
é igual a ambos''
e'0'
, mas então''
e'0'
não são iguais um ao outro. Mais dessas peculiaridades em PHP.Isso significa que
a == b == c
adicionaria outra ambiguidade, pois poderia gerar um resultado diferente, dependendo de ser interpretado como(a == b) & (a == c)
ou(a == b) & (a == c) & (b == c)
.fonte
Na maioria dos idiomas, isso deve ser trivialmente possível ao escrever uma
In
função; então, por que torná-la parte da linguagem real?Linq, por exemplo, tem
Contains()
.Tudo bem, para todos os pedantes, aqui está minha implementação em C #:
fonte
a == b || a == c
várias vezes, talvez seja hora paraequals_any(a, {b, c})
if (a > (b or c))
eif (a mod (b or c) == 2)
.i
variável. E, no geral, parece ter sido escrito depois de um longo dia :) Porque colocar aquireturn true
ereturn false
dentro do loop aqui significa que nunca haverá como ir além da primeira iteração. Você está apenas comparando com o primeirovalue
. By the way, por que não usarAny
como @Bob sugerido e simplificá-lo emreturn values.Any(value => Object.Equals(obj, value));
"if (a == b ou c)" funciona na maioria dos idiomas: se a == b ou se c não for negativo, nulo ou zero.
Reclamar que é detalhado erra o objetivo: você não deve acumular uma dúzia de coisas em uma condição. Se você precisar comparar um valor a um número arbitrário de outros valores, crie uma sub-rotina.
fonte
c
for avaliada como um booleano, em seguida, praticamente qualquer idioma pode lidara == b || c
:)if(a == b or c)
. Eu preciso fazer uma pausa, eu acho ...: Pif (a == b or c)
é um pseudocódigo para verificar sea
é igualb
oua
igual ac
. Não pretende verificar sec
é diferente de zero.Geralmente, você deseja manter sua sintaxe no mínimo e permitir que essas construções sejam definidas no próprio idioma.
Por exemplo, no Haskell, você pode converter qualquer função com dois ou mais argumentos em um operador infix usando backticks. Isso permite que você escreva:
onde
elem
é apenas uma função normal usando dois argumentos - um valor e uma lista de valores - e verifica se o primeiro é um elemento do segundo.E se você quiser usar em
and
vez deor
? No Haskell, você pode simplesmente usar o seguinte, em vez de esperar que o fornecedor do compilador implemente um novo recurso:fonte
Alguns idiomas oferecem isso - até certo ponto.
Talvez não seja o seu exemplo específico , mas tome por exemplo uma linha Python:
Portanto, alguns idiomas são adequados com várias comparações, desde que você a expresse corretamente.
Infelizmente, ele não funciona exatamente como você esperaria para comparações.
"O que você quer dizer ele retorna True ou 4?" - o aluguel depois de você
Uma solução nesse caso, pelo menos com o Python, é usá-lo de maneira um pouco diferente:
EDIT: O seguinte também faria algo semelhante, novamente em Python ...
Portanto, qualquer que seja o idioma que você esteja usando, pode não ser que você não consiga fazê-lo, apenas que você deve primeiro examinar mais de perto como a lógica realmente funciona. Normalmente, é apenas uma questão de saber o que você está 'realmente pedindo' o idioma para lhe dizer.
fonte
O método indexOf, usado em uma matriz, que quase todas as línguas têm, permite comparar um valor a várias outras, então acho que um operador especial não faz muito sentido.
Em javascript que escreveria:
fonte
Você pergunta por que não podemos fazer isso:
if(a == b or c)
O Python faz isso de maneira muito eficiente, de fato, com mais eficiência
set
:Para teste de associação, 'set' verifica se os hashes do elemento são iguais e só então compara a igualdade; portanto, os elementos, bec devem ser laváveis; caso contrário, uma lista compara diretamente a igualdade:
fonte
As linguagens no estilo APL permitem comparar um escalar com cada elemento em um vetor em uma única operação. Isso produz um vetor booleano. Por exemplo, gostaria de promover descaradamente a minha calculadora de aplicativos de recursos mínimos, o inca ( intérprete on-line ).
Para reduzir isso a um valor único, podemos fazer uma inclusão ou somar e verificar se há zero.
Portanto, como as outras respostas dizem, o problema é de sintaxe. Até certo ponto, as soluções de sintaxe ter sido encontrado, com o custo talvez pesada de aprender o paradigma matriz.
fonte