Tipos parametrizados em Raku, como usar valores de tempo de execução como parâmetros

Nov 28 2020

Eu gostaria de criar alguns tipos parametrizados para Raku; basicamente, gostaria de criar algumas classes diferentes cuja principal diferença seria a faixa de valores de um de seus atributos; por exemplo, classes representam tipos de edifícios, gostaria de ter classes diferentes para edifícios com 3 ou qualquer outro número de andares. Portanto, isto é o melhor que pude pensar:

subset Two-Tops of UInt where * <=2;
subset Three-Tops of UInt where * <=3;

role Zipi[ ::Capper ] {
    has Capper $.floor; } class Capped-at-three does Zipi[Three-Tops] {} my $capped = Capped-at-three.new( floor => 2 );
say $capped.raku;

Isso é claramente impraticável, uma vez que você precisa cuidar de muitos números diferentes de andares (não aqui em Granada, onde eles têm no máximo 10, eu acho, mas bem ...). O problema aqui é basicamente que você precisa ter as informações dos subconjuntos em tempo de compilação, então, a menos que você use macros (ainda experimental), não há como usar qualquer tipo de variável. Então, você pode pensar em uma maneira prática de definir esse tipo de papéis curry para qualquer valor do parâmetro?

Respostas

8 user0721090601 Nov 28 2020 at 15:51

Na verdade, ao contrário do que eu disse anteriormente, você pode usar condições em cláusulas where sem problemas, basta colocá-las entre colchetes:

role Zipi[$condition] { has $.floor is rw where {$_ ~~ $condition}
    method foo($x) { $!floor = $x } } class A does Zipi[2 < * < 5] { method bar($x) { $.floor = $x }
}

#my $a = A.new( floor => 10); # error my $a = A.new( floor => 4); # OK

#$a.foo(10); # error $a.foo(3); # OK

#$a.bar(0); # error $a.bar(4); # OK

#$a.floor = 9; # error $a.floor = 3; # OK

Isso deve abranger todos os tipos de atribuição

5 raiph Nov 28 2020 at 04:15

Eu tenho um número muito limitado de recursos MOP e o que segue parece feio, mas funciona e pode ser um passo na direção certa.

O que eu fiz:

  • Construído dinamicamente um array de 10.000 subsets via MOP.

  • O tempo mudou sua construção para compilar o tempo via BEGIN.

  • Usou um elemento apropriado da matriz para parametrizar a função.

my @max-floors-checkers; 
BEGIN {
  @max-floors-checkers = do for ^10_000 -> \floors {
    Metamodel::SubsetHOW.new_type: 
      refinee => UInt,
      refinement => { $^floors <= floors } } } role BuildingCategory[ ::MaxFloorsCheck ] { has MaxFloorsCheck $.floors }
    
class Capped-at-three does BuildingCategory[ @max-floors-checkers[3] ] {}

my $capped3 = Capped-at-three.new( floors => 2 ); say $capped3.raku;                                # Capped-at-three.new(floors => 2

my $capped4 = Capped-at-three.new( floors => 4 ); # Type check failed 
3 user0721090601 Nov 28 2020 at 01:40

Tentei usar wherecláusulas anônimas , mas da mesma forma sem sucesso, mas rastreei o problema: a wherecláusula aparentemente está sendo ignorada pelo BUILDmétodo. Não tenho certeza se é porque ele tem acesso direto (via $!floor) que ignora a wherecláusula, ou se algo estranho está acontecendo (provavelmente o último, em geral entendi Nilse tentei usar o valor paramaterizado em uma wherecláusula).

No entanto, isso deve funcionar bem, incluindo uma mensagem de erro útil:

role Zipi[$condition] {
    has $.floor; submethod BUILD(:$floor, |c) {
        die "Invalid floor number."
            unless $floor ~~ $condition;
        $!floor = $floor;
    }
}

Você pode ver como seria fácil modificar se você pudesse assumir que os pisos são sempre 0 .. x, ou x .. ye poderia fornecer uma mensagem de erro ainda mais útil.

1 raiph Nov 29 2020 at 21:38

Uma resposta negativa cobrindo o caso de um leitor conhecer Java, mas não Raku.

Collection<String> coll = new LinkedList<String>();

tipos parametrizados para Raku

O exemplo de Java vinculado é:

A instanciação de um tipo genérico com argumentos de tipo reais é chamada de tipo parametrizado. Exemplo (de um tipo parametrizado):

Collection<String> coll = new LinkedList<String>();

Um análogo Raku razoável é:

my Positional[Str] \coll = Array[Str].new;

O Positionaltipo é uma função parametrizável . Uma função especifica uma interface e / ou implementação parcial de um tipo. Eu acredito que o de Raku Positionalé suficientemente análogo ao de Java Collectionque serve para os propósitos desta nanswer.

O Arraytipo é uma classe parametrizável . Ele especifica uma estrutura de dados que segue a Positionalfunção. Não é uma lista vinculada, mas será suficiente para os propósitos desta falha.