Streams and the substitution model - stream

I am wondering how the substitution model can be used to show certain things about infinite streams. For example, say you have a stream that puts n in the nth spot and so on inductively. I define it below:
(define all-ints
(lambda ((n <integer>))
(stream-cons n (all-ints (+ 1 n)))))
(define integers (all-ints 1))
It is pretty clear that this does what it is supposed to, but how would someone go about proving it? I decided to use induction. Specifically, induction on k where
(last (stream-to-list integers k))
provides the last value of the first k values of the stream provided, in this case integers. I define stream-to-list below:
(define stream-to-list
(lambda ((s <stream>) (n <integer>))
(cond ((or (zero? n) (stream-empty? s)) '())
(else (cons (stream-first s)
(stream-to-list (stream-rest s) (- n 1)))))))
What I'd like to prove, specifically, is the property that k = (last (stream-to-list integers k)) for all k > 1.
Getting the base case is fairly easy and I can do that, but how would I go about showing the "inductive case" as thoroughly as possible? Since computing the item in the k+1th spot requires that the previous k items also be computed, I don't know how this could be shown. Could someone give me some hints?
In particular, if someone could explain how, exactly, streams are interpreted using the substitution model, I'd really appreciate it. I know they have to be different from the other constructs a regular student would have learned before streams, because they delay computation and I feel like that means they can't be evaluated completely. In turn this would man, I think, the substitution model's apply eval apply etc pattern would not be followed.

stream-cons is a special form. It equalent to wrapping both arguments in lambdas, making them thunks. like this:
(stream-cons n (all-ints (+ 1 n))) ; ==>
(cons (lambda () n) (lambda () (all-ints (+ n 1))))
These procedures are made with the lexical scopes so here n is the initial value while when forcing the tail would call all-ints again in a new lexical scope giving a new n that is then captured in the the next stream-cons. The procedures steam-first and stream-rest are something like this:
(define (stream-first s)
(if (null? (car s))
'()
((car s))))
(define (stream-rest s)
(if (null? (cdr s))
'()
((cdr s))))
Now all of this are half truths. The fact is they are not functional since they mutates (memoize) the value so the same value is not computed twice, but this is not a problem for the substitution model since side effects are off limits anyway. To get a feel for how it's really done see the SICP wizards in action. Notice that the original streams only delayed the tail while modern stream libraries delay both head and tail.

Related

Delayed "let" in SICP

SICP indicates cdr is opened up:
In section 3.5.4 , i saw this block:
(define (integral delayed-integrand initial-value dt)
(define int
(cons-stream initial-value
(let ((integrand (force delayed-integrand)))
(add-streams (scale-stream integrand dt)
int))))
int)
Normally if this was something like:
(define (stream-map proc s)
(if (stream-null? s)
the-empty-stream
(cons-stream (proc (stream-car s))
(stream-map proc (stream-cdr s)))))
The stream-cdr s would be evaluated as (cons-stream (stream-car (cdr s)) delay<>) even when the actual call would be in a delay. ie even though the stream-map function itself is delayed, the arguments are pre-computed. [Is this correct? - By the applicative model, the arguments should be substituted for ,before the function is "called", but is the call evaluation when delay is forced or when it's just specified]
Then why is let not pre-computed?
What i think? I think let is a lambda function with the variable as the arguments, so it's execution is delayed
(let ((var1 e1) (var2 e2)) e3)
is same as
Lambda (var1 var2) e3 (with var1 bound to e1 and var2 bound to e2)
Can someone please help me confirm this? Thanks
In SICP type streams the car of a stream is not delayed, but the cdr is.
The whole expression,
(let ((integrand (force delayed-integrand)))
(add-streams (scale-stream integrand dt)
int))
, is delayed since it is the second argument to cons-stream. What kind of expression is delayed doesn't matter so you can have a call, evaluation of variable or even a let there.
"the arguments are pre-computed. is this correct?"
No. (cons-stream a (func (stream-cdr b))) is just like
(cons-stream a
(lambda ()
;; our code is placed here, verbatim, as a whole:
(func (stream-cdr b))
)
)
const-stream is a macro, it just moves pieces of code around.
The lambda might be enclosed in a memo-proc call for the memoization, to do call-by-need, but it'll still have the code we wrote, like (func (stream-cdr b)), placed inside the lambda, "textually", by cons-stream. Which is a macro, just moving pieces of code around.
Regarding the snippet which you've added to the question, the authors were just being imprecise. What is meant there is, when (stream-cdr stream) in (stream-filter pred (stream-cdr stream)) will be called, it will produce (cons 10008 (delay .... )), as shown. Not before.
Where it says "which in this case is" is should have said "which in this case is the same as".
In section 3.5.1 Streams Are Delayed Lists the book says:
To make the stream implementation automatically and transparently interleave the construction of a stream with its use, we will arrange for the cdr of a stream to be evaluated when it is accessed by the stream-cdr procedure rather than when the stream is constructed by cons-stream.

order matters with return-from in SBCL

I'm on Day 3 of trying to learn Common Lisp (SBCL) by doing Advent of Code. I understand there is more than one type of return. I'm wondering if someone could explain to me why the following function will return nil (this makes sense)
(defun fn (n)
(cond ((zerop n)
(return-from fn nil))
(t
(write-line "Hello World")
(fn (- n 1)))))
but the following function will return "Hello World" (this does not make sense to me).
(defun fn (n)
(cond ((zerop n)
(return-from fn nil))
(t
(fn (- n 1))
(write-line "Hello World"))))
I found a great post covering some aspects of SBCL's return behaviour here, but to my understanding it doesn't seem to address this particular detail.
EDIT: a loop call is a more sensible way of writing this function, but it is not the way that I discovered this behaviour. My suspicion is that this behaviour arises because fn is called recursively.
(I started writing this before Sylwester's answer, which is mostly better I think.)
A critical difference between Lisp-family languages and many other languages is that Lisp-family languages are 'expression languages'. What this means technically is that languages like (say) C or Python there are two sorts of constructs:
expressions, which have values;
statements, which do not;
While in Lisp-family languages there is one sort of thing: expressions, which have values. Lisp-family languages are sometimes called 'expression languages' as a result of this.
This makes a huge difference if you want to write functions, which are things which return values (a function call is an expression in other words).
Conventional languages (Python as an example)
In a language which is not an expression language then if you're defining a function and find yourself in the middle of some construct which is a statement and you want to return a value, you have to use some special magic construct, often called return to do that. So in Python, where conditionals are statements, you might write:
def fib(n):
if n < 2:
return n
else:
return fib(n - 1) + fib(n - 2)
And in fact you have to use return because the body of a function definition in Python is a series of statements, so to return any kind of value at all you need to use return.
In fact, Python (and C, and Java &c &c) have a special form of a conditional which is an expression: in Python this looks like this:
def fib(n):
return n if n < 2 else (fib(n - 1) + fib(n - 2)
It looks different in C but it does the same thing.
But you still need this annoying return (OK, only one of them now) & that brings to light another feature of such languages: if some place in the syntax wants a statement you generally need to have a statement there, or if you can put an expression there its value just gets dropped. So you can try something like this:
def fib(n):
n if n < 2 else (fib(n - 1) + fib(n - 2)
And that's syntactically OK -- the expression gets turned into a statement -- but it fails at runtime because the function no longer returns a useful value. In Python you can get around this if you want people to hate you:
fib = lambda n: n if n < 2 else fib(n - 1) + fib(n - 2)
Python people will hate you if you do this, and it's also not useful, because Python's lambda only takes expressions so what you can write is crippled.
Lisp
Lisp has none of this: in Lisp everything is an expression and therefore everything has a value, you just need to know where it comes from. There is still return (in CL, anyway) but you need to use it much less often.
But, of course people often do want to write programs which look like 'do this, then do this, then do this', where most of the doing is being done for side-effect, so Lisps generally have some kind of sequencing construct, which lets you just have a bunch of expressions one after the other, all but (typically) one of which get evaluated for side-effect. In CL the most common sequencing construct is called progn (for historical reasons). (progn ...) is an expression made of other expressions, and its value is the value of last expression in its body.
progn is so useful in fact that a bunch of other constructs have 'implicit progns' in them. Two examples are function definitions (the body of defun is an implicit progn) and cond (the body of a cond-clause is an implicit `progn).
Your function
Here is your function (first version) with its various parts notated
(defun fn (n)
;; the body of fn is an implicit progn with one expression, so
;; do this and return its value
(cond
;; the value of cond is the value of the selected clause, or nil
((zerop n)
;; the body of this cond clause is an implicit progn with on
;; expression so do this and ... it never returns
(return-from fn nil))
(t
;; the body of this cond clause is an implicit progn with two expressions, so
;; do this for side-effect
(write-line "Hello World")
;; then do this and return its value
(fn (- n 1)))))
Here is the second version
(defun fn (n)
;; the body of fn is an implicit progn with one expression, so
;; do this and return its value
(cond
;; the value of cond is the value of the selected clause, or nil
((zerop n)
;; the body of this cond clause is an implicit progn with on
;; expression so do this and ... it never returns
(return-from fn nil))
(t
;; the body of this cond clause is an implicit progn with two expressions, so
;; do this for side-effect
(fn (- n 1))
;; then do this and return its value
(write-line "Hello World"))))
So you can see what is happening here: in the first version the value that gets returned is either nil or the value of the recursive call (also nil). In the second version the value that gets returned is either nil or whatever write-line returns. And it turns out that write-line returns the value of its argument, so that's what you get if you call it with an integer greater than zero.
Why have return-from at all in Lisp?
One thing that should be immediately clear from this whole expression-language thing is that you hardly ever need to explicitly return something in Lisp: you just have an expression that computes the value you want. But there are two good uses (which perhaps are really the same use) of explicit returns.
The first is that sometimes you are doing some big search for something in the form of a bunch of nested loops and at some point you just want to say 'OK, found it, here's the answer'. You can do that in one of two ways: you can carefully structure your loops so that once you find what you're after they all terminate nicely and the value gets passed back up, or you can just say 'here's the answer'. The latter thing is what return-from does: it just says 'I'm done now, unwind the stack carefully and return this':
(defun big-complicated-search (l m n)
(dotimes (i l)
(dotimes (j m)
(dotimes (k n)
(let ((it (something-involving i j k l m n)))
(when (interesting-p it)
(return-from big-complicated-search it)))))))
And return-from does this in the right way:
(defun big-complicated-file-search (file1 file2)
(with-open-file (f1 file1)
(with-open-file (f2 file2)
...
(when ...
(return-from big-complicated-search found)))))
When you call this, and when the thing is found, return-from will make sure that the two files you have opened are properly closed.
The second, which is really almost the same thing, is that sometimes you need to just give up, and return-from is a good way of doing this: it returns immediately, deals with clean-ups (see above) and is generally a nice way of saying 'OK, I give up now'. At first blush this seems like something you would do with some kind of exception-handling system, but in fact there are two critical differences:
in an exception-handling system (which CL has, of course), you need some kind of exception to raise so you might need to invent something;
exception-handling systems are dynamic not lexical: if you raise an exception then the thing that gets to handle it is hunted for up the stack dynamically: this means that you're at the mercy of anyone who stuck a handler in the way and it also typically rather slow.
Finally the exceptional-return-via-error-handling-mechanism is just, well, horrid.
Your code:
(defun fn (n)
(cond ((zerop n) (return-from fn nil))
(t (write-line "Hello World") (fn (- n 1)))
)
)
There is a bunch of things slightly wrong with above code:
(defun fn (n)
(cond ((zerop n) (return-from fn nil)) ; 1) the return from is not needed
(t (write-line "Hello World") (fn (- n 1))) ; 2) this line is not correctly
; indented
) ; 3) dangling parentheses Don't. Never.
; also: incorrect indentation
)
the first cond clause already returns a value, just write nil as the return value. Then the whole cond returns this value. It is very rare that you need return or return-from from a cond clause.
use an editor to indent your code. In GNU Emacs / SLIME the command control-meta-q will indent the expression. For help about the editor commands in the current mode see: control-h m for mode help.
indent correctly and don't use dangling parentheses. They are useless in Lisp. Learn to use the editor to correctly indent code - that's much more useful than to place wrongly indented parentheses on their own line. tab indents the current line.
It's more useful to format the code like this for a beginner:
(defun fn (n)
(cond ((zerop n)
(return-from fn nil))
(t
(write-line "Hello World")
(fn (- n 1)))))
Code then will look more like a prefix tree.
Also don't forget to disable inserting tabs in GNU Emacs Put this into your emacs init file: (setq-default indent-tabs-mode nil). You can evaluate Emacs Lisp expressions also on the fly with meta>-:.
Now according to 1. above code is usually written as:
(defun fn (n)
(cond ((zerop n)
nil)
(t
(write-line "Hello World")
(fn (- n 1)))))
When n is zero, the first clause is selected and its last value is returned. The other clauses are not looked at -> cond returns nil -> the function fn returns nil.
Usually I would write above recursive function like this:
(defun fn (n)
(unless (zerop n)
(write-line "Hello World")
(fn (- n 1))))
unless returns nil if (zerop n) is true. Another variant:
(defun fn (n)
(when (plusp n)
(write-line "Hello World")
(fn (- n 1))))
You CAN use return-from, but in case it was not clear: you don't need it most of the time.
Unlike C language family Lisp has the feature that everything is expressions. That means you "return" the result of an expression. eg.
(+ (if (< x 0)
(- x)
x)
3)
Here the result of the if is that it will be the absolute value of x. Thus if x is -5 or 5 the result of the expression is 8. You can write abs like this:
(defun my-abs (v)
(if (< v 0)
(- v)
v))
Notice I do not use return. THe result of the if is the last expression and that means the result of that is the result of my-abs.
Your two functions can be written like this:
(defun fn1 (n)
(cond
((zerop n) nil)
(t (write-line "Hello World") (fn1 (- n 1)))))
And
(defun fn2 (n)
(cond
((zerop n) nil)
(t (fn2 (- n 1)) (write-line "Hello World"))))
Needless to say (write-line "Hello World") returns its argument in addition to print the argument. Thus whenever it is the last expression it will be the result.
For every n above 0 it will do the recursions first and each end every one except the first will return "Hello World". If you call (fn2 0) the result is nil, the same as fn1.
EDIT
One might ask what is the purpose of return and return-from when there obviously is little use for it. If you want something else than the default result in a loop macro the common way to do it by finally clause.
(defun split-by (test list &key (return-form #'values))
"Split a list in two groups based on test"
(loop :for e :in list
:if (funcall test e)
:collect e :into alist
:else
:collect e :into blist
:finally (return (funcall return-form alist blist))))
(split-by #'oddp '(1 2 3 4) :return-form #'list)
; ==> ((1 3) (2 4))
Another way is if you are doing recursion and want to cancel everything when you know the result you can use return-from:
(defun find-tree-p (needle haystack &key (test #'eql))
"search the tree for element using :test as comparison"
(labels ((helper (tree)
(cond ((funcall test tree needle)
(return-from find-tree t))
((consp tree)
(helper (car tree))
(helper (cdr tree)))
(t nil))))
(helper haystack)))
(find-tree '(f g) '(a b c (d e (f g) q) 1 2 3) :test #'equal)
; ==> (f g) ; t
Now if you hadn't done return-from you would have had logic to check the returned value to see if you needed to continue or not. If you want to process elements and don't want to pass twice to check validity before computing the result, you can just start computing and use return-from as a call/cc. This function can be used to map over lists of lists and it stops at the shortest list so needs to become () when the first sublist is empty:
(defun cdrs (lists)
"return the cdrs if all elements are cons, () otherwise"
(loop :for list :in lists
:when (null list) :do (return-from cdrs '())
:collect (cdr list)))
(cdrs '((a) (b) (c))) ; ==> (nil nil nil)
(cdrs '((a) (b) ())) ; ==> ()

How do I jump out of a function in Lisp?

Is it possible in (Common) Lisp to jump to another function instead of call another?
I mean, that the current function is broken and another is called, without jumping back through thousands of functions, as if I'd decide myself if tail call optimization is done, even if it is not the tail.
I'm not sure if "(return-from fn x)" does, what I want.
Example:
(defun fn (x)
(when x
(princ x)
(jump 'fn (cdr x)))
(rest))
'jump' should be like calling the following function without saving the position of this function, instead returning to, where the original funcall was, so that there will be no stack overflow.
'rest' should only be executed if x is nil.
When you need a tail call optimization like structure in a language that doesn't (necessarily) provide it, but does provide closures, you can use a trampoline to achieve constant stack space (with a trade off for heap space for closure objects, of course). This isn't quite the same as what you asking for, but you might find it useful. It's pretty easy to implement in Common Lisp:
(defstruct thunk closure)
(defmacro thunk (&body body)
`(make-thunk :closure (lambda () ,#body)))
(defun trampoline (thunk)
(do ((thunk thunk (funcall (thunk-closure thunk))))
((not (thunk-p thunk)) thunk)))
To use the trampoline, you just call it with a thunk that performs the first part of your computation. That closure can either return another thunk, or a result. If it returns a thunk, then since it returned the initial stack frame is reclaimed, and then the closure of returned thunk is invoked. For instance, here's what an implementation of non-variadic mapcar might look like:
(defun t-mapcar1 (function list)
(labels ((m (list acc)
(if (endp list)
(nreverse acc)
(thunk
(m (rest list)
(list* (funcall function (first list)) acc))))))
(m list '())))
When the list is empty, we get an empty list immediately:
CL-USER> (t-mapcar1 '1+ '())
NIL
When it's not, we get back a thunk:
CL-USER> (t-mapcar1 '1+ '(1 2))
#S(THUNK :CLOSURE #<CLOSURE (LAMBDA #) {10033C7B39}>)
This means that we should wrap a call with trampoline (and this works fine for the base case too, since trampoline passes non-thunk values through):
CL-USER> (trampoline (t-mapcar1 '1+ '()))
NIL
CL-USER> (trampoline (t-mapcar1 '1+ '(1 2)))
(2 3)
CL-USER> (trampoline (t-mapcar1 '1+ '(1 2 3 4)))
(2 3 4 5)
Your example code isn't quite enough to be an illustrative example, but
(defun fn (x)
(when x
(princ x)
(jump 'fn (cdr x)))
(rest))
would become the following. The return provides the early termination from fn, and the thunk value that's returned provides the “next” computation that the trampoline would invoke for you.
(defun fn (x)
(when x
(princ x)
(return (thunk (fn (cdr x)))))
(rest))
How about you use a tail call?
(defun fn (x)
(if x
(progn
(princ x)
(fn (cdr x)))
(progn
(rest))))
It calls fn in a tail position. If an implementation provides tail call optimization, you won't get a stack overflow. If you don't want to rely on that, you would need to handle the problem in a non recursive way. There are no explicit 'remove this functions stack frame and then call function X' operators in Common Lisp.
Well, not really. I once did experiment with
(defmacro recurr (name bindings &body body)
(let* ((names (mapcar #'car bindings))
(restart (gensym "RESTART-"))
(temp1 (gensym))
(temp2 (gensym))
(shadows (mapcar (lambda (name) (declare (ignore name)) (gensym)) names)))
`(block ,name
(let ,bindings
(macrolet ((,name ,shadows
(list 'progn
(cons 'psetq
(loop
:for ,temp1 :in ',names
:for ,temp2 :in (list ,#shadows)
:nconcing (list ,temp1 ,temp2)))
(list 'go ',restart))))
(tagbody
,restart
(progn ,#body)))))))
and to be used like scheme's named-let, e.g.:
(recurr traverse ((list '(1 2 3 4)))
(if (null list) 'end
(traverse (cdr list))))
but:
The object defined (traverse in the example) is not a function, i.e., you cannot funcall or apply it
This kind of construct doesn't really cope with recursive structures (i.e., since no stack is kept, you cannot use it to traverse over arbitrary trees instead of sequences)
Another approach might be
(defmacro label (name (&rest bindings) &body body)
`(labels ((,name ,(mapcar #'first bindings) ,#body))
(,name ,#(mapcar #'second bindings))))
which actually addresses the points mentioned, but loses the "look ma, no stack space consing" property.

SICP Infinite Streams (Chapter 3.5.2)

This is a question related to the SICP Book Chapter 3.5.2.
I'm implementing a stream data structure in other programming languages. And I'm not sure if I understand the following snippet correctly.
(define (integers-starting-from n)
(cons-stream n (integers-starting-from (+ n 1))))
(define integers (integers-starting-from 1))
From what I understood at (integers-starting-from (+ n 1)) will execute the function which return a value by executing(cons-stream n (integers-starting-from (+ n 1)))). Because the second formal parameter of the cons-stream is (integers-starting-from (+ n 1)), and because it is enclosed by( ), thus it will execute the function again and again infinitely instead of delaying the execution.
From what I see before executing this snippet, It seems that the following integer will leads to an infinite recursive before even the seconds element of the stream being executed.
Why does this seems to work for scheme as shown during the lecture?
From my understand it should be written something like this instead:
(define (integers-starting-from n)
(cons-stream n (lambda() (integers-starting-from (+ n 1)))))
(define integers (integers-starting-from 1))
Does this means that scheme has some kinds of magic that delay the execution of (integers-starting-from (+ n 1)) ?
Thank you in advance
The trick lies in how we implement cons-stream. You explicitly created an evaluation promise when you defined the (lambda () ...) thunk. The special form cons-stream does this, but implicitly and using Scheme's primitives. For example, it can be implemented like this, notice how we use delay:
(define-syntax stream-cons
(syntax-rules ()
((stream-cons head tail)
(cons head (delay tail)))))
It makes more sense to encapsulate all the promise-creation logic in a single place, say cons-stream, instead of explicitly creating thunks everywhere.

Scheme console printing

Just started with Scheme. I'm having problem with printing on console.
A simple list printing example:
(define factorial
(lambda (n)
(cond
((= 0 n) 1)
(#t (* n (factorial (- n 1)))))))
I want to print n, every time the function is called. I figured that I can't do that within the same function? Do I need to call another function just so I can print?
Printing in Scheme works by calling display (and possibly, newline).
Since you want to call it sequentially before/after something else (which, in a functional (or in the case of Scheme, functional-ish) language only makes sense for the called functions side-effects), you would normally need to use begin, which evaluates its arguments in turn and then returns the value of the last subexpression. However, lambda implicitly contains such a begin-expression.
So in your case, it would go like this:
(lambda (n)
(display n) (newline)
(cond [...]))
Two remarks:
You can use (define (factorial n) [...]) as a shorthand for (define factorial (lambda (n) [...])).
The way you implement factorial forbids tail call-optimization, therefore the program will use quite a bit of stack space for larger values of n. Rewriting it into a optimizable form using an accumulator is possible, though.
If you only want to print n once, when the user calls the function, you will indeed need to write a wrapper, like this:
(define (factorial n)
(display n) (newline)
(inner-factorial n))
And then rename your function to inner-factorial.

Resources