Everyone Loves Porgs

人见人爱普落格

这个想法有一阵子了。我在完成的各个阶段都有几个发文的想法,有时候很难优先考虑这个问题。所以我想我要开始发布我一直在玩的更短的想法和事情,以免这个博客变成那些永不更新的博客之一。所以,我们开始吧。

类在 Raku 中很容易定义。它们非常容易,我发现自己使用它们来封装小型的 Hash-like 那样的东西,其中我也可能会使用一两种方法。

class Contact {
    has $.name;
    has $.phone;
    has $.bday;
    method age {
        (Date.new($.bday), *.later(:1year) ...^ * > Date.today).end
    }
}

是的,这是一种低效率的计算年龄的方法……就像生活中的很多事情一样,你越老,这种方法变得越慢。

无论如何,现在我已经定义了一个简单的小类来保存一些数据,但要实际实例化一个我不得不 bust out 一些命名参数。

my @contacts;
@contacts.push: Contact.new(:name<John>, :phone<555-1111>, :bday<1940-10-09>);

谁有时间为所有这些角色?有时候我只是想用位置参数来构建它们,但这意味着要编写一个新的自定义 multi method new 来处理这些情况……但我只是将一个快速肮脏的类放在一起,真的值得我花时间来构建自定义构造函数吗?

于是我开始四处游玩,并创建了一个让我用 Positional 参数的角色……或一个 Array ..或 List …构建我的类,嘿,I threw in a Hash for free!!

@contacts.push: Contact.new('James', '555-1112', '1942-06-18');

@contacts.push: Contact.new(< George 555-1113 1943-02-25 >)

my %hash = name => 'Richard', phone => '555-1114', bday => '1940-07-07';
@contacts.push: Contact.new(%hash);

我使用了自省方法 .^attributes 来获取属性列表。我只对本地属性感兴趣(不是继承的属性),尽管你肯定可以改变它,甚至通过参数化角色来控制它。我也只对拥有存取器的属性感兴趣(例如公共属性)。

role Porgs {
    multi method new(*@args where *.elems) {
        self.bless: |%(
            self.^attributes(:local)
                .grep(*.has_accessor)
                .map(*.name.substr: 2)
            Z=> @args)
    }
    multi method new(List $args) {
        self.new: |$args
    }
    multi method new(%args) {
        self.bless: |%args
    }
}

class Contact does Porgs { ... }

我称 Porgs 为 “Positional Args” 的缩写,但也和来自 Star Wars(星球大战) 中的生物共享一个名字。 Porgs 角色允许你编写小而可爱的类,就像生物一样。此外,每个人都喜欢 Porgs。

img

这就是今天的全部。我不打算将此发布到生态系统或任何其他计划中,因此,如果您愿意,请随时加以改进,重新命名并将其发布到生态系统中。另外,我不确定 self.^attributes 是否按照您声明的顺序返回属性是一个实现细节……所以也许这可能会变化?

Raku 

comments powered by Disqus