当前位置: 首页 > 知识库问答 >
问题:

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

万承志
2023-03-14

我试着用拉库OOP写杨彦湛的拉库谜语比赛答案。Raku类系统非常直观,在我遇到递归函数之前,一切都很有魅力。这是类和函数的代码版本:

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;

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

共有1个答案

卫嘉佑
2023-03-14

它们不是相同的算法也没用。
它们很接近,但不相同。

在子例程中,您有:

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

但该方法改为使用以下内容修改属性:

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

我真的不知道你如何期望它在一个不修改参数但另一个修改参数时表现相同。

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

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

而方法一使用数组。

我看不出你对这个班有什么好处。

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

我不会试图修复它,也不会重写它,因为有一些简单的决定让我怀疑要花多长时间才能解开这个设计。

从使用字符串比较eq来比较数字。
到计算除以2两次,而它可能只是$tigers

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

事实是,<代码>@!遭遇战处于不一致的状态并没有帮助。

我确实理解某人是如何以这种方式编码的。事实上,我确信我在早期也有同样糟糕的代码。

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

我还必须编写大量测试用例,以确保它适用于除4以外的数字<目前,这是我知道它适用的唯一输入
实现中没有任何内容会高呼:“这显然是正确的”
(正如我之前基本上说过的,有些事情暗示它可能不正确。)

然后我可以利用这些知识尝试将其重组为更容易转移到基于对象的设计中的东西。

或者我可以使子例程的内部值基于对象,从而将其缓慢地转换为基于对象的设计。

假设这只是一个尝试以另一种方式编写它的练习,我建议在尝试将其对象化之前,多处理一个子例程。例如,您可以尝试使其不使用<代码>。平坦

 类似资料:
  • 我正在制作一种强类型的玩具函数式编程语言。它使用Hindley Milner算法作为类型推断算法。 在实现该算法时,我有一个问题,即如何推断相互递归函数的类型。 和是相互递归的函数。现在,当类型检查器推断函数的类型时,它也应该能够推断函数的类型,因为它是一个子表达式。 但是,在那一刻,函数还没有定义。因此,显然,类型检查器甚至不知道函数的存在,以及函数的类型。 真实世界的编译器/Inteprete

  • 我想写一个函数返回一个数组,其所有子数组的长度必须为2。例如,返回将是。 我定义: (1); 和 我觉得(1)太复杂了。有更简单的吗?

  • 在F#中,我试图编写一个函数,给定两个字符串,它将返回第一个字符串中第二个字符串开头的所有索引。我的函数看起来像这样: 问题是在线

  • 无法理解如何使用int类型的递归函数查找二叉查找树的高度的解释。 对于任何二元搜索树,给定一个指向树的根节点的指针,其中节点按常规定义如下。。。 我们可以使用以下int类型的递归函数来给出二元搜索树的高度。。。(函数“max”只取两个整数,并返回其中较大的一个) 我的理解是findHeight(根- 我对递归非常陌生,所以我决定只解压缩其中一个递归函数调用,并尝试理解它。我写了findHeight

  • 8. 函数类型和函数指针类型 在C语言中,函数也是一种类型,可以定义指向函数的指针。我们知道,指针变量的内存单元存放一个地址值,而函数指针存放的就是函数的入口地址(位于.text段)。下面看一个简单的例子: 例 23.3. 函数指针 #include <stdio.h> void say_hello(const char *str) { printf("Hello %s\n", str); }

  • 这是为了学校的工作。我们必须写一个十进制到八进制转换的程序。八进制转换的递归函数被给出为空deci_oct(int x)。当我试图调用它里面的函数并发送值n/8时,错误“此处不允许使用空类型”出现。问题要求递归函数的返回类型应该是空的。任何帮助都是非常感激的。