Estoy creando un módulo que tiene un archivo de múltiples módulos, y enfrenté este problema al usar el rol en un módulo diferente.

Por ejemplo, tenemos dos módulos Foo y Bar, y hay un rol en cada módulo.

module Foo { 
    role foo is export {

    }  
}

module Bar { 
    import Foo; 

    role bar is export does foo {

    }
} 

import Foo;
import Bar;

sub f(foo \k) { }

f(bar.new);

Pensé que el código está bien, pero rakudo dijo que piensa que bar no es un tonto y rechazó compilar.

¿Qué pasa aquí?

5
araraloren 9 sep. 2018 a las 18:16

3 respuestas

La mejor respuesta

Esto me parece un error. Alguna investigación adicional:

module Foo {
    role Bar is export {}
}

module Quux {
    import Foo;
    constant Barr = Bar;
    role Baz does Bar is export {}
    role Bazz does Foo::Bar is export {}
}

import Foo;
import Quux;

# these are all the same: 
say Foo::EXPORT::ALL::Bar.WHICH;
say Quux::Barr.WHICH;
say Bar.WHICH;

# but different from our original type object!?!
say Foo::Bar.WHICH;

# now it gets weird:
say Baz ~~ Bar;           # True
say Baz.new ~~ Bar;       # False
say Baz ~~ Foo::Bar;      # False
say Baz.new ~~ Foo::Bar;  # True

# however, these all 'work':
say Bazz ~~ Bar;          # True
say Bazz.new ~~ Bar;      # True
say Bazz ~~ Foo::Bar;     # True
say Bazz.new ~~ Foo::Bar; # True

Por ahora, parece mejor derivar nuevos roles de la versión pública totalmente calificada del rol de otro módulo en lugar de uno exportado: la exportación parece crear un nuevo objeto de tipo que interactúa de manera extraña con la coincidencia inteligente / verificación de tipo ...

4
Christoph 10 sep. 2018 a las 13:50

Déjame ver si puedo canalizar a @raiph y responder esta pregunta de la mejor manera posible. Hay varios errores aquí.

Uso de import

El caso de uso principal para import es exactamente el que haces aquí; es descrito en la documentación. Sin embargo, es una mejor práctica colocar módulos en diferentes archivos (con el mismo nombre que el módulo) y elegir use en su lugar. use que importa e incluye todo en el espacio de nombres. use cargas (a través de need) y luego importa las módulo exactamente una vez.

Guardar llaves con la unidad

unit es básicamente azúcar sintáctico para ahorrar llaves. Entonces los dos primeros archivos se convertirán en:

Foo.pm6

unit module Foo;

  role foo is export {
} 

Bar.pm6

unit module Bar;

use Foo; 

role bar is export does foo {}

El use de Foo importa el símbolo foo directamente, y puede usarse como un rol.

¿Qué es un rol?

Por último, pero no menos importante, un papel mezclado en does es literalmente una declaración de "does". No es una declaración "es-a". Entonces bar puede do foo, pero no es foo. Lo que hace que el último archivo sea algo como esto:

use-foo-bar.p6:

use Foo;
use Bar;
sub f(bar \k) { }
f(bar.new);

Tenga en cuenta que he usado bar \k en lugar de foo \k. Si no lo hiciera, el error sería: Type check failed in binding to parameter 'k'; expected Foo::foo but got Bar::bar (Bar::bar.new)

Volver a la publicación original

Lo que estaba mal era simplemente la subdeclaración, que debería haber sido:

sub f(bar \k) { }

Debido a lo que se explica en la última sección anterior. Sin embargo, necesitaba examinar un poco el resto del programa para descubrir esto.

2
jjmerelo 10 sep. 2018 a las 14:03

El símbolo foo después de import no es =:= a Foo::foo y no acepta este último en una coincidencia inteligente. Eso me parece un error y presumiblemente está relacionado con lo que está sucediendo:

module Foo {
  role foo is export { }
  .say for foo.^name, Foo::foo.^name,
           Foo.WHICH, foo.WHICH, Foo::foo.WHICH,
           foo.isa(Foo::foo),
           Foo::foo.isa(foo),
           foo.does(Foo::foo),
           Foo::foo.does(foo),
           foo ~~ Foo::foo,
           Foo::foo ~~ foo,
}
import Foo;
.say for foo.^name, Foo::foo.^name,
         Foo.WHICH, foo.WHICH, Foo::foo.WHICH,
         foo.isa(Foo::foo),
         Foo::foo.isa(foo),
         foo.does(Foo::foo),
         Foo::foo.does(foo),
         foo ~~ Foo::foo,
         Foo::foo ~~ foo,

Foo::foo
Foo::foo
Foo|U64545472
Foo::foo|U64545856
Foo::foo|U64545856
False
False
True
True
True
True
Foo::foo
Foo::foo
Foo|U64545472         <^-- all good so far
Foo::foo|U64545616    <--- uhoh
Foo::foo|U64545856
False
False
True
True
True
False                 <-- presumably a consequence of uhoh

Presentaré un error en los próximos días si nadie me supera y nadie muestra por qué no es un error.

4
raiph 10 sep. 2018 a las 13:47