How to find "not a procedure" error - scheme

(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

Related

What is Classifier and Transformer in MIT Scheme?

In the following scheme code, accumulate does right-fold. When I tried to run using mit scheme. I ran into following error:
Transformer may not be used as an expression: #[classifier-item 13]
Classifier may not be used as an expression: #[classifier-item 12]
I google searched but didn't find useful information. Is it related a macro?
; This function is copied from SICP chapter 2
(define (accumulate op initial sequence)
(if (null? sequence)
initial
(op (car sequence)
(accumulate op initial (cdr sequence)))))
; works as expected
(accumulate
(lambda (x y) (or x y)) ; replace or with and also works
#f
'(#t #f #t #f #f)
))
; does not work
; error: Classifier may not be used as an expression: #[classifier-item 12]
(accumulate
or
#f
'(#t #f #t #f #f)
))
; does not work
; error: Transformer may not be used as an expression: #[classifier-item 13]
(accumulate
and
#f
'(#t #f #t #f #f)
))
Macros can be passed around in some languages, but not in Scheme and Common Lisp. The reason is that macros should be able to be expanded ahead of time. eg.
(define (cmp a b)
(cond ((< a b) -1)
((> a b) 1)
(else 0)))
Now a compiling Scheme will expand each node recursively replacing it with the expansion until it is no change:
(define (cmp a b)
(if (< a b)
(begin -1)
(cond ((> a b) 1)
(else 0))))
(define (cmp a b)
(if (< a b)
-1
(cond ((> a b) 1)
(else 0))))
(define (cmp a b)
(if (< a b)
-1
(if (> a b)
(begin 1)
(cond (else 0)))))
(define (cmp a b)
(if (< a b)
-1
(if (> a b)
1
(cond (else 0)))))
; end result
(define (cmp a b)
(if (< a b)
-1
(if (> a b)
1
0)))
From this point of cond doesn't need to exist in the underlying language at all since you'll never ever use it, but how would this have to be implemented to work:
(define (test syntax a b)
(syntax a b))
(test or #f #t)
For this to work the underlying language needs to know what or is even after expansion since syntax would need to be bound to or and then the transformation can happen. But when the code runs the macro expansion has already happened and in most implementations you would see something indicating that or is an unbound variable. It seems like MIT Scheme has added error checking for top level syntax syntax that will fire an error if you don't override it. Eg. if you add this you will not see any problems whatsoever:
(define (or a b) (if a a b))
(define (and a b) (if a b #f))
Now after those lines any reference to and and or are not the syntax, but these procedures. There are no reserved words in Scheme so if you do something crazy, like defining define you just cannot use it for the rest f that scope:
(define define display) ; defiens define as a top level variable
(define define) ; prints the representation of the function display
(define test 10) ; fail since test is an undefined variable so it cannot be displayed.
I created a interpreted lisp with macros that actually could be passed, but it isn't very useful and the chances of optimization is greatly reduced.
Yes it's related to the macros / special forms like and and or.
You can make it work simply by wrapping them as lambdas, (accumulate (lambda (a b) (or a b)) ...) -- the results will be correct but of course there won't be any short-circuiting then. The op is a function and functions receive their arguments already evaluated.
Either hide the arguments behind lambdas ((lambda () ...)) and evaluate them manually as needed, or define specific versions each for each macro op, like
(define (accumulate-or initial sequence)
(if (null? sequence)
initial
(or (car sequence)
(accumulate-or initial (cdr sequence)))))
Here sequence will still be evaluated in full before the call to accumulate-or, but at least the accumulate-or won't be working through it even after the result is already known.
If sequence contains some results of heavy computations which you want to avoid in case they aren't needed, look into using "lazy sequences" for that.

List of procedures in 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

Maximum recursion error [duplicate]

I'm reading The Little Schemer. And thanks to my broken English, I was confused by this paragraph:
(cond ... ) also has the property of not considering all of its
arguments. Because of this property, however, neither (and ... ) nor
(or ... ) can be defined as functions in terms of (cond ... ), though
both (and ... ) and (or ... ) can be expressed as abbreviations of
(cond ... )-expressions:
(and a b) = (cond (a b) (else #f)
and
(or a b) = (cond (a #t) (else (b))
If I understand it correctly, it says (and ...) and (or ...) can be replaced by a (cond ...) expression, but cannot be defined as a function that contains (cond ...). Why is it so? Does it have anything to do with the variant arguments? Thanks.
p.s. I did some searching but only found that (cond ...) ignores the expressions when one of its conditions evaluate to #f.
Imagine you wrote if as a function/procedure rather than a user defined macro/syntax:
;; makes if in terms of cond
(define (my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))
;; example that works
(define (atom? x)
(my-if (not (pair? x))
#t
#f))
;; example that won't work
;; peano arithemtic
(define (add a b)
(my-if (zero? a)
b
(add (- a 1) (+ b 1))))
The problem with my-if is that as a procedure every argument gets evaluated before the procedure body gets executed. thus in atom? the parts (not (pair? x)), #t and #f were evaluated before the body of my-if gets executed.
For the last example means (add (- a 1) (+ b 1)) gets evaluated regardless of what a is, even when a is zero, so the procedure will never end.
You can make your own if with syntax:
(define-syntax my-if
(syntax-rules ()
((my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))))
Now, how you read this is the first part is a template where the predicate consequent and alternative represent unevaluated expressions. It's replaced with the other just reusing the expressions so that:
(my-if (check-something) (display 10) (display 20))
would be replaced with this:
(cond ((check-something) (display 10))
(else (display 20)))
With the procedure version of my-if both 10 and 20 would have been printed. This is how and and or is implemented as well.
You cannot define cond or and or or or if as functions because functions evaluate all their arguments. (You could define some of them as macros).
Read also the famous SICP and Lisp In Small Pieces (original in French).

Scheme - logical operator procedures

I know Scheme and other Lisp dialects include logical operators such as 'and' and 'or', but, since I am currently learning Scheme, I am trying to program my own logical operators. So far my attempts at 'or' have been successful (at least so far as my testing has shown me). My logical or operator is the following:
(define (logical-or a b)
(if a true b))
I am trying to program a logical operator for 'and' that also returns a boolean, but I keep getting stuck. I have tried any number of combinations, but I will just list the following one, which doesn't return a boolean:
(define (logical-and a b)
(if a b false))
Any hints or help welcome.
As Uselpa's answer and the leppie's comments mentioned, the operators and and or don't return #t but the value that was not #f that decided the outcome of the form. Thus
(and 'these 'are 'all 'true 'values) ; ==> values
(or 'these 'are 'all 'true 'values) ; ==> these
The logical operators and and or are short circuiting so they are not procedures. Imagine this procedure:
(define (first-true-value lst)
(and (pair? lst)
(or (car lst)
(first-true-value (cdr lst)))))
(first-true-value '()) ; ==> #f
(first-true-value '(#f #f)) ; ==> #f
(first-true-value '(#f #f hello)) ; ==> hello
If you replace and and or with your versions the procedure will never stop evaluating the recursion.
We know we can rewrite and with if. (and) is #t, (and a) is a and (and a b ...) is (if a (and b ...) #f). We could do this with th easiest Scheme macros, syntax-rules:
(define-syntax logical-and
(syntax-rules ()
((logical-and) #t)
((logical-and a) a)
((logical-and a b ...)
(if a (logical-and b ...) #f))))
We can also do or the same way. (or) is #f and (or a b ..) is (if a a (or b ...)):
(define-syntax logical-or
(syntax-rules ()
((logical-or) #f)
((logical-or a b ...) ; NB: zero elements match "b ..."
(if a a (logical-or b ...)))))
There is a problem with this one since it uses a twice.. Try (logical-or (display "hello")). It will evaluate (display "hello") and thus display the text twice. To fix this we need to wrap the value in a let:
(define-syntax logical-or
(syntax-rules ()
((logical-or) #f)
((logical-or a b ...)
(let ((tmp a))
(if tmp
tmp
(logical-or b ...))))))
If you try the same it will only display "hello" once. Lets try writing my initial procedure with the new macros:
(define (first-true-value lst)
(logical-and (pair? lst)
(logical-or (car lst)
(first-true-value (cdr lst)))))
;; and we test them:
(first-true-value '()) ; ==> #f
(first-true-value '(#f #f)) ; ==> #f
(first-true-value '(#f #f hello)) ; ==> hello
Your logical-or does not always return booleans either:
> (logical-or #f 2)
2
As #leppie says, anything not false (#f) is true in Scheme; try experimenting a little with the build-in or function:
> (or 1 2)
1
> (or #f 2)
2
> (or #t 2)
#t
> (or 1 #f)
1
> (or #f #t)
#t
so the definition in Scheme would be:
(define (my-or a b)
(if a a b))
Likewise, for and:
> (and 1 #t)
#t
> (and 1 #f)
#f
> (and 1 2)
2
> (and #f 2)
#f
> (and #t 2)
2
so the definition is
(define (my-and a b)
(if a b a))
If you want to only return booleans, then you'd code
(define (logical-or a b)
(cond
(a #t)
(b #t)
(else #f)))
(define (logical-and a b)
(if a
(if b
#t
#f)
#f))
This works for 2 values, but since the build-in and and or operators allow any number of parameters (even 0) and only evaluate their parameters if necessary the real definitions are a little more complicated.

"cond","and" and "or" in Scheme

I'm reading The Little Schemer. And thanks to my broken English, I was confused by this paragraph:
(cond ... ) also has the property of not considering all of its
arguments. Because of this property, however, neither (and ... ) nor
(or ... ) can be defined as functions in terms of (cond ... ), though
both (and ... ) and (or ... ) can be expressed as abbreviations of
(cond ... )-expressions:
(and a b) = (cond (a b) (else #f)
and
(or a b) = (cond (a #t) (else (b))
If I understand it correctly, it says (and ...) and (or ...) can be replaced by a (cond ...) expression, but cannot be defined as a function that contains (cond ...). Why is it so? Does it have anything to do with the variant arguments? Thanks.
p.s. I did some searching but only found that (cond ...) ignores the expressions when one of its conditions evaluate to #f.
Imagine you wrote if as a function/procedure rather than a user defined macro/syntax:
;; makes if in terms of cond
(define (my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))
;; example that works
(define (atom? x)
(my-if (not (pair? x))
#t
#f))
;; example that won't work
;; peano arithemtic
(define (add a b)
(my-if (zero? a)
b
(add (- a 1) (+ b 1))))
The problem with my-if is that as a procedure every argument gets evaluated before the procedure body gets executed. thus in atom? the parts (not (pair? x)), #t and #f were evaluated before the body of my-if gets executed.
For the last example means (add (- a 1) (+ b 1)) gets evaluated regardless of what a is, even when a is zero, so the procedure will never end.
You can make your own if with syntax:
(define-syntax my-if
(syntax-rules ()
((my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))))
Now, how you read this is the first part is a template where the predicate consequent and alternative represent unevaluated expressions. It's replaced with the other just reusing the expressions so that:
(my-if (check-something) (display 10) (display 20))
would be replaced with this:
(cond ((check-something) (display 10))
(else (display 20)))
With the procedure version of my-if both 10 and 20 would have been printed. This is how and and or is implemented as well.
You cannot define cond or and or or or if as functions because functions evaluate all their arguments. (You could define some of them as macros).
Read also the famous SICP and Lisp In Small Pieces (original in French).

Resources