微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

递归函数和类中的 Raku 类型约束

如何解决递归函数和类中的 Raku 类型约束

我尝试在 raku OOP 中编写 yangyanzhan's solution of the raku-riddle-contest。 Raku 类系统非常直观,everything work as a charm 直到我遇到了一个递归函数。这是类和函数代码版本:

class Encounters {
  has $.tigers;
  has @!encounters;

  method encounters {
    if @!encounters.elems eq $.tigers {
      return [@!encounters,];  
    }                          
    my @total_encounters = []  ;
    for 1..$.tigers -> $tiger   {
      if ($tiger / 2) eq ($tiger / 2).round {
        @!encounters = ( @!encounters,[$tiger]).flat ;
        my @encounter_events = Encounters.new( tigers => $.tigers,encounters => @!encounters ).encounters;
        @total_encounters.append: @encounter_events;
      }
    }
    return @total_encounters;
  }
}

sub encounters($tigers,@encounters) {
  if @encounters.elems eq $tigers {
    return [@encounters,];  
  }                          
  my @total_encounters = []  ;
  for 1..$tigers -> $tiger   {
    if ($tiger / 2) eq ($tiger / 2).round {
      my $sig = ( @encounters,[$tiger] ).flat;
      my @encounter_events = encounters( $tigers,$sig );
      @total_encounters.append: @encounter_events;
    }
  }
  return @total_encounters;
}

sub MAIN( $tigers ) {
  (encounters $tigers,[] ).say;
  Encounters.new( tigers => $tigers ).encounters.say;
}

对于 $tigers = 4,函数给出:

[(2 2 2 2) (2 2 2 4) (2 2 4 2) (2 2 4 4) (2 4 2 2) (2 4 2 4) (2 4 4 2) (2 4 4 4) (4 2 2 2) (4 2 2 4) (4 2 4 2) (4 2 4 4) (4 4 2 2) (4 4 2 4) (4 4 4 2) (4 4 4 4)]

另一方面,班级总是陷入无限循环。我相信函数和类的区别就在于这行代码

 @!encounters = ( @!encounters,[$tiger]).flat;
 my $sig = ( @encounters,[$tiger] ).flat;

我不清楚这是因为递归语法格式错误还是函数和类之间的类型约束不同。

解决方法

好吧,它们不是相同的算法也无济于事。
它们很接近,但又不一样。

在子程序之一中:

my $sig = ( @encounters,[$tiger] ).flat;

但该方法改为修改属性:

@!encounters = ( @!encounters,[$tiger]).flat;

我真的不知道当一个不修改其参数但另一个修改它时,您如何期望它以相同的方式运行。


更重要的是,子程序使用 Seq 值。

my $sig = ( @encounters,[$tiger] ).flat;
note $sig.raku;
# $((2,4,2,2).Seq)

虽然方法一使用数组。


我不认为您对课堂有任何好处。

使用方法调用来修改类的结构并不是一个好主意。
我会在对象构建时进行更多的处理。


我不会尝试修复或重写它,因为有一些简单的决定让我怀疑解开设计需要多长时间。

从使用字符串比较 eq 来比较数字。
当它可能只是 $tigers %% 2

时计算两次除以 2

当有人做这样的事情时,真的让人怀疑是否有更大的结构性问题恰好解决了。

@!encounters 处于不一致状态这一事实于事无补。

我确实理解有人可能会以这种方式编码。事实上,我确信我早年也有同样糟糕的代码。


如果我要尝试,我会删除基于对象的对象,然后首先开始清理子例程。 我的想法是,通过努力,我会更好地了解问题空间。

我还必须编写大量测试用例以确保它适用于 4 以外的数字。
现在,这是我知道它适用的唯一输入。
实现中没有任何东西会尖叫:“这显然是正确的”。
(就像我之前所说的,有些事情暗示它可能不正确。)

然后我可以利用这些知识尝试将其重构为可以更轻松地转移到基于对象的设计中的内容。

或者我可以让子程序的内部值基于对象,从而慢慢地将其转移到基于对象的设计中。


假设这只是尝试以另一种方式编写它的练习,我建议在尝试将其对象化之前,多弄乱一个子程序。 例如,您可以尝试使其不使用 .flat

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。