惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
博客园 - Franky
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
L
LangChain Blog
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hacker News: Front Page
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
AI
AI
T
Troy Hunt's Blog
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
Attack and Defense Labs
Attack and Defense Labs

博客园 - NeilChen

恢复 Windows 7 的“回到父目录”按钮 FireFox 脑残的安全设定 SQL Server 事务自动回滚 下载 infoq 网站视频 也做了一下腾讯前端面试题 Select prototyping tools Lisp in Small Parts TechTalk by Peter Seibel on Common Lisp 时隔3年,再做双倍超立方数的题目,这次用Lisp Operation is not valid due to the current state of the object lisp 笔记 - 闭包 Common Lisp 在 Windows 上的开发环境比较 翻译英文技术文章是一件很可耻的事情吗? 写了个博客备份的 ruby 程序 体验 Clozure CL 试用 Portable Allegro Serve Windows XP, Emacs, CLisp, SLIME 关于 Business Rule Engine Irony - 一个 .NET 语言实现工具包 - NeilChen
Racket, SICP stream learning
NeilChen · 2012-05-11 · via 博客园 - NeilChen

在 windows 上重新安装了最新的 Racket 5.2.1.

恍然发现,Common-Lisp 的安装真的比较坑爹啊,Racket 可能才是研究和学习 lisp 比较理想的选择!

不管是 Windows 还是 Ubuntu,自学习 Lisp 以来,Common Lisp 的各种实现 + 开发环境也安装了很多了,每一个配置起来都比较麻烦,也都有这样那样的问题。而相比而言,安装 Racket 却超级傻瓜化。

一番周折后,终于调通了 SICP 220 页开始的对于 stream 的一些示例代码。其中需要注意的是:

书中提到的 cons-stream 是一个 special form, 但是我一开始写成了简单的 function 如下:

; this won't work as a simple function
(define (cons-stream a b)
    (cons a (delay b)))

但这个实际是是不 work 的。如果流比较大或者是无限流,几乎一定会导致无限递归、内存溢出。解决的办法参考了 stack overflow 上一个答案,利用 Racket 的 define-syntax 语法定义宏。其实和 Common Lisp 里宏有点接近,只是定义时使用的语法有差异,用到方括号,详见代码。

和 Common Lisp 中列表的 subseq 函数相似,我简单的实现了一个 stream-subseq 函数,用于截取流中某一区间的子序列,配合 display-stream 函数打印会比较方便的了解流中间任意一段的信息,后面的测试输出代码我基本都这么写了。

通过无限流移位后相加、相乘甚至配合其他运算进行任意组合,是流使用起来感觉最妙的地方。代码中包含了 SICP 原书中附带的一个筛法求素数序列的实现。

通过几个例子简单的试验下来发现,的确 stream 的功效是强大的。因为本质上每一步计算都是惰性求值,所以即使是要估算序列中很后面的数值,也不会像列表那样带来很多分配空间的开销。斐波那契数列可以轻而易举的算到很后面。下面是我调试通过的测试代码:

#lang racket

;(define (delay exp)
;  (lambda () exp))
;  ;(memo-proc (lambda ()
;  ; exp)))
;
;(define (force delayed-object)
;  (delayed-object))
;
;(define (memo-proc proc)
;  (let ((already-run? false) (result false))
;    (lambda ()
;      (if (not already-run?)
;          (begin (set! result (proc))
;                 (set! already-run? true)
;                 result)
;          result))))

(define (stream-car stream) (car stream))

(define (stream-cdr stream) (force (cdr stream)))

; this won't work as a simple function
;(define (cons-stream a b)
;  (cons a (delay b)))

; This is scheme syntax for macro
; http://stackoverflow.com/questions/5610480/scheme-sicp-r5rs-why-is-delay-not-a-special-form
(define-syntax cons-stream
  (syntax-rules ()
    [(cons-stream x y) (cons x (delay y))]))

(define the-empty-stream '())

(define (stream-null? stream)
  (null? stream))

(define (stream-filter pred stream)
  (cond ((stream-null? stream) the-empty-stream)
        ((pred (stream-car stream))
         (cons-stream (stream-car stream)
                      (stream-filter pred (stream-cdr stream))))
        (else (stream-filter pred (stream-cdr stream)))))

(define (stream-ref s n)
  (if (stream-null? s) the-empty-stream
      (if (= n 0)
          (stream-car s)
          (stream-ref (stream-cdr s) (- n 1)))))

(define (stream-map proc . argstreams)
  (if (stream-null? (car argstreams))
      the-empty-stream
      (cons-stream (apply proc (map stream-car argstreams))
                   (apply stream-map 
                          (cons proc (map stream-cdr argstreams))))))

(define (stream-for-each proc s)
  (if (stream-null? s)
      'done
      (begin (proc (stream-car s))
             (stream-for-each proc (stream-cdr s)))))

; Neil, 2012-05-10
(define (stream-subseq stream a b)
  (cond ((stream-null? stream) the-empty-stream)
        ((= a b) the-empty-stream)
        ((> a b) the-empty-stream)
        (else (cons-stream (stream-ref stream a)
              (stream-subseq stream (+ a 1) b)))))

(define (display-line x)
  (newline)
  (display x))

(define (display-stream s)
  (stream-for-each display-line s))

; examples
;(let ((x (delay (+ 1 2))))
;  (for ([i (in-range 1 10)])
;            (display (force x))))
;
(define (integers-starting-from n)
  (cons-stream n (integers-starting-from (+ n 1))))

(define integers
  (integers-starting-from 1))

;(display-line (stream-ref integers 0))
(let ((x (stream-subseq integers 10000 10010)))
  (display-stream x))

(define odd-numbers 
  (stream-filter odd? integers))

(display-stream (stream-subseq odd-numbers 50 60))
  
;(let ((x (cons-stream 1 (cons-stream 2 '(3)))))
;  (display-stream x))

(define (stream-add s n)
  (stream-map (lambda (x)
                (+ x n)) s))

(define (add-streams s1 s2)
  (stream-map + s1 s2))

(define fib
  (cons-stream 1
               (cons-stream 1
                            (add-streams fib
                                        (stream-cdr fib)))))

(display-stream (stream-subseq fib 150 160))


(define (divisible? x y)
  (= (remainder x y) 0))

(divisible? 10 2)

(define (sieve stream)
  (cons-stream
   (stream-car stream)
   (sieve (stream-filter
           (lambda (x)
             (not (divisible? x (stream-car stream))))
           (stream-cdr stream)))))

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

(display-stream (stream-subseq primes 1000 1010))

接下来打算认真体会一下书中提到的欧拉发明的序列加速器的算法。真的是很厉害的 idea.