List of procedures in scheme - scheme

In scheme, I would like to be able to have a list of procedures that I could use on lists of numbers via map.
For example, say I have the procedure
(define (overten? x) (> x 10))
Why does this work when called with (foo '(1 2 11 12) '()) ?
(define (foo lst proc)
(map overten? lst)
)
But this gives an error called with (foo '(1 2 11 12) '(overten?)) ?
(define (foo lst proc)
(map (car proc) lst)
)
With the error being
The object overten? is not applicable.

Because '(overten?) is a list containing a symbol. Only if you evaluated overten? you would get back the procedure. You need to write (list overten?) so that arguments to list are evaluated (unlike quote).
See Why does Scheme have both list and quote?

'(overten?) is not a list with procedures. It's a list with a symbol that has nothing to do with procedures bound to that name in any scope
You need to think evaluation:
overten?
; ==> {procedure overten? blabla}
; (a implementation dependent representation of a procedure object
'overten
; ==> overten?
; (just a symbol with name "overten?", nothing to do with the procedure object above)
(list overten? 'overten?)
; ==> ({procedure overten? blabla} overten)
a list where the first element is a procedure and the second a symbol with name "overten?"
(define another-name-quoted 'overten?)
; ==> undefined
; 'overten? evaluated to a symbol, them bound to another-name-quoted
(define another-name overten?)
; ==> undefined
; overten? evaluated to a procedure, then bound to another-name
The procedure overten? is not more overten? than it is another-name.
Here is an example where we use lists of procedures. It's an implementation of the compose procedure:
(define (my-compose . procs)
(let* ((rprocs (if (zero? (length procs))
(list values)
(reverse procs)))
(proc-init (car rprocs))
(proc-list (cdr rprocs)))
(lambda args
(foldl (lambda (proc acc)
(proc acc))
(apply proc-init args)
proc-list))))
(define sum-square-sub1-sqrt
(my-compose inexact->exact
floor
sqrt
sub1
(lambda (x) (* x x))
+))
(sum-square-sub1-sqrt 1 2 3) ; 5

Related

Unusual Scheme `let` binding, what is `f`?

In "The Scheme Programming Language 4th Edition" section 3.3 Continuations the following example is given:
(define product
(lambda (ls)
(call/cc
(lambda (break)
(let f ([ls ls])
(cond
[(null? ls) 1]
[(= (car ls) 0) (break 0)]
[else (* (car ls) (f (cdr ls)))]))))))
I can confirm it works in chezscheme as written:
> (product '(1 2 3 4 5))
120
What is 'f' in the above let? Why is the given ls being assigned to itself? It doesn't seem to match what I understand about (let ...) as described in 4.4 local binding:
syntax: (let ((var expr) ...) body1 body2 ...)
If 'f' is being defined here I would expect it inside parenthesis/square brackets:
(let ([f some-value]) ...)
This is 'named let', and it's a syntactic convenience.
(let f ([x y] ...)
...
(f ...)
...)
is more-or-less equivalent to
(letrec ([f (λ (x ...)
...
(f ...)
...)])
(f y ...))
or, in suitable contexts, to a local define followed by a call:
(define (outer ...)
(let inner ([x y] ...)
...
(inner ...)
...))
is more-or-less equivalent to
(define (outer ...)
(define (inner x ...)
...
(inner ...)
...)
(inner y ...))
The nice thing about named let is that it puts the definition and the initial call of the local function in the same place.
Cavemen like me who use CL sometimes use macros like binding, below, to implement this (note this is not production code: all its error messages are obscure jokes):
(defmacro binding (name/bindings &body bindings/decls/forms)
;; let / named let
(typecase name/bindings
(list
`(let ,name/bindings ,#bindings/decls/forms))
(symbol
(unless (not (null bindings/decls/forms))
(error "a syntax"))
(destructuring-bind (bindings . decls/forms) bindings/decls/forms
(unless (listp bindings)
(error "another syntax"))
(unless (listp decls/forms)
(error "yet another syntax"))
(multiple-value-bind (args inits)
(loop for binding in bindings
do (unless (and (listp binding)
(= (length binding) 2)
(symbolp (first binding)))
(error "a more subtle syntax"))
collect (first binding) into args
collect (second binding) into inits
finally (return (values args inits)))
`(labels ((,name/bindings ,args
,#decls/forms))
(,name/bindings ,#inits)))))
(t
(error "yet a different syntax"))))
f is bound to a procedure that has the body of let as a body and ls as a parameter.
http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_sec_11.16
Think of this procedure:
(define (sum lst)
(define (helper lst acc)
(if (null? lst)
acc
(helper (cdr lst)
(+ (car lst) acc))))
(helper lst 0))
(sum '(1 2 3)) ; ==> 6
We can use named let instead of defining a local procedure and then use it like this:
(define (sum lst-arg)
(let helper ((lst lst-arg) (acc 0))
(if (null? lst)
acc
(helper (cdr lst)
(+ (car lst) acc)))))
Those are the exact same code with the exception of some duplicate naming situations. lst-arg can have the same name lst and it is never the same as lst inside the let.
Named let is easy to grasp. call/ccusually takes some maturing. I didn't get call/cc before I started creating my own implementations.

How do two procedures (or macros) share one local environment in Scheme?

so my task is to create two procedures or macros (not specified in the assignment) in Scheme. Both of those procedures are supposed to modify a local environment that they share. There is an important condition that the binding is accessible only from those two procedures, so the procedures do not modify a global definition.
The task of procedure 1 is to set a local variable to a new value.
The task of procedure 2 is to add a number to the value that was set by procedure 1.
(proc1 5) => 5
(proc2 6) => 11
Here's what I have so far:
(define proc1
(lambda (val)
(let ((x 0))
(begin
(set! x val)
x))))
I don't know how to get proc2 to have access to the local environment of proc1. My guess is to use either call/cc or a coroutine but I don't know how, can you please help me?
Thank you!
How can two procedures share free variables that are not also global:
(let ((v 0))
(define (inc) ...)
(define (dec) ...)
;; both of them are available from here
)
Now if you want the two procedure in the global environment you could set!:
(define inc #f)
(define dec #f)
(let ((v 0))
(set! inc (lambda () (set! v (+ v 1))))
(set! inc (lambda () (set! v (- v 1)))))
But there is a third option. It is how object oriented programming works:
#!r6rs
(import (rnrs))
(define (make-peano v)
(define (inc) (set! v (+ v 1)) v)
(define (dec) (set! v (- v 1)) v)
(define (message-handler msg)
(case msg
((inc) inc)
((dec) dec)
(else (raise (condition (make-error) (make-message-condition "Error: unknown message"))))))
message-handler)
(define (peano-inc peano)
((peano 'inc)))
(define (peano-dec peano)
((peano 'dec)))
(define peano (make-peano 5))
(peano-inc peano)
; ==> 6
(peano-inc peano)
; ==> 7
(peano-inc peano)
; ==> 8
(peano-dec peano)
; ==> 7

How to find "not a procedure" error

(define (comp f g)
(lambda (x)(f (g x))))
(define (complement f) (cond ((equal? (comp f (lambda (g) g)) #t) #f)
((equal? (comp f (lambda (g) g)) #f) #t)))
((complement odd?)2)
It keeps saying that ((complement odd?)2) is not a procedure. I'm not sure how to fix it.
When you run this code you'll see that ((complement odd?) 2) is red in the definitions and you get the following error:
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
So that would mean (complement odd?) doesn't return a procedure but the value #<void>. Lets try that:
(complement odd?)
; ==> nothing (aka #<void>)
If you really want to see it use it somewhere:
(list (complement odd?))
; ==> (#<void>) now you see it
That means you are not handling all your possible checks in the cond in complement and I see why.. Have you tried comp?
(comp f (lambda (g) g)) ; ==> #<procedure>
Surely enough the use of comp becomes a procedure. Not strange since the body has one lambda form that indicates the return would be a procedure. It will never be #t or #f When you don't have an else (default) term for when neither of your predicates became true cond returns an implementation specific defauls value. In Racket this is #<void> which is supressed by the REPL, but in other implementations it can be banana or whatever the implementers want it to be so you should always have a else clause. If you don't think you need it then do (else (error "should never happen")) and you're good to go. (try it)
The consequences in your cond are #t and #f. That means that if your code sould have worked you would have got this error message instead:
application: not a procedure;
expected a procedure that can be applied to arguments
given: #t
For each place your return smething that is not a procedure that would be an error since you are using the result as a procedure. You need to change your implementation such that it returns a procedure always.
So, this is the answer to how to find “not a procedure” error. It's not the answer to how to fix your procedure but since this is the simplest procedure in the world I'll add it. You have a procedure comp that takes two procedures and return the composition of the two. eg. if you want add2 you can (define add2 (comp add1 add1)). The complement must be that the false value #f turns #t while all the true values turn #f. not does this so the composition of not and odd? would become the procedure that works the same as even?:
(define (complement f)
(comp not f)) ; comp returns a procedure always
(define my-even? (complement odd?))
(my-even? 2) ; ==> #t
Since we don't mutate anything you can use substitution method to check what this does:
(my-even? 2) ; ==>
((comp not odd?) 2) ; ==>
(((lambda (x) (not (odd? x))) 2) ; ==>
(not (odd? 2)) ; ==>
(not #f) ; ==>
#t

General memoization in Scheme

i have been assigned homework to make a general memoization procedure in scheme, so far it works on procedures that take one argument, but fail on what it seems to be the last argument when provided with more than 1. It also fails to memoize procedures that take no arguments.
Any help would be greatly appreciated.
(define mem
(lambda (mem-it func)
(let ((table (make-table) )(func-store func))
(cond
((equal? mem-it 'memoize)
(lambda args
(if (null? args)
func
(let ((prev (lookup args table)))
(or prev
(let ((result (apply func args)))
(insert! args result table)
result))))))
((equal? mem-it 'unmemoize)
(func-store))
(else (display "No Such command"))))))
This is what i have so far
(define (test-proc . args)
(display "computing test-proc of ")
(display args)
(newline)
(if (null? args)
0
(+ (expt (- 42 (car args)) 2)
(apply test-proc (cdr args)))))
And here is the test procedure provided
The error occurs when i try to run the following test
(set! test-proc (mem 'memoize test-proc))
(test-proc 40 41 42 43 44)
Here are the other procedures used
(define (make-table)
(list '*table*))
(define (lookup key table)
(let ((record (assoc key (cdr table))))
(and record (cdr record))))
(define (insert! key value table)
(let ((record (assoc key (cdr table))))
(if record
(set-cdr! record value)
(set-cdr! table
(cons (cons key value) (cdr table))))))
Your memoizarion procedure has a feature where it returns the implementation procedure when no arguments are passed:
((mem 'memoize test-proc)) ; ==> test-proc
The base case of your test procedure will never hit because of this feature thus for (test-proc 1) you can substitute it with the expression (+ 1681 test-proc) which will signal an error since test-proc is not a number.
It's better to use unique magic values:
(define +GET-PROC+ (list "get-proc"))
(test-proc +GET-PROC+) ; ==> original-test-proc
Since we are making a list it's is eq? that data only. In R6RS you can refrain from exporting so that code that uses memoization doesn't really have access to mess with it. All lists that look like it eg ("get-proc") won't be eq? so it can be used as an argument without getting the original procedure.
Since you are not using a standard hash procedure from (rnrs hashtables) or SRFI-69 it's not possible for me to check it but since you are using a list as key your hashtable must use equal? as test. This is often a source of frustration when using hash tables in most lisps.

Scheme Argument Checker Error-handling

I'm fairly new to Scheme programming and was wondering how I can add some error checkers in this program. I would like it to check if the user types in more than one parameter and if the user does I would like it to say that its an error.
(define (thirds lst)
(cond ((or (null? lst) (null? (cdr lst))) lst)
((null? (cddr lst)) (list (car lst)))
(else (cons (car lst)
(thirds (cdddr lst))))))
The Scheme interpreter should check this automatically. You only need to do your own checking of the number of arguments if you define the procedure to take spread arguments, i.e.
(define (thirds . args)
...)
You would normally only do this if the procedure takes a variable number of arguments. For procedures with static arguments, just list them in the definition and let the interpreter do the checking for you.
If you really want to detect this yourself, you can do:
(define (thirds . args)
(if (= (length args) 1)
(let ((lst (car args)))
(cond ... ; all the rest of your code
))
(display "Oh that's an error")))
So, using your definition of thirds in #!racket (the language) and trying to use it like this:
(thirds '(a b c) '(d e f))
thirds: arity mismatch;
the expected number of arguments does not match the given number
expected: 1
given: 2
arguments...:
'(a b c)
'(d e f)
context...:
/usr/share/racket/collects/racket/private/misc.rkt:87:7
As you can see all computation stops since I have given a one argument procedure two arguments. It's a contract violation and it throws an exception.
It's perfectly possible to make handlers:
(with-handlers ([exn:fail:contract?
(λ (e) (displayln "got a contract error"))])
(thirds '(1 2 3) '(4 5 6)))
; prints "got a contract error"

Resources