• Publicidad

6 primitivas de Perl 6 que no sabías que necesitabas

¿Tienes algo interesante que decir? ¿O quizá algo no tan interesante? Aquí tenemos un espacio para compartir todo lo que queramos decir y que no cabe en ninguno de los otros foros.

6 primitivas de Perl 6 que no sabías que necesitabas

Notapor explorer » 2010-07-25 17:08 @756

.pick
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
    say @mazo.pick();                   # escoge una carta, cualquier carta...

    say @mazo.pick(5);                  # mano de poker

    my @barajado = @mazo.pick(*);       # aquí, '*' significa 'sigue adelante'
                                        # Quiere decir que extraemos todas las cartas del mazo,
                                        # de forma aleatoria, y las guardamos en @barajado

    my @urna = <negra blanca blanca>;   # cuentas de colores, 1/3 negras, 2/3 blancas
    .say for @urna.pick(50, :replace);  # devolvemos a la urna la cuenta extraída
                                        # Quiere decir que hacemos 50 extracciones de cuentas de colores,
                                        # decimos de qué color es la bolita, y la devolvemos a la @urna


    for @urna.pick(*, :replace) {
        .say;                           # infinito extractor de cuentas de colores
    }

    say [+] (1..6).pick(4, :replace);   # Extrae cuatro números de la lista del 1 al 6, y nos da la suma de ellos

    class Enemigo {                                            # definimos la clase Enemigo
        method atacar-con-flechas  { say "piou piou piou"    } # con una serie de métodos,
        method atacar-con-espadas  { say "swish cling clang" } # que en realidad son estrategias
        method atacar-con-rayos    { say "sssSSS fwoooof"    } # de combate, usando nuestras armas,
        method atacar-con-camelia  { say "flap flap ¡RAWWR!" } # incluida nuestra mariposa más mortífera
    }

    my $selector = { .name ~~ /^ 'atacar-con-' / };            # expresión regular que define a los métodos de ataque
    given Enemigo.new -> $e {                                  # creamos un nuevo Enemigo, $e
        my $atacar-estrategia                                  # elegimos una estrategia de ataque
            = $e.^methods().grep($selector).pick();            # eligiendo al azar (pick()) de entre todos
                                                               # los métodos de Enemigo que sean para atacar

        $e.$atacar-estrategia;                                 # atacamos al enemigo con esa estrategia
    }
 
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


.classify
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
    my @nombres = <Patrick Jonathan Larry Moritz Audrey>;
    say .key, "\t", ~.values              # ordenamos los nombres por número de caracteres
        for @nombres.classify( *.chars );

    # Salida:
    # 5       Larry
    # 6       Moritz Audrey
    # 7       Patrick
    # 8       Jonathan

    .say for slurp("README")\              # leemos todo el fichero
         .words()\                         # dividimos en una lista de palabras
         .classify( *.Str )\               # agrupamos las palabras según las veces que aparecen,
                                           # es decir, el primer elemento de la lista es la palabra,
                                           # y el segundo elemento es un array con todas las veces
                                           # que aparece en el texto
         .map({; .key => .value.elems })\  # lo convertimos a hash palabra => número de veces
         .sort( { -.value } )\             # ordenamos por esos valores, de forma descendente
         .[ ^10 ];                         # y nos quedamos con las 10 palabras más comunes

    class Estudiante {                     # Un estudiante
        has Str $.nombre;                  # que tiene un nombre
        has Int $.grado is rw;             # y una graduación
    }

    my Estudiantes @estudiantes = obtener-estudiantes();       # Obtenemos la lista de estudiantes
    for @estudiantes.classify( *.grado ).sort -> $grupo {      # Para todos ellos, los ordenamos por
                                                               # su nivel de graduación. $grupo es un
        say "Estos estudiantes tienen el grado $grupo.key():"; # hash cuya clave es el grado, y el valor
        say .nombre for $grupo.value.list;                     # la lista de estudiantes
    }
 
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


.sort
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
# 1 si $a es mayor, -1 si $b es mayor, 0 si son iguales
$a <=> $b;

# ordenar estudiantes de acuerdo a su grado
@estudiantes.sort: -> $a, $b { $a.grado <=> $b.grado };

# lo mismo
@estudiantes.sort: { $^a.grado <=> $^b.grado };

# lo mismo
@estudiantes.sort: { .grado };

# lo mismo
@estudiantes.sort: *.grado;

# leg da -1, 0 o 1 de acuerdo a una ordenación léxico-gráfica
# 'leg' es para Str, 'cmp' es ahora un 'sort' independiente del tipo
$a leg $b;

# ordena estudiantes por nombre (orden Unicode)
@estudiantes.sort: { $^a.nombre leg $^b.nombre };

# lo mismo
@estudiantes.sort: *.nombre;

# no te preocupes, los cálculos son almacenados, por lo que no hay reevaluaciones
@elementos.sort: *.calculo-extensivo();

# ... que quiere decir que esto funciona (y es un buen barajado)
@mazo.sort: { rand }

# ... pero este es más lindo :)
@mazo.pick(*);
 
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Sobrecargando operadores
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
    sub infix:<±>($numero, $error) {    # definimos un operador infijo
        $numero - $error + rand * 2 * $error;
    }
    say 15 ± 5;                          # algo entre 10 y 20

    sub postfix:<!>($n) { [*] 1..$n }    # definimos un operador postfijo
    say 5!;                              # que calcula el factorial del número 5: 120

    class Physical::Unit {               # Definimos una clase, de unidades de física
        has Int $.kg = 0;                # estos atributos denotan la potencia de las unidades
        has Int $.m  = 0;                # por ej., $.kg == 2 significa que este objeto
        has Int $.s  = 0;                # tiene de unidades kg**2

        has Numeric $.carga;

                                         # Definimos la multiplicación con otra unidad física
        method multiplicar(Physical::Unit $otro) {
            Physical::Unit.new(
                :kg( $.kg + $otro.kg ),
                :m(  $.m + $otro.m   ),
                :s(  $.s + $otro.s   ),
                :carga( $.carga * $otro.carga )
            )
        }

                                         # Definimos la inversión
        method invertir() {
            Physical::Unit.new(
                :kg( -$.kg ), :m( -$.m ), :s( -$.s ),
                :carga( 1 / $.carga )
            )
        }

                                         # Definimos la conversión a cadena de caracteres
        method Str {
            $.carga
            ~ ($.kg ?? ($.kg == 1 ?? " kg" !! "kg**$.kg") !! "")
            ~ ($.m  ?? ($.m  == 1 ?? " m"  !! "m**$.m")   !! "")
            ~ ($.s  ?? ($.s  == 1 ?? " s"  !! "s**$.s")   !! "")
        }
    }

                                         # Definimos operadores postfijos
    sub postfix:<kg>(Numeric $carga) { Physical::Unit.new( :kg(1), :$carga ) }
    sub postfix:<m>(Numeric $carga)  { Physical::Unit.new( :m(1), :$carga  ) }
    sub postfix:<s>(Numeric $carga)  { Physical::Unit.new( :s(1), :$carga  ) }

    # Definimos varias combinaciones de multiplicación de unidades físicas
    # Notar cómo usamos ahora 'multi sub', para no ensombrecer el original infix:<*>
    multi sub infix:<*>(Physical::Unit $a, $b) {
        $a.clone( :carga($a.carga * $b) );
    }

    multi sub infix:<*>($a, Physical::Unit $b) {
        $b.clone( :carga($a * $b.carga) );
    }

    multi sub infix:<*>(Physical::Unit $a, Physical::Unit $b) {
        $a.multiplicar($b);
    }

    # y otras para la división
    multi sub infix:</>(Physical::Unit $a, $b) {
        $a.clone( :carga($a.carga / $b) );
    }

    multi sub infix:</>($a, Physical::Unit $b) {
        $b.invertir.clone( :carga($a / $b.carga) );
    }

    multi sub infix:</>(Physical::Unit $a, Physical::Unit $b) {
        $a.multiplicar($b.invertir);
    }

    # Ejemplos de uso
    say 5m / 2s;                         # 2.5 m s**-1
    say 100kg * 2m / 5s;                 # 40 kg m s**-1
 
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


infix:<Z>
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
    # Z (el operador 'zip') significa "mezcla estas listas juntas"
    my @gustos = <picante dulce suave>;
    my @alimentos = <sopa patatas tofu>;
    @gustos Z @alimentos; # <picante sopa dulce patatas suave tofu>

    # » significa "llama al método por cada elemento"
    .say for @estudiantes».grado;                 # todos los grados

    for @estudiantes».nombre Z @estudiantes».grado -> $nombre, $grado {
        say "$nombre obtuvo este año un grado de $grado";
    }

    # Notar que la siguiente lista es infinita - funciona igualmente
    for @estudiantes».nombre Z (1..6).pick(*, :replace) -> $nombre, $dado {
        say "$nombre juego un $dado";
    }

    # puede también usar Z junto con dos listas con un operador infijo
    my @total-puntuaciones = @primera-puntuacion Z+ @segunda-puntuacion;

    # cadenas como claves; un número incremental de unos, como valores
    my %hash = @nombres Z=> 1 xx *;              # xx es el operador de repetición

    # numerar personas con números crecientes
    my %gente2numeros = @gente Z=> 1..*;

    # ¿no tienes un buen operador? ¡créate el tuyo propio!
    sub infix:<gusta>($amante, $amado) { "$amante está encariñado con $amado" }

    # notar como el operador infijo infix:<Zgusta> está disponible automáticamente
    my @relaciones = @amantes Zgusta @amados;
 
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


infix:<...>
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
    1 ... $n                                    # enteros de 1 a $n
    $n ... 1                                    # y al revés

    1, 3 ... $n                                 # números impares hasta $n
    1, 3, ... *                                 # números impares
    1, 2, 4 ... *                               # potencias de dos
    map { $_ * $_ }, (1 ... *)                  # cuadrados

    1, 1, -> $a, $b { $a + $b } ... *           # fibonacci
    1, 1, { $^a + $^b } ... *                   # ídem
    1, 1, *+* ... *                             # ídem

    'Camelia', *.chop ... '';                   # todos los prefijos posibles de 'Camelia'

    # Ver http://blog.plover.com/CS/parentheses.html
    # para ver los principios que hay detrás de esto
    sub siguiente-parentesis-balanceado($s) {
        $s ~~ /^ ( '('+ ) ( ')'+ ) '(' /;
        [~] $s.substr(0, $/.from),
            "()" x ($1.chars - 1),
            "(" x ($0.chars - $1.chars + 2),
            ")",
            $s.substr($/.to);
    }

    my $N = 3;

    my $inicio = "()" x $N;
    my &paso = &siguiente-parentesis-balanceado;
    my $fin = "(" x $N ~ ")" x $N;

    for $inicio, &paso ... $fin -> $cadena {
        say $cadena;
    }

    # Salida:
    # ()()()
    # (())()
    # ()(())
    # (()())
    # ((()))
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


(Traducción del artículo de masak, del día 23 de julio en use.perl.org)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Publicidad

Volver a Pasando el rato

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 10 invitados