When I try to call the subtotal function, I get the error "application: not a procedure; expected a procedure that can be applied to arguments given: 1
(define (subtotal id-list)
(if (null? id-list)
0
(+ (getprice(car id-list)) (subtotal (cdr id-list)))))
(subtotal (list (1 2 3)))
The getprice function works fine, so I don't know why it thinks subtotal isn't a procedure.
Related
I'm trying to take in user input and add it to a list but I have not been able to get it working. I'm still new to scheme and have been browsing around to try to figure it out but I haven't had any luck.
(display "Continue to enter numbers until satisfied then enter e to end")
(newline)
(define (intlist number)
(define number(read-line))
(cond (number? number)
(cons lst (number))
(else
(display lst)
done')))
this is what I have so far. Any help or direction to where I can learn a bit more is appreciated.
Your solution is almost correct, but it doesn't work, because:
Variable lst doesn't exist and with this expression (number), you are calling some undefined function number.
done' is badly written 'done.
Function cons expects element as first argument and other element or list as second argument.
See these examples:
> (cons 1 2)
'(1 . 2)
> (cons 1 '())
'(1)
> (cons 1 (cons 2 (cons 3 '())))
'(1 2 3)
Last example is important here- your function will be recursive and it will return a cons cell in each step. If I will follow your solution, this can be enough:
(define (list-from-user)
(let ((number (read)))
(if (number? number)
(cons number (list-from-user))
'())))
(Note that I used read instead of read-line, because read-line returns string, and let instead of define.)
If you really want to wait for e, you must decide, what happens if user enters something that isn't number and isn't e- maybe just ignore it?
(define (list-from-user)
(let ((user-input (read)))
(cond ((number? user-input) (cons user-input (list-from-user)))
((eq? user-input 'e) '())
(else (list-from-user)))))
Then just add some wrapping function with output:
(define (my-fn)
(begin (display "Continue to enter numbers until satisfied then enter e to end")
(newline)
(list-from-user)))
and call it
> (my-fn)
Note that my function returns list with numbers, instead of some useless 'done, so I can use that function in other functions.
(define (sum-of-list)
(let ((lst (my-fn)))
(format "Sum of given list is ~a." (apply + lst))))
> (sum-of-list)
Reading SICP I am now at exercise 2.04, which is a procedural representation of cons, car and cdr, given in the book as follows:
(define (cons x y)
(lambda (m)
(m x y)))
(define (car z)
(z
(lambda (p q)
(p))))
Note, that for running the code I use racket with the following preamble in my code:
#lang racket
(define (Mb-to-B n) (* n 1024 1024))
(define MAX-BYTES (Mb-to-B 64))
(custodian-limit-memory (current-custodian) MAX-BYTES)
I also tried #lang scheme to no avail.
Here is what I understand:
About cons
cons returns a function.
This function which will apply another function given as parameter to the two parameters x and y of cons.
This means by calling cons we retain the possibility to apply a function to the two parameters and are able to treat them as some unit.
About car
car now uses the fact, that we can apply a function to the unit of 2 values given to cons, by giving a function as a parameter to the function, which we get returned from cons.
It supplies that function with a lambda expression, which always returns the first of two given values.
Usage
At first I tried the following:
(car (cons 1 2))
(car (cons 2 3))
(car (cons (cons 1 1) (cons 2 2)))
(car (car (cons (cons 1 1) (cons 2 2))))
However, that leads to errors:
:racket -l errortrace -t exercise-2.04-procedural-representation-of-pairs.rkt
application: not a procedure;
expected a procedure that can be applied to arguments
given: 1
arguments...: [none]
errortrace...:
/home/xiaolong/development/LISP/Racket/SICP/exercise-2.04-procedural-representation-of-pairs.rkt:24:6: (p)
/home/xiaolong/development/LISP/Racket/SICP/exercise-2.04-procedural-representation-of-pairs.rkt:33:0: (car (cons 1 2))
context...:
/home/xiaolong/development/LISP/Racket/SICP/exercise-2.04-procedural-representation-of-pairs.rkt: [running body]
I could not understand what was wrong with my code, so I looked up some usage examples in other people's solutions. One is on http://community.schemewiki.org/?sicp-ex-2.4:
(define x (cons 3 4))
(car x)
But to my surprise, it doesn't work! The solution in the wiki seems to be wrong. I get the following error:
application: not a procedure;
expected a procedure that can be applied to arguments
given: 3
arguments...: [none]
errortrace...:
/home/xiaolong/development/LISP/Racket/SICP/exercise-2.04-procedural-representation-of-pairs.rkt:24:6: (p)
/home/xiaolong/development/LISP/Racket/SICP/exercise-2.04-procedural-representation-of-pairs.rkt:42:0: (car x)
context...:
/home/xiaolong/development/LISP/Racket/SICP/exercise-2.04-procedural-representation-of-pairs.rkt: [running body]
What am I doing wrong here?
You have an error in your code. Instead of:
(define (car z)
(z
(lambda (p q)
(p))))
you should have written (see the book):
(define (car z)
(z
(lambda (p q)
p)))
Note that in the last row p is written without parentheses.
The message: application: not a procedure means that p is not a procedure (it is actually a number), while with the notation (p) you are calling it as a parameterless procedure.
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
I understand that for-each in scheme doesn't create a new list but in my output, I expected:
4
9
16
done.
I'm just getting "done".
What's going on here?
(define (for-each proc list)
(cond ((null? list) "done")
(else
(proc (car list))
(for-each proc (cdr list)))))
(define square (lambda(x)(* x x)))
(square 5)
(for-each square (list 2 3 4))
In your code, the line (proc (car list)) gets executed for the effect, but its result will be ignored. If you just want to print the results of the square function, try this:
(for-each (lambda (x) (display (square x)) (newline)) ; applies function on each element
'(2 3 4))
=> 4
9
16
done
If you want to obtain the results of applying the procedure on each element of the input list, you have to use map, not for-each:
(map square '(2 3 4))
=> '(4 9 16)
for-each iterates over an input list and performs an operation over each element, but only for its effect (say, printing each element). It doesn't accumulate the result in an output list, it doesn't even print them unless explicitly stated - on the other hand, map iterates over an input list, performs an operation over each element and accumulates the result in an output list.
(define wadd (lambda (i L)
(if (null? L) 0
(+ i (car L)))
(set! i (+ i (car L)))
(set! L (cdr L))))
(wadd 9 '(1 2 3))
This returns nothing. I expect it to do (3 + (2 + (9 + 1)), which should equate to 15. Am I using set! the wrong way? Can I not call set! within an if condition?
I infer from your code that you intended to somehow traverse the list, but there's nothing in the wadd procedure that iterates over the list - no recursive call, no looping instruction, nothing: just a misused conditional and a couple of set!s that only get executed once. I won't try to fix the procedure in the question, is beyond repair - I'd rather show you the correct way to solve the problem. You want something along these lines:
(define wadd
(lambda (i L)
(let loop ((L L)
(acc i))
(if (null? L)
acc
(loop (cdr L) (+ (car L) acc))))))
When executed, the previous procedure will evaluate this expression: (wadd 9 '(1 2 3)) like this:
(+ 3 (+ 2 (+ 1 9))). Notice that, as pointed by #Maxwell, the above operation can be expressed more concisely using foldl:
(define wadd
(lambda (i L)
(foldl + i L)))
As a general rule, in Scheme you won't use assignments (the set! instruction) as frequently as you would in an imperative, C-like language - a functional-programming style is preferred, which relies heavily on recursion and operations that don't mutate state.
I think that if you fix your indentation, your problems will become more obvious.
The function set! returns <#void> (or something of similar nothingness). Your lambda wadd does the following things:
Check if L is null, and either evaluate to 0 or i + (car L), and then throw away the result.
Modify i and evaluate to nothing
Modify L and return nothing
If you put multiple statements in a lambda, they are wrapped in a begin statement explicitly:
(lambda () 1 2 3) => (lambda () (begin 1 2 3))
In a begin statement of multiple expressions in a sequence, the entire begin evaluates to the last statement's result:
(begin 1 2 3) => 3