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

如何使用定义的生成器构建惰性列表,是否有“获取”替代方案?

方兴旺
2023-03-14

我正在阅读懒惰列表上的perl6intro,它让我对某些事情感到困惑。

举个例子:

sub foo($x) {
  $x**2
}

my $alist = (1,2, &foo ... ^ * > 100);

将给我(1 2 4 16 256),它将使相同的数字平方,直到超过100。我想要这个给我(14 9 16 25….),因此不是将同一个数平方,而是将一个数x推进1(或另一个给定的“步长”)、foo x等等。

在这种特殊情况下,有可能实现这一点吗?

关于懒惰列表,我的另一个问题是:在Haskell中,有一个takeWhile函数,Perl6中是否存在类似的东西?


共有3个答案

薛坚
2023-03-14

我要这个给我(1 4 9 16 25 .. )

my @alist = {(++$)²} ... Inf;
say @alist[^10]; # (1 4 9 16 25 36 49 64 81 100)

{...}是任意代码块。当用作...序列运算符的LHS时,它会为序列的每个值调用。

(…)²计算为paren内表达式的平方。(我本可以写下同样的意思。)

$通过将预增量(添加一个)与$变量相结合来返回1, 2, 3, 4, 5, 6...

在Haskell中,有一个获取函数,Perl6中是否存在类似的东西?

将上述序列中的Inf替换为所需的结束条件:

my @alist = {(++$)²} ... * > 70;    # stop at step that goes past 70
say @alist; # [1 4 9 16 25 36 49 64 81]

my @alist = {(++$)²} ...^ * > 70;   # stop at step before step past 70
say @alist; # [1 4 9 16 25 36 49 64]

注意, 和<代码>^ 序列运算符的变体提供了停止条件的两种变体。我注意到,在您最初的问题中,您有<代码>…^*

董昕
2023-03-14
匿名用户

我要这个给我(1 4 9 16 25 .. )

获得该序列的最简单方法是:

my @a = (1..*).map(* ** 2);  # using a Whatever-expression
my @a = (1..*).map(&foo);    # using your `foo` function

...或者如果您更喜欢以类似于Haskell/Python列表理解的方式编写它:

my @a = ($_ ** 2 for 1..*);  # using an in-line expression
my @a = (foo $_ for 1..*);   # using your `foo` function

虽然可以不厌其烦地通过<代码>表达这个序列 运算符(正如Brad Gilbert的答案和raiph的答案所证明的那样),它实际上没有意义,因为该运算符的目的是生成序列,其中每个元素都是使用一致规则从之前的元素派生的。

为每项工作使用最佳工具:

>

如果序列最容易表示为闭合公式(例如,平方序列):
使用映射或表示。

莫宝
2023-03-14

下面是如何编写Perl

sub take-while ( &condition, Iterable \sequence ){
  my \iterator = sequence.iterator;

  my \generator = gather loop {
    my \value = iterator.pull-one;
    last if value =:= IterationEnd or !condition(value);
    take value;
  }

  # should propagate the laziness of the sequence
  sequence.is-lazy
  ?? generator.lazy
  !! generator
}

我可能还应该展示droptime的实现。

sub drop-while ( &condition, Iterable \sequence ){
  my \iterator = sequence.iterator;

  GATHER: my \generator = gather {

    # drop initial values
    loop {
      my \value = iterator.pull-one;

      # if the iterator is out of values, stop everything
      last GATHER if value =:= IterationEnd;

      unless condition(value) {
        # need to take this so it doesn't get lost
        take value;

        # continue onto next loop
        last;
      }
    }

    # take everything else
    loop {
      my \value = iterator.pull-one;
      last if value =:= IterationEnd;
      take value
    }
  }

  sequence.is-lazy
  ?? generator.lazy
  !! generator
}

这些只是简单的实用例子。

可以说,这些值得作为方法添加到列表/可迭代对象中。

您可以(但可能不应该)使用序列生成器语法实现这些。

sub take-while ( &condition, Iterable \sequence ){
  my \iterator = sequence.iterator;
  my \generator = { iterator.pull-one } …^ { !condition $_ }
  sequence.is-lazy ?? generator.lazy !! generator
}
sub drop-while ( &condition, Iterable \sequence ){
  my \end-condition = sequence.is-lazy ?? * !! { False };
  my \iterator = sequence.iterator;

  my $first;
  loop {
    $first := iterator.pull-one;
    last if $first =:= IterationEnd;
    last unless condition($first);
  }

  # I could have shoved the loop above into a do block
  # and placed it where 「$first」 is below

  $first, { iterator.pull-one } … end-condition
}

如果它们被添加到Perl中

直接实现您的要求如下:

do {
  my $x = 0;
  { (++$x)² } …^ * > 100
}

这可以通过状态变量实现:

{ ( ++(state $x = 0) )² } …^ * > 100

并且在声明之外不使用的状态变量不需要名称。
(标量变量以未定义的任何开始,在数字上下文中变为0)

{ (++( $ ))² } …^ * > 100
{ (++$)² } …^ * > 100

如果需要初始化匿名状态变量,可以使用定义的-or运算符//与相等的元运算符=相结合。

{ (++( $ //= 5))² } …^ * > 100

在一些简单的情况下,您不必告诉序列生成器如何计算下一个值<在这种情况下,也可以简化结束条件。

say 1,2,4 ...^ 100
# (1 2 4 8 16 32 64)

唯一可以安全简化结束条件的其他时间是,如果您知道它将在值上停止。

say 1, { $_ * 2 } ... 64;
# (1 2 4 8 16 32 64)

say 1, { $_ * 2 } ... 3;
# (1 2 4 8 16 32 64 128 256 512 ...)
 类似资料:
  • 我定义OpenAPI 3.0文档并使用OpenAPI-generator-cli-3.3.4。jar生成Java代码(DTO)。但我无法解决这个问题:

  • 在一次编程练习中,首先要求对阶乘函数进行编程,然后计算总和:在乘法中(所以我们不能直接使用阶乘)。我不是在寻找这个特定(琐碎)问题的解决方案,我试图探索Haskell的能力,这个问题是我想玩的玩具。 我认为Python的生成器可以很好地解决这个问题。例如: 然后我试图弄清楚Haskell中是否有与这个生成器相似的行为,我认为懒惰对所有员工都没有任何额外的概念。 例如,我们可以用 然后用以下方法解决

  • 我有一个特定的Postgre架构,它收集所有定义类型的表,如,其中的值可以是,等。 我们需要获取所有这些表,并根据它们生成枚举,以便以后在我们的应用程序中使用。因此,这些枚举应该如下所示: 我们决定使用JOOQ看起来很有趣,但是我们找不到留档/示例来创建一个使用默认java生成器行为加上自定义枚举生成扩展的自定义生成器。 基于这篇文章用JOOQ从表中生成枚举类,它带来了一些想法,但仍然不清楚如何实

  • 我想用jQuery开发一个动态表单生成器,用户可以在其中构建自己的表单并更改表单名称、输入类型、大小等。我知道有一些很酷的拖放在线表单生成器,但我想开发一个非常简单的表单生成器。 我已经开始发展这一点,我面临着一些问题。 当用户单击标签(输入字段)时,它会使用jquery和edit and delete按钮动态创建一个输入字段。 下面的代码在div中附加输入字段,该字段现在是空的。 点击文本输入,

  • 我正在尝试获取自定义属性(https://laravel.com/docs/5.5/eloquent-mutators#defining-访问器)从查询中删除。 现在我有: 你ser.php 用户控制器。php 返回 所以问题是:有没有办法也获得view\u url属性?(我用()在内部进行了尝试,但失败了) 我还可以只返回角色名,而不是像您在“return”代码中看到的那样返回整个对象吗?(我想

  • 我正在编写一个通用组件,该组件封装了一个生成器并执行常规操作: 按键筛选 转换值 等等 为了尽可能接近地模拟包装生成器,如果生成器使用引用,我想使用引用。 当我尝试使用 构造的情况下迭代生成器对引用完全不起作用: