p6s*_*eve 8 units-of-measurement mixins raku
这个新问题是我之前提出的问题的后续问题,是在我充实内容时出现的。请注意,我也做了一些研究,并且有意识地避开了这里提到的 Scalar Mixins bug 。因此,我将角色混合到对象中,而不是标量容器中。
大局是进行数学运算,同时也执行简单的误差计算。
这是我的失败代码的简洁版本:
1 role Error {
2 has $.abs-error
3 }
4
5 multi prefix:<-> ( Error:D $x ) is default {
6 # - $x; # fails - enters an infinite loop
7 # - $x.Real; # fails - does not drop the Error mixin
8 ( 0 - $x ) does Error($x.abs-error) # works - but relies on the infix:<-> form
9 }
10
11 my $dog = 12.5 does Error(0.5);
12
13 #what i have...
14 say $dog; #12.5
15 say $dog.WHAT; #(Rat+{Error})
16 say $dog.abs-error; #0.5
17
18 #what i want...
19 say (-$dog); #-12.5
20 say (-$dog).WHAT; #(Rat+{Error})
21 say (-$dog).abs-error; #0.5
Run Code Online (Sandbox Code Playgroud)
我的问题的核心是:
我尝试了(拼命?)一些事情:
谢谢大家的建议!!
对这个问题的直接回答是:不,没有任何操作可以撤销 mixin。但是,您可以采取一些技巧来实现原始类型的功能:
\n$obj-with-mixin.OriginalType::method-name()表单调用已被重写的方法。multi(例如运算符),您可以&prefix:<->.cando(\\(1.5)).head解析但不调用-on的实现Rat,然后直接调用它。然而,看看这个问题和你之前的问题,你似乎每一步都在与语言作斗争;is default这确实是最后的手段,即使你可以使用 mixin 方法让它工作,你也会发现结果非常慢,很大程度上是因为 mixin 触发了去优化(脱离了专门的和 JIT 编译的代码)给口译员)。
也许可以探索使用组合的设计:
\n# An object holding the value and the error.\nclass Error does Real {\n has Real $.value;\n has Real $.abs-error;\n multi method Real(Error:D:) { $!value }\n multi method gist(Error:D:) { "$!value\xc2\xb1$!abs-error" }\n}\n\n# A cute constructor of this type, just for fun.\nmulti infix:<\xc2\xb1>(Real $value, Real $abs-error) {\n Error.new(:$value, :$abs-error)\n}\n\n# Negation; no `is default` or other tricks required!\nmulti prefix:<->(Error $e --> Error) {\n Error.new(value => -$e.value, abs-error => $e.abs-error)\n}\n\n# It works!\nmy $x = 4.5 \xc2\xb1 0.1;\nsay $x;\nsay -$x;\nRun Code Online (Sandbox Code Playgroud)\n