【发布时间】:2019-05-06 19:55:57
【问题描述】:
使子程序/过程可供重用是模块的核心功能之一,我认为这是一种语言如何可组合并因此在程序员时间上高效的基本方式:
如果你在你的模块中创建一个类型,我可以创建我自己的模块来添加一个对你的类型进行操作的子。我不必扩展你的模块来做到这一点。
# your module
class Foo {
has $.id;
has $.name;
}
# my module
sub foo-str(Foo:D $f) is export {
return "[{$f.id}-{$f.name}]"
}
# someone else using yours and mine together for profit
my $f = Foo.new(:id(1234), :name("brclge"));
say foo-str($f);
正如Overloading operators for a class 中所见,这种模块的可组合性同样适用于运算符,这对我来说是有道理的,因为无论如何运算符只是 subs 的某种语法糖(至少在我的脑海中)。请注意,此类运算符的定义不会导致现有代码的行为发生任何令人惊讶的变化,您需要将其显式导入代码中才能访问它,就像上面的子代码一样。
鉴于此,我觉得很奇怪我们没有类似的方法机制,例如How do you add a method to an existing class in Perl 6? 的讨论,特别是因为 perl6 是一种方法快乐的语言。如果我想扩展现有类型的使用,我想以与编写原始模块相同的样式来执行此操作。如果 Int 上有一个 .is-prime,我必须可以添加一个.is-semi-prime 也是,对吧?
我阅读了上面链接中的讨论,但不太相信“远距离行动”的论点:这与我从模块中导出另一个多子有什么不同?例如,使这成为词法更改(Trait + impl ... for)的 rust 方式对我来说似乎很卫生,并且非常符合上面的 operator 方法。
比技术性更有趣(至少对我而言)是语言设计的问题:为现有名词(类型)提供新动词(subs,operators,methods)的能力不是语言的核心设计目标吗?像perl6?如果是,为什么它会以不同的方式对待方法?如果它确实出于充分的理由对它们进行了不同的处理,这是否意味着我们将许多不可组合的方法用作名词,而我们应该使用 subs 来代替?
【问题讨论】:
-
也许会进一步混淆:方法与后缀运算符有何不同或为什么不同?
-
我不完全确定我理解这个问题。如果要添加 .is-semi-prime,可以:
augment class Int { method is-semi-prime {…}}。对于与后缀的直接并行,您只需添加一个 multi 方法。 -
@guifa:当然你可以做扩充,但它不是你可以导入并因此组成的东西,它是卫生的或词法范围的,因此可以推断出它的作用范围。我想这就是它需要 MONKEY-TYPING 的部分原因。这一切都很好,但我发现它与潜艇和操作员的工作方式非常不一致......
标签: raku