Utilisez Haskell comme des modules Prelude dans un module de raku

11

J'écris un package de dessin avec certaines parties et j'ai des opérateurs et des types de données dispersés. Cependant, je ne veux pas que les utilisateurs ajoutent les modules correspondants à chaque fois, car ce serait assez compliqué, par exemple, j'aurais une Pointclasse, un Monoidrôle et une Styleclasse dans des chemins différents comme celui-ci

unit module Package::Data::Monoid;
# $?FILE = lib/Package/Data/Monoid.pm6

role Monoid {...}
unit module Package::Data::Point;
# $?FILE = lib/Package/Data/Point.pm6

class Point {...}
unit module Package::Data::Style;
# $?FILE = lib/Package/Data/Style.pm6

class Style {...}

Je voudrais avoir un haskellprélude similaire lib/Package/Prelude.pm6 avec l'effet que je peux écrire de tels scripts

use Package::Prelude;

# I can use Point right away, Style etc...

au lieu de faire

use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;

# I can too use point right away, but for users not knowing the
# inner workings it's too overwhelming

J'ai essayé beaucoup de choses:

  • Cette version ne me donne pas le bon effet, je dois taper tout le chemin à pointer, c'est à dire Package::Data::Point...
unit module Package::Prelude;
# $?FILE = lib/Package/Prelude.pm6
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
  • Cette version me donne Pointtout de suite, mais j'ai des problèmes avec les opérateurs et ainsi de suite, je voudrais également ajouter automatiquement tout ce qui provient des routines exportées dans les exemples de packages mentionnés.
# $?FILE = lib/Package/Prelude.pm6
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;

sub EXPORT {
  hash <Point> => Point
     , <Style> => Style
     , <mappend> => &mappend
     ...
}

Connaissez-vous un moyen meilleur et plus rapide d'obtenir un tel fichier prélude?

margolari
la source
Vous pouvez utiliser unit class Package::Data::Point. Vous n'avez pas à utiliser module.
Brad Gilbert

Réponses:

12

L'utilisation EXPORTest dans la bonne direction. Les choses clés à savoir sont:

  • Les importations sont lexicales
  • Nous pouvons utiliser l'introspection pour obtenir et accéder aux symboles dans la portée lexicale actuelle

La recette est donc:

  • use tous les modules à l'intérieur de EXPORT
  • Ensuite, extrayez tous les symboles importés et renvoyez-les comme résultat de EXPORT

À titre d'exemple, je crée un module Foo::Point, comprenant un opérateur et une classe:

unit module Foo::Point;

class Point is export {
    has ($.x, $.y);
}

multi infix:<+>(Point $a, Point $b) is export {
    Point.new(x => $a.x + $b.x, y => $a.y + $b.y)
}

Et, juste pour démontrer qu'il peut fonctionner avec plusieurs modules, également Foo::Monad:

unit module Foo::Monad;

class Monad is export {
    method explain() { say "Just think of a burrito..." }
}

Le but est de faire fonctionner cela:

use Foo::Prelude;
say Point.new(x => 2, y => 4) + Point.new(x => 3, y => 5);
Monad.explain;

Ce qui peut être réalisé en écrivant un Foo::Preludequi contient:

sub EXPORT() {
    {
        use Foo::Point;
        use Foo::Monad;
        return ::.pairs.grep(*.key ne '$_').Map;
    }
}

Il y a quelques bizarreries ici pour expliquer:

  1. A suba des déclarations implicites $_, $/et $!. L'exportation de ceux-ci entraînerait une erreur de conflit de symboles au moment de la compilation lorsque le module est use'd. Un bloc n'a qu'un implicite $_. Ainsi, nous facilitons notre vie avec un bloc nu imbriqué.
  2. Il greps'agit de s'assurer que nous n'exportons pas notre $_symbole implicitement déclaré (grâce au bloc imbriqué, c'est le seul dont nous devons nous soucier).
  3. ::est un moyen de référencer la portée actuelle (étymologie: ::est le séparateur de paquet). ::.pairsobtient ainsi des Pairobjets pour chaque symbole dans la portée actuelle.

Il existe un mécanisme de réexportation spéculé qui pourrait apparaître dans une future version en langue Raku qui éliminerait le besoin de ce morceau de passe-partout.

Jonathan Worthington
la source
Enfin, c'est exactement le comportement que je cherchais, merci beaucoup!
margolari