是否有一种方法(隐式)删除Raku角色混合?



这个新问题是我在充实内容时出现的前一个问题的后续问题。请注意,我也做了一些研究,我有意识地避开了这里提到的标量混合错误。因此,我将角色混合到对象中,而不是标量容器中。

大图是做数学运算的同时也执行简单的误差计算。

下面是我失败代码的简洁版本:

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

我的问题的核心是:

  • 作为$dog I的用户可以获取第14行
  • 中变量(12.5)的值
  • 那么我怎么能得到未修饰的值在第7行左右?

我已经尝试了(拼命?)几件事:

  • 强制转换为Real(仍然得到混合对象)
  • 给真实容器赋值(允许Rat+{Error} ~~ Real)
  • $ dog.default =比;对于类型"Rat+{Error}"的调用,没有这样的"default"方法

谢谢你的建议!

对这个问题的直接回答是:不,没有撤销mixin的操作。但是,您可以使用一些技巧来达到原始类型的功能:

  • 在方法重写的情况下,使用$obj-with-mixin.OriginalType::method-name()表单调用已经被重写的方法。
  • multi子(如操作符)的情况下,可以通过&prefix:<->.cando((1.5)).head来解析-Rat上的实现,但不能调用,然后直接调用。

看看这个问题和你之前的问题,然而,似乎你每一步都在与语言作斗争;is default确实是最后的手段,即使你可以使用mixin方法让它工作,你会发现结果非常慢,在很大程度上是因为mixins触发反优化(从专门的和jit编译的代码中掉回解释器)。

或许可以用构图来探索设计:

# An object holding the value and the error.
class Error does Real {
has Real $.value;
has Real $.abs-error;
multi method Real(Error:D:) { $!value }
multi method gist(Error:D:) { "$!value±$!abs-error" }
}
# A cute constructor of this type, just for fun.
multi infix:<±>(Real $value, Real $abs-error) {
Error.new(:$value, :$abs-error)
}
# Negation; no `is default` or other tricks required!
multi prefix:<->(Error $e --> Error) {
Error.new(value => -$e.value, abs-error => $e.abs-error)
}
# It works!
my $x = 4.5 ± 0.1;
say $x;
say -$x;

离开@raiphs注释,我找到了一个快速而肮脏的修复方法,使用我知道的事实。say方法可以产生Object的未修饰值…

…面向对象编程的纯粹主义者,现在请把目光移开。

1 role Error {       
2     has $.abs-error;
3     
4     method negate {
5         my $val = +"{self}";     #extract unadorned value of $x
6         (- $val) does Error( $!abs-error );
7     }   
8 }   
9 
10 multi prefix:<-> ( Error:D $x ) is default { $x.negate }
11 
12 my $dog = 12.5 does Error(0.5);
13 
14 #what i get...
15 say (-$dog);            #-12.5
16 say (-$dog).WHAT;       #(Rat+{Error})
17 say (-$dog).abs-error;  #0.5

最新更新