4

要在 Lisp 中将流实现为延迟列表,建议使用 Lisp 宏。

(defmacro cons-stream (a b)
   (cons ,a (delay ,b)))

(defmacro delay (expr)
  `(memo-proc (lambda () ,expr)))

Python 和 Perl 会怎样做同样的事情?

编辑。是否可以使用如此酷的构造作为流

(define primes (sieve (integers-starting-from 2)))

在 Python 和 Perl 等语言中

4

4 回答 4

5

在 Python 中,最接近的结构可能是生成器表达式。

在 Perl 中,没有原生惰性列表,但该语言提供了构建一个惰性列表所需的所有原语。我编写了一个名为List::Gen的惰性列表库,可在 CPAN 上使用。

use List::Gen '*';

my $primes = <2..>->filter(\&is_prime);  # where you provide &is_prime

say "@$primes[0..10]";  # lazily finds the first 11 primes

<2..>位可以详细地写为range(2, 9**9**9)

于 2011-06-27T20:51:27.503 回答
4

Perl

runrig 建议使用 Mark Dominus 出色的Higher Order Perl中的技术。使用HOP 的免费示例代码中的Stream 模块,Eratosthenes 的筛子是

#! /usr/bin/env perl

use strict;
use warnings;

use Stream qw/ filter head node promise show tail upfrom /;

use subs 'sieve';  # no parens on recursive calls
sub sieve {
  my($s) = @_;
  my $n = head $s;
  node $n, promise { sieve filter { $_[0] % $n != 0 } tail $s };
}

sub primes { sieve upfrom 2 }

show primes, 10;

输出:

$ ./素数
2 3 5 7 11 13 17 19 23 29

Python

借用alexbowe的 gist 代码,Python 中使用流的筛子是

#! /usr/bin/env python

null_stream = (None, None)

def reduce(f, result, stream):
    if stream is null_stream: return result
    return reduce(f, f(result, head(stream)), tail(stream))

def take(N, stream):
    if N <= 0 or stream is null_stream: return null_stream
    return (head(stream), lambda: take(N-1, tail(stream)))

def filter(pred, stream):
    if stream is null_stream: return null_stream
    if pred(head(stream)):
        return (head(stream), lambda: filter(pred, tail(stream)))
    return filter(pred, tail(stream))

def integers_from(N): return (N, lambda: integers_from(N+1))
def head((H, _)): return H
def tail((_, T)): return T()
def to_array(stream): return reduce(lambda a, x: a + [x], [], stream)

def sieve(stream):
    if stream is null_stream: return null_stream
    h = head(stream)
    return (h, lambda: sieve(filter(lambda x: x%h != 0, tail(stream))))

def primes(): return sieve(integers_from(2))

print to_array(take(10, primes()))

输出:

$ ./prymes
[2、3、5、7、11、13、17、19、23、29]

其他可能性

在某些语言中,流模式是不可见的。例如,惰性求值是 Haskell 的一个特性,因此您可以定义primes

primes = sieve [2 ..]
  where sieve (x:xs) =
          let remains = filter (not . isMultipleOf x) xs
          in x : sieve remains
        isMultipleOf a b = b `mod` a == 0
于 2011-06-27T21:13:41.490 回答
3

在 perl 中,您将使用匿名子例程(如 LISP 的 lambda)。高阶 Perl的第 6 章有很多例子

于 2011-06-27T19:31:16.823 回答
1

虽然很难说出您真正想要什么,但由于不同语言之间的许多事情都存在细微差别,您正在寻找的 Python 等价物可能是generator,它是一种可以被要求产生下一个值的函数,并且然后暂停自己。它们之前在(例如)你可以使用 Python 生成器函数做什么?,并且在其他地方有很多关于它们的示例和教程——例如,http://www.dabeaz.com/generators/index.html

于 2011-06-27T19:25:58.880 回答