[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
continuation curiosity -- for entertainment purposes only
From: |
Stephen Compall |
Subject: |
continuation curiosity -- for entertainment purposes only |
Date: |
Wed, 16 Jul 2003 12:50:07 -0500 |
While writing up an <ahem> interesting example for using call/cc, I
ran into this curiosity. Expressions at the top level are not
considered a single program flow. Observe:
Here is the original source for `ccgrep.scm', including lots of
debugging messages:
;; begin ccgrep.scm
(use-modules (ice-9 rdelim) (srfi srfi-13))
(define debug-message
(lambda args (for-each display args) (newline)))
(define next-match #f)
(display
(let lp ((line (read-line)))
(debug-message "called: " line)
(if (eof-object? line)
(begin (set! next-match #f) "")
(if (string-contains line "bash")
(or (call-with-current-continuation
(lambda (nm)
(debug-message "captured continuation")
(set! next-match nm)
(string-append line "\n")))
(lp (read-line)))
(lp (read-line))))))
(debug-message "value of continuation saver: " next-match)
(and next-match (next-match (begin
(debug-message "calling continuation")
#f)))
(debug-message "quitting")
;; end ccgrep.scm
I piped /etc/passwd to it, and here is the output (with some
unimportant lines taken out):
address@hidden guile]$ guile -s ccgrep.scm < /etc/passwd
called: root:x:0:0:root:/root:/bin/bash
captured continuation
root:x:0:0:root:/root:/bin/bash
value of continuation saver: #<continuation 406 @ 80a4678>
calling continuation
called: bin:x:1:1:bin:/bin:
called: daemon:x:2:2:daemon:/sbin:
<snip>
called: gopher:x:13:30:gopher:/usr/lib/gopher-data:
called: postgres:x:40:41:PostgreSQL Server:/var/lib/pgsql:/bin/bash
captured continuation
postgres:x:40:41:PostgreSQL Server:/var/lib/pgsql:/bin/bash
quitting
Imagine my surprise when it failed to consider the top-level
expressions that report on next-match and run it if it's there as part
of the flow, and skipped to what it hadn't executed --- the "quitting"
message.
So I reworked it as a function created and called in one step:
;; repeat previous setup
((lambda ()
(define next-match #f)
(display
(let lp ((line (read-line)))
(debug-message "called: " line)
(if (eof-object? line)
(begin (set! next-match #f) "")
(if (string-contains line "bash")
(or (call-with-current-continuation
(lambda (nm)
(debug-message "captured continuation")
(set! next-match nm)
(string-append line "\n")))
(lp (read-line)))
(lp (read-line))))))
(debug-message "value of continuation saver: " next-match)
(and next-match (next-match (begin
(debug-message "calling continuation")
#f)))
(debug-message "quitting")))
;; end of ccgrep.scm
...and it worked exactly as I expected it to, as a simple grep
proof-of-concept that displays all lines containing "bash".
I haven't tried using a simple let in place of my one-shot function.
--
Stephen Compall or s11 or sirian
A plumber is needed, the network drain is clogged
- continuation curiosity -- for entertainment purposes only,
Stephen Compall <=