Redefinir operadores para definir funções
A redefinição de operadores pode salvar muitos bytes entre parênteses e vírgulas.
Operadores unários recursivos
Para um exemplo unário, compare as seguintes implementações recursivas da sequência de Fibonacci:
F(n)=n>1?F(n-1)+F(n-2):n # 24 bytes
!n=n>1?!~-n+!(n-2):n # 20 bytes
!n=n>1?!~-n+!~-~-n:n # 20 bytes
Experimente online!
O operador redefinido mantém sua precedência inicial.
Note que não poderíamos simplesmente trocar a !
favor de ~
, uma vez que ~
já está definido para números inteiros, enquanto !
está definido apenas para booleanos.
Operadores binários
Mesmo sem recursão, redefinir um operador é mais curto do que definir uma função binária. Compare as seguintes definições de um teste de divisibilidade simples.
f(x,y)=x==0?y==0:y%x==0 # 23 bytes
(x,y)->x==0?y==0:y%x==0 # 23 bytes
x->y->x==0?y==0:y%x==0 # 22 bytes
x\y=x==0?y==0:y%x==0 # 20 bytes
Experimente online!
Operadores binários recursivos
A seguir, ilustra como redefinir um operador binário para calcular a função Ackermann:
A(m,n)=m>0?A(m-1,n<1||A(m,n-1)):n+1 # 35 bytes
^ =(m,n)->m>0?(m-1)^(n<1||m^~-n):n+1 # 36 bytes
| =(m,n)->m>0?m-1|(n<1||m|~-n):n+1 # 34 bytes
m\n=m>0?~-m\(n<1||m\~-n):n+1 # 28 bytes
Experimente online!
Observe que ^
é ainda mais longo do que usar um identificador comum, pois sua precedência é muito alta.
Como mencionado anteriormente
m|n=m>0?m-1|(n<1||m|~-n):n+1 # 28 bytes
não funcionaria para argumentos inteiros, pois |
já está definido neste caso. A definição para números inteiros pode ser alterada com
m::Int|n::Int=m>0?m-1|(n<1||m|~-n):n+1 # 38 bytes
mas isso é proibitivamente longo. No entanto, ele faz o trabalho se passar por um flutuador como argumento esquerda e um número inteiro como argumento direita.