Language Evaluation question: Eager Vs. Lazy - language-agnostic

I was reading Shriram's PLAI and this I got stuck in these questions:
Can you prove that the eager and lazy regimes will always produce the same answer? (Shriram asks to look at the language he developed but is there another way to prove this and how?)
Will eager evaluation always reduce with fewer steps?
Here is the Code of Substitution and Eager Evaluation in Clojure.
;; Gets W-lang and returns the computed number
;; (evaluate (let x (num 10) (let y x x)) -> 10
;; (evaluate (let x (num 10) (let y (add x (num 10)) y)) ->20
;; (evaluate (let x 10 (let x x x ))) -> 10
;; (evaluate (let x 10 (let x (+ 10 x)
;; (let y (let y (+ 10 x) y)
;; (+ x y))))-> 50
(defn evaluate[W-lang]
(condp = (first W-lang)
'num (second W-lang)
'add (+ (evaluate (second W-lang))
(evaluate (third W-lang)))
'sub (- (evaluate (second W-lang))
(evaluate (third W-lang)))
'let (evaluate (subst (second W-lang)(third W-lang)
(forth W-lang)))))
;; subst: symbol value W-Lang -> W-lang
;; substitutes the symbol and returns a W-Lang
(defn subst[id value W-lang]
(cond
(symbol? W-lang) (if (= id W-lang) value W-lang)
(seq? W-lang)
(condp = (first W-lang)
'num (list 'num (first (rest W-lang)))
'add (list 'add (subst id value (second W-lang))
(subst id value (third W-lang)))
'sub (list 'sub (subst id value (second W-lang))
(subst id value (third W-lang)))
'let
(if (= (second W-lang) id)
(list 'let (second W-lang)
(subst id value (third W-lang))
(forth W-lang))
(list 'let(second W-lang)
(subst id value (third W-lang))
(subst id value (forth W-lang))))
W-lang)))

You haven't provided enough information, but if Shriram provides a small-step semantics, you're probably looking for a proof by strong induction over the number of steps, and the proof technique you want is probably bisimulation.
As for eager versus lazy, which one is capable of more unnecessary computation? Which one puts an upper bound on additional computation?
I had a look at Shriram's latest draft, and he doesn't really hit semantics until chapter 23, and then it's only big-step semantics. I couldn't find where he might show you the techniques you need to answer the questions, unless maybe he has it in mind for you to write interpreters that count reductions.
If you want proofs, I don't think Shriram's book is the right place to learn proof technique for programming languages. Glynn Winskel's book on the formal semantics of programming languages is quite good, but it's fairly advanced. Unless you're mathematically sophisticated, it will be difficult without a teacher.
You're probably better off skipping the proof parts of Shriram's stuff, or trying a more user-friendly textbook like Benjamin Pierce's Types and Programming Languages.
Disclaimer: I have written a programming-languages textbook, but as it remains unavailable (I can't seem to finish chapter 8 and get a draft to a publisher), it probably shouldn't be viewed as competition. But one day it will be :-)

I have not read the book in answer to the second question I would say: no, eager evaluation does not always result in fewer reductions. With lazy evaluation you may very well avoid having to do some computation.

Related

Scheme Error "application: not a procedure"

I'm reading sicp and am writing a program to find the first 3 prime numbers from 1,000. I'm using an altered version of Fermat's method (However the algorithm is irrelevant in this case as I only need to understand the error message). The whole set of code is:
(define (fz-prime number count)
(if (< count 4)
(if (= (fz-fermat-loop number 1) 0)
(fz-prime (+ number 1) count)
((display number) (fz-prime (+ number 1) (+ count 1))))))
(define (fz-fermat-loop number count)
count
(if (> count 5)
1
(if (= (fz-fermat-test number (fz-random number)) 0)
0
(fz-fermat-loop number (+ count 1)))))
(define (fz-fermat-test number count)
(if (= (modulo count number) (modulo (fz-exp-wrapper count number) number))
1
0))
(define (fz-random number)
(random (- number 2)))
(define (fz-exp-wrapper base power)
(fz-exp base power 1))
(define (fz-exp base power result)
(if (<= power 0) result
(fz-exp base (- power 1) (* result base))))
(fz-prime 1000 1)
Now everytime I run the code, it shows the following error:
100910131019. . application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
The first 3 numbers are the first three prime numbers, but I don't get what the error message says.
The error message suggests that you're using Racket, but also that you've chosen a language level that disables useful error messages such as the one I get when I copy your program into buffer in the #lang racket language:
if: missing an "else" expression in: (if (< count 4) (if (= (fz-fermat-loop number 1) 0)
(fz-prime (+ number 1) count) ((display number) (fz-prime (+ number 1) (+ count 1)))))
Actually, I bet you're using Jens Axel Soegaard's excellent sicp language, which is entirely the right choice for working through sicp.... but is unfortunately missing some useful error messages.
Specifically, in the language you're using, an if can be missing an else branch, and if the test fails, it silently evaluates to the special # value.
Oh! But wait! You have another problem... you write
((display number) (fz-prime (+ number 1) (+ count 1)))
I bet you're thinking that if you just take two expressions such as (display number) and (fz-prime ...) and wrap them in parens, this means "do the first, then do the second." Actually, though, this means "the first expression evaluates to a function; call it with the arguments that result from evaluating the remaining expressions" and #void is exactly what (display ...) returns.
You might be looking for begin, here, like so:
(begin
(display number)
(fz-prime (+ number 1) (+ count 1)))

Lisp &rest parameters and recursive calls

I have the following Common Lisp Function:
(defun test(A &rest indexes)
(if (null (first indexes))
A
(test (nth (+ 1 (first indexes)) A) (rest indexes))
)
)
As far as I know &rest parameters are treated as a list in the function body but since
(rest indexes) also returns a list I'm stuck with nested Lists as parameters.
For example (test '("a" "b" "c" ("d" "e")) 3 1 6 7)
would cause indexes to be ((1 6 7)) at the second call.
Is there any way to pass my list without having this problem?
Basic style rule: don't use &rest arguments for list processing functions.
Why? Common Lisp implementations are allowed to only support up to the value of CALL-ARGUMENTS-LIMIT number of arguments. This number is 50 or larger, depending on implementation.
This means your function might in some implementation process lists not larger as fifty items.
Better: pass the list as a separate argument.
(defun test (A indexes)
...)
(test '("a" "b" "c" ("d" "e")) '(3 1 6 7))
Wrong solution: don't use apply, since it does not solve the problem of limited argument lists.
CLISP
[1]> call-arguments-limit
4096
[2]> (defun l1 (&rest l) l)
L1
[3]> (apply #'l1 (loop repeat 5000 collect 1))
*** - APPLY: too many arguments given to
#<FUNCTION L1 (&REST L)
(DECLARE (SYSTEM::IN-DEFUN L1))
(BLOCK L1 L)>
The following restarts are available:
ABORT :R1 Abort main loop
rest is a accessor function that is paired together with first to give you the first element and the rest of the list. rest is the same as cdr.
&rest is a lambda list keyword that slurps the remaining arguments in the variable name that follows it.
You are really looking for apply. Imagine I make a function that can take 0 or more numeric parameters and add them together:
(defun add (&rest numbers)
(apply #'+ numbers))
Apply can take more than two arguments. The first is the function to call and all but the last are extra arguments that are put in front of the last arguments element. You are guaranteed the implementation supports 50 arguments or upto the number of arguments a function can take in that particular implementation supports above 50.
(apply #'+ 1 2 '(3 4 5)) ; ==> 15
Now recursing by &rest and apply makes inefficient code so you should use higher order functions, loop macro, or make a helper:
;; higher order function
(defun fetch-indexes (a &rest indexes)
(mapcar (lambda (i) (nth i a)) indexes))
;; loop macro
(defun fetch-indexes (a &rest indexes)
(loop :for i :in indexes
:collect (nth i a)))
;; helper function
(defun fetch-indexes (a &rest indexes)
(labels ((helper (indexes)
(if (endp indexes)
'()
(cons (nth (first indexes) a)
(helper (rest indexes))))))
(helper indexes)))
;; test (works the same with all)
(fetch-indexes '(a b c d) 2 3 0 1)
; ==> (c d a b)
Using apply in recursion should be avoided, but I'll show how it's done.
(defun fetch-indexes (a &rest indexes)
(if (endp indexes)
'()
(cons (nth (first indexes) a)
(apply #'fetch-indexes a (rest indexes)))))
In your example you have nested lists. In order for that to work you would need to flatten it as well. I haven't done that so these supports one proper list of elements.
Another solution, albeit a bit more verbose, but less reliant on details of apply is to use a sub-function for the recursion, which just takes a list. The outer "main" entry point takes the &rest indices syntax, while the inner function takes it as a list:
(defun test (a &rest indices)
(labels ((internal-test (indices)
;; ... the recursion thing calling internal-test
))
(internal-test indices)))
In contrast to the (defun add (&rest args) ... ) example, you might still have some arguments before the rest, which in case of using apply would require you to append those to the variable arguments list.
Of course, as Rainer Joswig pointed out, you need to take care only to use this, when the number of variable args is small.

Scheme function [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am trying to interpret what this scheme function does:
(define (y s lis)
(cond
((null? lis) '() )
((equal? s (car lis)) lis)
(else (y s (cdr lis)))))
It runs but I am not exactly sure what it is doing or trying to do.
Does it need a list to sort or something? I am using DrRacket to run it. I have never seen scheme before
and any help would be greatly appreciated.
It's a search function, that given a value and a list looks for the value in the list. If it finds it, returns the part of the list starting at the point where the element was found. If the value isn't in the list, it returns an empty list. Let's see how this works, step by step:
; define a function called `y` that receives
; as parameters a value `s` and a list `lis`
(define (y s lis)
; we're going to test three possible conditions
(cond
; if the list is empty
((null? lis)
; then we didn't find the value, return the empty list
'())
; if the first element in the list equals the `s` value
((equal? s (car lis))
; then return the list up to this point
lis)
; otherwise
(else
; keep looking in the rest of the list, by recurring over it
(y s (cdr lis)))))
To see the function in action, let's test it with some values:
; call the function with a value that is present in the list
(y 3 '(1 2 3 4 5))
; see how the list is returned starting at the point where the value was found
=> '(3 4 5)
; call the function with a value that is not present in the list
(y 7 '(1 2 3 4 5))
; an empty list is returned
=> '()
To really, really understand how this works, you have to realize that in the last line of the function we're calling the function itself - it's the magic of recursion! Also, it'll help you to understand what each one of the primitive operations used is doing, click on each link to read the documentation, I'm simplifying and summarizing the key points:
define: give a name to a value (in particular, it can be a function)
cond: test for different conditions, execute some expressions depending on which condition was true
null?: test to see if a list is empty
equal?: compare two objects for equality
car: get the first element in a list
cdr: get the rest of the elements in a list
We can go on a mystic journey and treat this definition as it is, a definition. Cryptic? This means equational reasoning, i.e. reasoning through equations, i.e. definitions. Here's what I mean. You have
(define (y s lis)
(cond
((null? lis) '() )
((equal? s (car lis)) lis)
(else (y s (cdr lis)))))
We can re-write this as two equations,
y s lis = lis , if (null? lis) || (equal? s (car lis))
= y s (cdr lis) , otherwise
Here y s lis stands for "the result of Scheme call (y s lis)" and so on.
Clearly we have two cases. One is base case, another describes a reduction step. Re-writing again,
y s lis = y s (cdr lis) , if (not (null? lis)) && (not (equal? s (car lis)))
= lis , otherwise
This is practically in English now. So while lis is not null, and its car isn't s, we proceed along to its cdr, and so on and so forth until either we hit the list's end, or its car is s, and then we stop. So when we've found s, we return the list, otherwise the list is exhausted and the empty list is returned. This is otherwise known as member in Common Lisp. R5RS Scheme's member, as well as Racket's, returns #f when no x is found in the list.
Where is the equational reasoning here, you ask? In treating the RHS as the answer, and re-applying the same set of rules for each reduction step. For example:
y x [a,b,x,c,d,e] ; A
= y x [b,x,c,d,e] ; by 1st rule ; B
= y x [x,c,d,e] ; by 1st rule ; C
= [x,c,d,e] ; by 2nd rule ; D
When we get to apply the 2nd rule, we arrive at the end of the reduction chain, i.e. we get our answer. The result of the Scheme call corresponding to A will be the same as the Scheme call's corresponding to B, or C, or finally D:
(y x (cons a (cons b (cons x z)))) ==
(y x (cons b (cons x z))) ==
(y x (cons x z)) ==
(cons x z)
What's so mystic about it, you ask? Here probably not much; but usually what that means is that by assuming the meaning of a function, and by interpreting the RHS through it, we arrive at the meaning of the LHS; and if this is the same meaning, that is our proof for it. Induction is kind of magical. For more involved examples see How to recursively reverse a list using only basic operations?.
Incidentally structural recursion is also known as folding, so your function is really
y s lis = para (λ (xs x r) (if (equal? x s) xs (r))) '() lis
using one type of folding, paramorphism, with explicit laziness,
para f z lis = g lis
where
g xs = z , if (null? xs)
= f xs (car xs) (λ () (g (cdr xs))) , otherwise
Looks like homework.
Since you are using DrRacket you should add
(y 'e '(q w e r t y))
And hit Debug Q >| and step through it. A different way to write the same code is:
(define (y s lis)
(if (null? lis)
'()
(if (equal? s (car lis))
lis
(y s (cdr lis)))))
Or you can choose Intermediate student with lambda from the language menu in the bottom left and then press Step >|.
That language doesn't support all of Scheme but a small subset, including everything in this procedure. It's great to see how things are evaluated.
I think its a test to see if element s is found inside the list lst. I'm still learning Scheme (but I did get through The Little Schemer so let me try (this has likely been typed and submitted before I I finish this but I'll try anyways).
So define is creating a function called y that takes the arguments s and lst. The first line of this function is cond which goes though each list and tries to find some expression that evaluates to true. The first condition is the exit condition (always have an exit when you iterate) it checks to see if lis is null, if so it returns a quoted empty list (like the null of lists)
The next condition looks to see if the first element of lst (car takes the first element of a list) equals s if so then it returns the rest f the list (this means it found the element).
The last condition is else which is alway true and it calls the function y with the same s and the list minus the first element (cdr returns a sublist of the list minus the first element). Hope this helps (and I hope I was right)
Here is an example of calling this function:
(y 'b (list 'a 'b 'c))
And this returns
('b 'c)

Automatic TCO in Clojure

Is there a way to define a function in Clojure that is automatically tail-call-optimized?
e.g.
(defrecur fact [x]
(if (= x 1)
1
(* x (fact (dec x)))))
would be translated internally to something like:
(defn fact [x]
(loop [n x f 1]
(if (= n 1)
f
(recur (dec n) (* f n)))))
Can you tell me if something like this already exists?
The short answer is "No".
The slightly longer answer is that Clojure is deliberately designed to require explicit indication where Tail Call Optimisation is desired, because the JVM doesn't support it natively.
Incidentally, you can use recur without loop, so there's no more typing required, e.g.:
(defn func [x]
(if (= x 1000000)
x
(recur (inc x))))
Update, April 29:
Chris Frisz has been working on a Clojure TCO research project with Dan Friedman, and whilst nobody is claiming it to be 'the answer' at this time, the project is both interesting and promising. Chris recently gave an informal talk about this project, and he's posted it on his blog.
To the best of my knowledge, there is no automatic way to generate tail recursion in Clojure.
There are examples of functions that use recursion without using loop .. recur that work without overflowing the stack. That is because those functions have been carefully written to use lazy sequences.
Here is an example of replacing flatten with a hand-written function. This example came from http://yyhh.org/blog/2011/05/my-solutions-first-50-problems-4clojure-com
(fn flt [coll]
(let [l (first coll) r (next coll)]
(concat
(if (sequential? l)
(flt l)
[l])
(when (sequential? r)
(flt r)))))
One of the guiding principals behind this decision was to make the special part look special. that way it is obvious where tail calls are in use and where they are not. This was a deliberate design decision on which some people have strong opinions though in practice I rarely see recur used in idomatic Clojure anyway so In practice it's not a common problem.

Tail-recursive?

I'm writing a function that takes a list and returns the sum of the squares of all items in the list. Called on (1 2 3) it should return 14: (12 + 22 + 32).
I have this sqsum function:
(define (sqsum lis)
(if (null? lis)
0
(+ (* (car lis) (car lis)) (sqsum (cdr lis)))
)
)
Is this tail recursive? I think it is recursive but not tail recursive.
This is part of my homework and I'm not looking for solution: I just want to know if this is tail recursive or not. If not then I need to read more and find new solutions.
To be tail recursive the recursion has to happen at the very last function, i.e. you cannot do anything with the results from the recursiv call. Here you pass it to +, which makes it non-tail-recursive. The compiler could optimize this away though, and it's pretty easy to do yourself too.
No, it is not tail recursive.
The general approach to making a non-tail recursive function tail-recursive is to include an accumulator, which is an extra argument that carries the current evaluation of the procedure through your recursive calls.
Incidentally, this is also where "helper" functions are very useful. The general practice is to define your function so that it does not take the accumulator, define a helper function within it that does take the accumulator, and then have the main function do little besides call the helper function. You'll see what I mean in a sec.
In your case (if I'm remembering my Scheme properly :p):
(define (sqsum lis)
(define (sqsum-h lis acc)
(if (null? lis)
acc
(sqsum-h (cdr lis) (+ acc (* (car lis) (car lis))))
)
)
(sqsum-h lis 0)
)
This is tail-recursive because the last thing any recursive call does is immediately return the result of another function without modifying it.