Gunakan Haskell seperti modul Prelude dalam modul di raku

11

Saya menulis paket gambar dengan beberapa bagian, dan saya memiliki operator dan tipe data yang tersebar di seluruh penjuru. Namun saya tidak ingin para pengguna menambahkan modul yang sesuai setiap waktu, karena akan sangat berantakan, misalnya saya memiliki Pointkelas, Monoidperan dan Stylekelas di jalur yang berbeda seperti ini

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

Saya ingin memiliki haskellpembuka seperti lib/Package/Prelude.pm6 dengan efek bahwa saya dapat menulis skrip seperti itu

use Package::Prelude;

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

bukannya melakukan

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

Saya sudah mencoba banyak hal:

  • Versi ini tidak memberi saya efek yang tepat, saya harus mengetikkan seluruh jalur ke titik, yaitu, Package::Data::Point...
unit module Package::Prelude;
# $?FILE = lib/Package/Prelude.pm6
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
  • Versi ini memberi saya Pointsegera, tetapi saya mendapatkan masalah dengan operator dan sebagainya, juga saya hanya ingin menambahkan semuanya secara otomatis dari rutinitas yang diekspor dalam paket contoh yang disebutkan.
# $?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
     ...
}

Apakah Anda tahu cara yang lebih baik dan cepat untuk mendapatkan file seperti pembuka?

margolari
sumber
Anda bisa menggunakannya unit class Package::Data::Point. Anda tidak harus menggunakan module.
Brad Gilbert

Jawaban:

12

Menggunakan EXPORTberada di arah yang benar. Hal-hal penting yang perlu diketahui adalah:

  • Impor leksikal
  • Kita dapat menggunakan introspeksi untuk mendapatkan dan mengakses simbol dalam lingkup leksikal saat ini

Jadi resepnya adalah:

  • use semua modul di dalamnya EXPORT
  • Kemudian ekstrak semua simbol yang diimpor dan kembalikan sebagai hasil dari EXPORT

Sebagai contoh, saya membuat modul Foo::Point, termasuk operator dan kelas:

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

Dan, hanya untuk menunjukkannya dapat bekerja dengan banyak modul, juga Foo::Monad:

unit module Foo::Monad;

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

Tujuannya adalah membuat ini bekerja:

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

Yang bisa dicapai dengan menulis a Foo::Preludeyang berisi:

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

Ada beberapa keanehan di sini untuk dijelaskan:

  1. Sebuah submemiliki deklarasi implisit $_, $/dan $!. Mengekspor ini akan menghasilkan kesalahan bentrokan simbol waktu kompilasi ketika modul use'd. Blok A hanya memiliki implisit$_ . Dengan demikian kita membuat hidup kita lebih mudah dengan blok kosong bersarang.
  2. Ini grepuntuk memastikan kita tidak mengekspor $_simbol yang dinyatakan secara implisit (berkat blok bersarang, itu satu-satunya yang harus kita perhatikan).
  3. ::adalah cara untuk merujuk ruang lingkup saat ini (etimologi: ::adalah pemisah paket). ::.pairsdengan demikian memperoleh Pairobjek untuk setiap simbol dalam lingkup saat ini.

Ada mekanisme re-ekspor berspekulasi yang mungkin muncul dalam rilis bahasa Raku di masa depan yang akan menghilangkan kebutuhan untuk sedikit boilerplate ini.

Jonathan Worthington
sumber
Akhirnya, inilah perilaku yang saya cari, terima kasih banyak!
margolari