rakuのモジュールでPreludeモジュールのようにHaskellを使用する


11

私はいくつかのパーツを含む描画パッケージを書いており、演算子とデータ型が散在しています。ただし、ユーザーに毎回対応するモジュールを追加してほしくありません。これは非常に煩雑になるためです。たとえばPoint、次のような異なるパスにクラス、Monoidロール、Styleクラスがあるとします。

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 {...}

私はそのよう なスクリプトを書くことができるという効果でhaskell同様のプレリュードを持ちたいですlib/Package/Prelude.pm6

use Package::Prelude;

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

する代わりに

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

私は多くのことを試しました:

  • このバージョンは私に正しい効果を与えません、私はポイントするためにパス全体をタイプしなければなりません、すなわちPackage::Data::Point...
unit module Package::Prelude;
# $?FILE = lib/Package/Prelude.pm6
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
  • このバージョンはPointすぐに使用できますが、演算子などに問題が発生します。また、上記のサンプルパッケージのエクスポートされたルーチンからすべてを自動的に追加したいだけです。
# $?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
     ...
}

あなたはそのようなプレリュードのようなファイルを取得するより良い迅速な方法を知っていますか?


使用できますunit class Package::Data::Point。を使用する必要はありませんmodule
Brad Gilbert

回答:


12

使用EXPORTは正しい方向です。知っておくべき重要な点は次のとおりです。

  • インポートは語彙的です
  • イントロスペクションを使用して、現在の字句スコープ内のシンボルを取得してアクセスできます

だからレシピは:

  • use 内部のすべてのモジュール EXPORT
  • 次に、インポートされたすべてのシンボルを抽出し、結果としてそれらを返します EXPORT

例として、Foo::Point演算子とクラスを含むモジュールを作成します。

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)
}

そして、それが複数のモジュールで動作することを実証するために、またFoo::Monad

unit module Foo::Monad;

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

目標は、この作業を行うことです。

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

これは、以下Foo::Preludeを含むを書くことで達成できます。

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

ここで説明する奇妙な点がいくつかあります。

  1. Aは、sub暗黙の宣言を持っている$_$/$!。これらをエクスポートすると、モジュールがuse'd'のときにコンパイル時のシンボルクラッシュエラーが発生します。ブロックには暗黙的なのみがあり$_ます。したがって、ネストされたベアブロックを使用すると、作業が簡単になります。
  2. これgrepは、暗黙的に宣言された$_シンボルをエクスポートしないようにするためです(ネストされたブロックのおかげで、注意が必要なのはそれだけです)。
  3. ::現在のスコープを参照する方法です(語源:::はパッケージ区切り文字です)。::.pairsしたがってPair、現在のスコープ内の各シンボルのオブジェクトを取得します。

将来のRaku言語のリリースでは、この定型文の必要性を排除する可能性があると推測される再エクスポートメカニズムがあります。


最後に、これはまさに私が探していた振る舞いです、本当にありがとう!
margolari
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.