From: Kevin M. Rosenberg Date: Sat, 15 Mar 2003 00:48:56 +0000 (+0000) Subject: r4200: *** empty log message *** X-Git-Tag: debian-1.2.1-3~10 X-Git-Url: http://git.kpe.io/?p=pipes.git;a=commitdiff_plain;h=439ba38fc06701c4db33f9aaf5ab17a0c88ea6ca r4200: *** empty log message *** --- diff --git a/COPYING b/COPYING index 1d7faa2..d095466 100644 --- a/COPYING +++ b/COPYING @@ -1,7 +1,7 @@ Pipes's Copyright Statement --------------------------- -Copyright (c) 2000-2002 Kevin Rosenberg +Copyright (c) 2000-2003 Kevin Rosenberg Copyright (c) 1998-2002 Peter Norvig All rights reserved. diff --git a/debian/changelog b/debian/changelog index 2cb73c4..8a260ce 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +cl-pipes (1.1-1) unstable; urgency=low + + * Fix bug in examples file. Add ln2 examples to run-examples + * Rename pipes.lisp to src.lisp + * Update standards-version to 3.5.9.0 (no changes needed) + * Expand long description + + -- Kevin M. Rosenberg Fri, 14 Mar 2003 13:57:08 -0700 + cl-pipes (1.0-2) unstable; urgency=low * Remove 'load-compiled-op from .asd file diff --git a/debian/control b/debian/control index 8c01b6b..21ece44 100644 --- a/debian/control +++ b/debian/control @@ -3,11 +3,12 @@ Section: devel Priority: optional Maintainer: Kevin M. Rosenberg Build-Depends-Indep: debhelper (>= 4.0.0) -Standards-Version: 3.5.8.0 +Standards-Version: 3.5.9.0 Package: cl-pipes Architecture: all Depends: ${shlibs:Depends}, common-lisp-controller (>= 3.47) Description: Common Lisp library for pipes or streams This package has functions for manipulating pipes, also called streams. - + This package is adapted from an implementation in Peter Norvig's + Paradigms of Artificial Intelligence Programming. diff --git a/debian/copyright b/debian/copyright index 27686ae..ef1d4a9 100644 --- a/debian/copyright +++ b/debian/copyright @@ -7,7 +7,7 @@ Upstream Authors: Kevin Rosenberg & Peter Norvig Pipes's Copyright Statement --------------------------- -Copyright (c) 2000-2002 Kevin Rosenberg +Copyright (c) 2000-2003 Kevin Rosenberg Copyright (c) 1998-2002 Peter Norvig All rights reserved. diff --git a/pipes-example.lisp b/pipes-example.lisp index 2cf07f6..3ce8cc0 100644 --- a/pipes-example.lisp +++ b/pipes-example.lisp @@ -1,111 +1,119 @@ -;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- -;;;; ************************************************************************* -;;;; FILE IDENTIFICATION -;;;; -;;;; Name: pipes-examples.lisp -;;;; Purpose: Pipe examples -;;;; Programmer: Kevin M. Rosenberg -;;;; Date Started: Apr 2000 -;;;; -;;;; $Id: pipes-example.lisp,v 1.2 2002/11/07 20:26:13 kevin Exp $ -;;;; -;;;; This file, part of pipes, is Copyright (c) 2002 by Kevin M. Rosenberg -;;;; -;;;; ************************************************************************* - -(in-package #:pipes-user) - - -(defun integers (&optional (start 0) end) - (if (or (null end) (<= start end)) - (make-pipe start (integers (+ start 1) end)) - nil)) - -(defun fibgen (a b) - (make-pipe a (fibgen b (+ a b)))) - -(defun fibs () - (fibgen 0 1)) - - -(defun divisible? (x y) - (zerop (rem x y))) - -(defun no-sevens () - (pipe-filter #'(lambda (x) (not (divisible? x 7))) (integers))) - - -(defun sieve (stream) - (make-pipe - (pipe-head stream) - (sieve (pipe-filter - #'(lambda (x) - (not (divisible? x (pipe-head stream)))) - (pipe-tail stream))))) - -(defun primes () - (sieve (integers 2))) - - -;; Pi - -(defun scale-pipe (factor pipe) - (pipe-map #'(lambda (x) (* x factor)) pipe)) - -(defun sum-pipe (sum s) - (make-pipe sum - (sum-pipe (+ sum (pipe-head s)) - (pipe-tail s)))) - -(defun partial-sums (s) - (make-pipe (pipe-head s) (sum-pipe 0 s))) - -(defun pi-summands (n) - (make-pipe (/ 1d0 n) - (pipe-map #'- (pi-summands (+ n 2))))) - -(defun pi-stream () - (scale-pipe 4d0 (partial-sums (pi-summands 1)))) - -(defun square (x) - (* x x)) - -(defun euler-transform (s) - (let ((s0 (pipe-elt s 0)) - (s1 (pipe-elt s 1)) - (s2 (pipe-elt s 2))) - (if (and s0 s1 s2) - (if (eql s1 s2) ;;; series has converged - +empty-pipe+ - (make-pipe (- s2 (/ (square (- s2 s1)) - (+ s0 (* -2 s1) s2))) - (euler-transform (pipe-tail s)))) - +empty-pipe+))) - - -(defun ln2-summands (n) - (pipe-map (/ 1d0 n) - (pipe-map #'- (ln2-summands (1+ n))))) - -(defun ln2-stream () - (partial-sums (ln2-summands 1))) - -(defun make-tableau (transform s) - (make-pipe s - (make-tableau transform - (funcall transform s)))) - -(defun accelerated-sequence (transform s) - (pipe-map #'pipe-head - (make-tableau transform s))) - - -(defun run-examples () - (let ((*print-length* 20)) - (format t "~&pi-stream: ~S" - (pipe-values (pi-stream) 10)) - (format t "~&euler-transform: ~S" - (pipe-values (euler-transform (pi-stream)) 10)) - (format t "~&accelerate-sequence: ~S" - (pipe-values - (accelerated-sequence #'euler-transform (pi-stream)) 10)))) +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: pipes-examples.lisp +;;;; Purpose: Pipe examples +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Apr 2000 +;;;; +;;;; $Id: pipes-example.lisp,v 1.3 2003/03/15 00:48:56 kevin Exp $ +;;;; +;;;; This file, part of pipes, is Copyright (c) 2002 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:pipes-user) + + +(defun integers (&optional (start 0) end) + (if (or (null end) (<= start end)) + (make-pipe start (integers (+ start 1) end)) + nil)) + +(defun fibgen (a b) + (make-pipe a (fibgen b (+ a b)))) + +(defun fibs () + (fibgen 0 1)) + + +(defun divisible? (x y) + (zerop (rem x y))) + +(defun no-sevens () + (pipe-filter #'(lambda (x) (not (divisible? x 7))) (integers))) + + +(defun sieve (stream) + (make-pipe + (pipe-head stream) + (sieve (pipe-filter + #'(lambda (x) + (not (divisible? x (pipe-head stream)))) + (pipe-tail stream))))) + +(defun primes () + (sieve (integers 2))) + + +;; Pi + +(defun scale-pipe (factor pipe) + (pipe-map #'(lambda (x) (* x factor)) pipe)) + +(defun sum-pipe (sum s) + (make-pipe sum + (sum-pipe (+ sum (pipe-head s)) + (pipe-tail s)))) + +(defun partial-sums (s) + (make-pipe (pipe-head s) (sum-pipe 0 s))) + +(defun pi-summands (n) + (make-pipe (/ 1d0 n) + (pipe-map #'- (pi-summands (+ n 2))))) + +(defun pi-stream () + (scale-pipe 4d0 (partial-sums (pi-summands 1)))) + +(defun square (x) + (* x x)) + +(defun euler-transform (s) + (let ((s0 (pipe-elt s 0)) + (s1 (pipe-elt s 1)) + (s2 (pipe-elt s 2))) + (if (and s0 s1 s2) + (if (eql s1 s2) ;;; series has converged + +empty-pipe+ + (make-pipe (- s2 (/ (square (- s2 s1)) + (+ s0 (* -2 s1) s2))) + (euler-transform (pipe-tail s)))) + +empty-pipe+))) + + +(defun ln2-summands (n) + (make-pipe (/ 1d0 n) + (pipe-map #'- (ln2-summands (1+ n))))) + +(defun ln2-stream () + (partial-sums (ln2-summands 1))) + +(defun make-tableau (transform s) + (make-pipe s + (make-tableau transform + (funcall transform s)))) + +(defun accelerated-sequence (transform s) + (pipe-map #'pipe-head + (make-tableau transform s))) + + +(defun run-examples () + (let ((*print-length* 20)) + (format t "~&pi-stream:~& ~S" + (pipe-values (pi-stream) 10)) + (format t "~& pi-stream euler-transform:~& ~S" + (pipe-values (euler-transform (pi-stream)) 10)) + (format t "~& pi-stream accelerate-sequence:~& ~S" + (pipe-values + (accelerated-sequence #'euler-transform (pi-stream)) 10))) + (format t "~&ln2-stream:~& ~S" + (pipe-values (ln2-stream) 10)) + (format t "~& ln2-stream euler-transform:~& ~S" + (pipe-values (euler-transform (ln2-stream)) 10)) + (format t "~& ln2-stream accelerate-sequence:~& ~S" + (pipe-values + (accelerated-sequence #'euler-transform (ln2-stream)) 10))) + diff --git a/pipes.asd b/pipes.asd index 09c7be5..5922c74 100644 --- a/pipes.asd +++ b/pipes.asd @@ -7,7 +7,7 @@ ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Apr 2000 ;;;; -;;;; $Id: pipes.asd,v 1.2 2002/11/08 16:51:40 kevin Exp $ +;;;; $Id: pipes.asd,v 1.3 2003/03/15 00:48:56 kevin Exp $ ;;;; ;;;; This file, part of PIPES, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ************************************************************************* @@ -23,6 +23,6 @@ (pushnew :pipes cl:*features*)) :components ((:file "package") - (:file "pipes" :depends-on ("package")))) + (:file "src" :depends-on ("package")))) diff --git a/pipes.lisp b/pipes.lisp deleted file mode 100644 index 68a9b2f..0000000 --- a/pipes.lisp +++ /dev/null @@ -1,125 +0,0 @@ -;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- -;;;; ************************************************************************* -;;;; FILE IDENTIFICATION -;;;; -;;;; Name: pipes.lisp -;;;; Purpose: Pipes based on ideas from Norvig's PAIP book -;;;; Programmers: Kevin M. Rosenberg and Peter Norvig -;;;; Date Started: Apr 2000 -;;;; -;;;; $Id: pipes.lisp,v 1.3 2002/11/08 16:51:40 kevin Exp $ -;;;; -;;;; This file is Copyright (c) 2000-2002 by Kevin M. Rosenberg and -;;;; Copyright (c) 1998-2002 by Peter Norvig. -;;;; ************************************************************************* - -(in-package :pipes) - - -(defconstant +empty-pipe+ nil) - -(defmacro make-pipe (head tail) - "Create a pipe by evaluating head and delaying tail." - `(cons ,head #'(lambda () ,tail))) - -(defun pipe-tail (pipe) - "Return tail of pipe or list, and destructively update - the tail if it is a function." - (if (functionp (rest pipe)) - (setf (rest pipe) (funcall (rest pipe))) - (rest pipe))) - -(defun pipe-head (pipe) (first pipe)) - -(defun pipe-elt (pipe i) - "The i-th element of pipe, 0-based." - (if (= i 0) - (pipe-head pipe) - (pipe-elt (pipe-tail pipe) (- i 1)))) - - -(defun pipe-enumerate (pipe &key count key (result pipe)) - "Go through all (or count) elements of pipe, - possibly applying the KEY function. (Try PRINT.)" - ;; Returns RESULT, which defaults to the pipe itself. - (if (or (eq pipe +empty-pipe+) (eql count 0)) - result - (progn - (unless (null key) (funcall key (pipe-head pipe))) - (pipe-enumerate (pipe-tail pipe) - :count (if count (1- count)) - :key key :result result)))) - -(defun pipe-values (pipe &optional count) - "Simple wrapper to return values of a pipe" - (pipe-enumerate pipe :count count)) - -(defun pipe-force (pipe) - "Force the enumeration of all of the pipe. Never returns -if the pipe is infinite in length." - (pipe-enumerate pipe)) - -(defun pipe-filter (predicate pipe) - "Keep only items in pipe satisfying predicate." - (if (eq pipe +empty-pipe+) - +empty-pipe+ - (let ((head (pipe-head pipe)) - (tail (pipe-tail pipe))) - (if (funcall predicate head) - (make-pipe head (pipe-filter predicate tail)) - (pipe-filter predicate tail))))) - - -(defun pipe-map (fn pipe) - "Map fn over pipe, delaying all but the first fn call." - (if (eq pipe +empty-pipe+) - +empty-pipe+ - (make-pipe (funcall fn (pipe-head pipe)) - (pipe-map fn (pipe-tail pipe))))) - - -(defun pipe-map-filtering (fn pipe &optional filter-pred) - "Map fn over pipe, delaying all but the first fn call, - while filtering results." - (if (eq pipe +empty-pipe+) - +empty-pipe+ - (let* ((head (pipe-head pipe)) - (tail (pipe-tail pipe)) - (result (funcall fn head))) - (if (or (and filter-pred (funcall filter-pred result)) - result) - (make-pipe result (pipe-map-filtering fn tail filter-pred)) - (pipe-map-filtering fn tail filter-pred))))) - - -(defun pipe-append (x y) - "Return a pipe that appends the elements of x and y." - (if (eq x +empty-pipe+) - y - (make-pipe (pipe-head x) - (pipe-append (pipe-tail x) y)))) - - -(defun pipe-mappend (fn pipe) - "Lazily map fn over pipe, appending results." - (if (eq pipe +empty-pipe+) - +empty-pipe+ - (let ((x (funcall fn (pipe-head pipe)))) - (make-pipe (pipe-head x) - (pipe-append (pipe-tail x) - (pipe-mappend fn (pipe-tail pipe))))))) - -(defun pipe-mappend-filtering (fn pipe &optional filter-pred) - "Map fn over pipe, delaying all but the first fn call, - appending results while filtering." - (if (eq pipe +empty-pipe+) - +empty-pipe+ - (let* ((head (pipe-head pipe)) - (tail (pipe-tail pipe)) - (result (funcall fn head))) - (if (or (and filter-pred (funcall filter-pred result)) - result) - (make-pipe (pipe-head result) - (pipe-append (pipe-tail result) - (pipe-mappend-filtering fn tail filter-pred))) - (pipe-mappend-filtering fn tail filter-pred))))) diff --git a/src.lisp b/src.lisp new file mode 100644 index 0000000..61f852b --- /dev/null +++ b/src.lisp @@ -0,0 +1,125 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: pipes.lisp +;;;; Purpose: Pipes based on ideas from Norvig's PAIP book +;;;; Programmers: Kevin M. Rosenberg and Peter Norvig +;;;; Date Started: Apr 2000 +;;;; +;;;; $Id: src.lisp,v 1.1 2003/03/15 00:48:56 kevin Exp $ +;;;; +;;;; This file is Copyright (c) 2000-2002 by Kevin M. Rosenberg and +;;;; Copyright (c) 1998-2002 by Peter Norvig. +;;;; ************************************************************************* + +(in-package :pipes) + + +(defconstant +empty-pipe+ nil) + +(defmacro make-pipe (head tail) + "Create a pipe by evaluating head and delaying tail." + `(cons ,head #'(lambda () ,tail))) + +(defun pipe-tail (pipe) + "Return tail of pipe or list, and destructively update + the tail if it is a function." + (if (functionp (rest pipe)) + (setf (rest pipe) (funcall (rest pipe))) + (rest pipe))) + +(defun pipe-head (pipe) (first pipe)) + +(defun pipe-elt (pipe i) + "The i-th element of pipe, 0-based." + (if (= i 0) + (pipe-head pipe) + (pipe-elt (pipe-tail pipe) (- i 1)))) + + +(defun pipe-enumerate (pipe &key count key (result pipe)) + "Go through all (or count) elements of pipe, + possibly applying the KEY function. (Try PRINT.)" + ;; Returns RESULT, which defaults to the pipe itself. + (if (or (eq pipe +empty-pipe+) (eql count 0)) + result + (progn + (unless (null key) (funcall key (pipe-head pipe))) + (pipe-enumerate (pipe-tail pipe) + :count (if count (1- count)) + :key key :result result)))) + +(defun pipe-values (pipe &optional count) + "Simple wrapper to return values of a pipe" + (pipe-enumerate pipe :count count)) + +(defun pipe-force (pipe) + "Force the enumeration of all of the pipe. Never returns +if the pipe is infinite in length." + (pipe-enumerate pipe)) + +(defun pipe-filter (predicate pipe) + "Keep only items in pipe satisfying predicate." + (if (eq pipe +empty-pipe+) + +empty-pipe+ + (let ((head (pipe-head pipe)) + (tail (pipe-tail pipe))) + (if (funcall predicate head) + (make-pipe head (pipe-filter predicate tail)) + (pipe-filter predicate tail))))) + + +(defun pipe-map (fn pipe) + "Map fn over pipe, delaying all but the first fn call." + (if (eq pipe +empty-pipe+) + +empty-pipe+ + (make-pipe (funcall fn (pipe-head pipe)) + (pipe-map fn (pipe-tail pipe))))) + + +(defun pipe-map-filtering (fn pipe &optional filter-pred) + "Map fn over pipe, delaying all but the first fn call, + while filtering results." + (if (eq pipe +empty-pipe+) + +empty-pipe+ + (let* ((head (pipe-head pipe)) + (tail (pipe-tail pipe)) + (result (funcall fn head))) + (if (or (and filter-pred (funcall filter-pred result)) + result) + (make-pipe result (pipe-map-filtering fn tail filter-pred)) + (pipe-map-filtering fn tail filter-pred))))) + + +(defun pipe-append (x y) + "Return a pipe that appends the elements of x and y." + (if (eq x +empty-pipe+) + y + (make-pipe (pipe-head x) + (pipe-append (pipe-tail x) y)))) + + +(defun pipe-mappend (fn pipe) + "Lazily map fn over pipe, appending results." + (if (eq pipe +empty-pipe+) + +empty-pipe+ + (let ((x (funcall fn (pipe-head pipe)))) + (make-pipe (pipe-head x) + (pipe-append (pipe-tail x) + (pipe-mappend fn (pipe-tail pipe))))))) + +(defun pipe-mappend-filtering (fn pipe &optional filter-pred) + "Map fn over pipe, delaying all but the first fn call, + appending results while filtering." + (if (eq pipe +empty-pipe+) + +empty-pipe+ + (let* ((head (pipe-head pipe)) + (tail (pipe-tail pipe)) + (result (funcall fn head))) + (if (or (and filter-pred (funcall filter-pred result)) + result) + (make-pipe (pipe-head result) + (pipe-append (pipe-tail result) + (pipe-mappend-filtering fn tail filter-pred))) + (pipe-mappend-filtering fn tail filter-pred)))))