【问题标题】:python delayed executionpython延迟执行
【发布时间】:2011-09-23 18:41:09
【问题描述】:

要在 Lisp 中实现 streams as delayed lists,使用 Lisp 宏是 recommended

(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 等语言中

【问题讨论】:

  • Python 使用generators 来做这种事情。
  • 在 Lisp 中并没有什么特别之处(当然除了宏的使用),但它与迭代器或生成器不同。它们有时可用于实现类似的解决方案,但它们的界面却截然不同。

标签: python perl lisp sicp


【解决方案1】:

虽然很难说出您实际想要什么,但由于不同语言之间的许多事情都存在细微差别,您正在寻找的 Python 等价物可能是 generator ,这是一种可以被要求产生下一个值然后将自身挂起的函数。它们以前在(例如)What can you use Python generator functions for? 中有所介绍,并且在其他地方有很多关于它们的示例和教程——例如,http://www.dabeaz.com/generators/index.html

【讨论】:

  • 不! -- 生成器与惰性列表不同。主要区别在于它们提供了一个功能接口,而生成器仅限于获取当前结果。
  • 是的,不同的语言不同的东西是不同的。
  • 这些是不同的功能,时期。不仅仅是一些通用的“不同的东西看起来不同”。换句话说,这不是问题的答案。在 Python 中创建惰性列表可能很容易——结果确实看起来与在 Lisp 中不同,但它不会是生成器。 (这里有一个提示:实现生成器需要低级支持,例如获取延续;实现惰性列表只需要一流的函数。)
【解决方案2】:

在 perl 中,您将使用匿名子例程(如 LISP 的 lambda)。在chapter 6Higher Order Perl 中有很多例子

【讨论】:

    【解决方案3】:

    在 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
    

    &lt;2..&gt; 位可以写成range(2, 9**9**9)

    【讨论】:

      【解决方案4】:

      Perl

      runrig suggested Mark Dominus 的优秀技术Higher Order Perl。使用 HOP 的免费示例代码中的Stream module,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;
      

      输出:

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

      Python

      借用gist by alexbowe的代码,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
      

      【讨论】:

      • 非常感谢您的详细解答
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-25
      • 2018-02-25
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多