Estoy aprendiendo Raku como un proyecto apasionante y quería implementar un fizzbuzz simple , ¿por qué join solo retiene el zumbido si escribo lambdas con bloques puntiagudos?
my $iif =-> $x,$y,$z {if $x {$y} else {$z}} my $modToString =-> $x,$y,$z {$iif($x%%$y,$z,'')} my $FB =-> $x {join($modToString($x,3,'fizz'),$modToString($x,5,'buzz'))} my $logic =-> $x {$iif($FB($x),$FB($x),$x)} say map(-> $x {$logic($x)}, 1..100) $modToString(1,3,'fizz') > $modToString(3,3,'fizz') > fizz $modToString(3,5,'buzz') > $modToString(5,5,'buzz') > buzzSi transformo las variables de bloques puntiagudos en variables de marcador de posición, Rakudo arroja un error:
my $iif = {if $^x {$^y} else {$^z}}; my $modToString = {$iif($^x%%$^y,$^z,'')}; my $FB = {join($modToString($^x,3,'fizz'),$modToString($^x,5,'buzz'))} my $logic = {$iif($FB($^x),$FB($^x),$^x)} say map(-> $x {$logic($x)}, 1..100) Too many positionals passed; expected 1 argument but got 3 in block at <unknown file> line 1 in block at <unknown file> line 1 in block at <unknown file> line 1 in block at <unknown file> line 1 in block <unit> at <unknown file> line 1Si pongo los corchetes alrededor de los argumentos de combinación, solo genera los números:
my $iif =-> $x,$y,$z {if $x {$y} else {$z}} my $modToString =-> $x,$y,$z {$iif($x%%$y,$z,'')} my $FB =-> $x {join(<$modToString($x,3,'fizz'),$modToString($x,5,'buzz')>)} my $logic =-> $x {$iif($FB($x),$FB($x),$x)} say map(-> $x {$logic($x)}, 1..100)¿Por qué?
Porque muchas cosas en Raku son bloques, incluso cosas que no lo parecen. En particular, esto incluye el "argumento" para controlar el flujo como if .
if 1 { 2 } else { 3 } De hecho, hemos escrito dos bloques aquí. Una es una función constante que devuelve 2 y la otra es una función constante que devuelve 3 . Ahora, por lo general, esto es transparente para nosotros y el motor Raku es lo suficientemente inteligente como para compilarlos. Pero todavía están allí. De hecho, podemos hacerlos explícitos. Lo siguiente se comporta de manera idéntica a la declaración if anterior.
if 1 -> { 2 } else -> { 3 } En tu caso, sin embargo, termina importando. Los argumentos anónimos (los que tienen ^ twigil) se unen al bloque más interno. Así que has escrito
{if $^x {$^y} else {$^z}}y pretendías que fuera equivalente a
-> $x, $y, $z {if $x {$y} else {$z}}pero lo que en realidad escribiste fue
-> $x {if $x -> $y {$y} else -> $z {$z}};Así que realmente escribió una función de un argumento y le pasó tres argumentos, como indica el mensaje de error.
Como regla general, generalmente puede asumir que cada vez que vea un { , comienza un hash literal o un bloque. Y este último siempre introduce un ámbito en el que pueden existir variables y argumentos locales.
En tu caso particular, puedes usar el ternario ??!! operador (esto es lo mismo que ?: en la mayoría de los otros lenguajes como C++ o Java)
{$^x ?? $^y !! $^z}Este operador no hace cortocircuito y no introduce bloques, por lo que funcionará bien.
Migración de la solución de OP de la pregunta a una respuesta.
¡Después de la respuesta de Silvio Mayolo entendí el problema y también señalaron que escribí un operador ternario sin sentido!
¡También escribí join en lugar de la tilde! Estoy feliz de decir que mi fizzbuzz ahora funciona:
my $modToString =-> $x,$y,$z {$x%%$y??$z!!''} my $FB =-> $x {$modToString($x,3,'fizz')~$modToString($x,5,'buzz')} my $logic =-> $x {$FB($x)??$FB($x)!!$x} say map(-> $x {$logic($x)}, 1..100)