I know we have a function to count number of items in a list, however in this procedure I am can not use this function. So how can I count number of elements in a list.
(define (last_element l count )
(+ count 2)
(if (null? cdr l)
done
(last_element (cdr l) count)))
(last_element (list 1 2 3 4 5) 0)
(define (mylength2 l count)
(if (null? l) count
(mylength2 (cdr l) (+ count 1))))
Related
I started learning Racket today so please be patient :)
What I'm trying is to sum numbers (ages in this case) stored inside a struct.
So I have this:
(define-struct rec (name age)) ; defining the struct of records
(define r1 (make-rec "Joe" 23))
(define r2 (make-rec "Sue" 13))
(define r3 (make-rec "Ann" 44))
(define reclist (list r1 r2 r3)) ; defining a list of records
I found out how to sum integers, this seems a good way to do that:
(define liste (list 1 2 3 4 5))
(define (sum-list l)
(cond
[(empty? l) 0]
[(+ (first l) (sum-list (rest l)))]))
Now, I have been trying to somehow combine these functions in a way that I can grab the age inside each record and then sum them all but to no avail. I tried different loop constructs but the problem is that it never returns a value but a procedure name.
I know, I'm missing something very basic here but I'm stuck anyway.
Since your sum-list function operates only on numbers you need to project your rec list to a number list. This can be done with a map function. The expression (map rec-age reclist) will yield the number list for you.
Altering your code:
(define (sum-list lst . lkey)
(define key (if (null? lkey) values (car lkey)))
(cond
[(empty? lst) 0]
[(+ (key (first lst)) (sum-list (rest lst) key))]))
Alternative tail recursive version
(define (sum-list lst . lkey)
(define key (if (null? lkey) car (compose (car lkey) car)))
(let loop ((acc 0) (lst lst))
(if (null? lst)
acc
(loop (+ acc (key lst))
(cdr lst)))))
Alternate higher order procedure version in one blob:
(define (sum-list lst . lkey)
(define key (if (null? lkey) values (car lkey)))
(foldl (lambda (x acc)
(+ acc (key x)))
0
lst))
Using map to get the values and apply:
(define (sum-list lst . lkey)
(apply +
(if (null? lkey)
lst
(map (car lkey) lst))))
For many elements this might be more effective:
(define (sum-list lst . lkey)
(foldl +
0
(if (null? lkey)
lst
(map (car lkey) lst))))
All work like this:
(sum-list '(1 2 3 4)) ; ==> 10
(sum-list '((1)(2)(3)(4)) car) ; ==> 10
(sum-list reclist rec-age) ; ==> 80
I have been asked to translate a couple of C functions to scheme for an assignment. My professor very briefly grazed over how Scheme works, and I am finding it difficult to understand. I want to create a function that checks to see which number is greater than the other, then keeps checking every time you input a new number. The issue I am having is with variable declaration. I don't understand how you assign a value to an id.
(define max 1)
(define (x x)
(let maxfinder [(max max)]
(if (= x 0)
0
(if (> max x)
max
((= max x) maxfinder(max))))))
The trouble I keep running into is that I want to initialize max as a constant, and modify x. In my mind this is set up as an infinite loops with an exit when x = 0. If max is > x, which it should not be for the first time through, then set max = to x, and return x. I don't know what to do with the constant max. I need it to be a local variable. Thanks
Parenthesis use is very strict. Besides special forms they are used to call procedures. eg (> max x) calls procedure > with arguments max and x. ((if (> x 3) - +) 6 x) is an example where the if form returns a procedure and the result is called.
((= max x) ...) evaluates (= max x) and since the result is not a procedure it will fail.
maxfinder without parenthesis is just a procedure object.
(max) won't work since max is a number, not a procedure.
As for you problem. You add the extra variables you need to change in the named let. Eg. a procedure that takes a number n and makes a list with number 0-n.
(define (make-numbered-list n)
(let loop ((n n) (acc '()))
(if (zero? n)
acc
(loop (- n 1) (cons n acc)))))
Local variables are just locally bound symbols. This can be rewritten
(define (make-numbered-list n)
(define (loop n acc)
(if (zero? n)
acc
(loop (- n 1) (cons n acc))))
(loop n '()))
Unlike Algol dialects like C you don't mutate variables in a loop, but use recusion to alter them.
Good luck
If i understand you correctly, you are looking for the equivalent of a C function's static variable. This is called a closure in Scheme.
Here's an example implementation of a function you feed numbers to, and which will always return the current maximum:
(define maxfinder
(let ((max #f)) ; "static" variable, initialized to False
(lambda (n) ; the function that is defined
(when (or (not max) (< max n)) ; if no max yet, or new value > max
(set! max n)) ; then set max to new value
max))) ; in any case, return the current max
then
> (maxfinder 1)
1
> (maxfinder 10)
10
> (maxfinder 5)
10
> (maxfinder 2)
10
> (maxfinder 100)
100
So this will work, but provides no mechanism to reuse the function in a different context. The following more generalised version instantiates a new function on every call:
(define (maxfinder)
(let ((max #f)) ; "static" variable, initialized to False
(lambda (n) ; the function that is returned
(when (or (not max) (< max n)) ; if no max yet, or new value > max
(set! max n)) ; then set max to new value
max))) ; in any case, return the current max
use like this:
> (define max1 (maxfinder)) ; instantiate a new maxfinder
> (max1 1)
1
> (max1 10)
10
> (max1 5)
10
> (max1 2)
10
> (max1 100)
100
> (define max2 (maxfinder)) ; instantiate a new maxfinder
> (max2 5)
5
Define a function to determine the maximum between two numbers:
(define (max x y)
(if (> x y) x y))
Define a function to 'end'
(define end? zero?)
Define a function to loop until end? computing max
(define (maximizing x)
(let ((input (begin (display "number> ") (read))))
(cond ((not (number? input)) (error "needed a number"))
((end? input) x)
(else (maximizing (max x input))))))
Kick it off:
> (maximizing 0)
number> 4
number> 1
number> 7
number> 2
number> 0
7
A function that returns how many times it has been called in Scheme would look like
(define count
(let ((P 0))
(lambda ()
(set! P (+ 1 P))
P)))
(list (count) (count) (count) (count)) ==> (list 1 2 3 4)
But suppose that we have an expression that looks like this
(map ______ lst)
and we want that to evaluate to
(list 1 2 3 ... n)
where n = (length list)
The problem requires we use a lambda statement in the blank, and we cannot use any auxiliary definitions like (count) in the blank, so
(lambda (x) (count))
is not allowed. Simply replacing (count) with the previous definition like this:
(map
(lambda (x)
((let ((P 0))
(lambda ()
(set! P (+ 1 P))
P))))
L)
doesn't work either.
Any suggestions?
You're very, very close to a correct solution! in the code in the question just do this:
The outermost lambda is erroneous, delete that line and the corresponding closing parenthesis
The innermost lambda is the one that will eventually get passed to the map procedure, so it needs to receive a parameter (even though it's not actually used)
Delete the outermost parenthesis surrounding the let form
It all boils down to this: the lambda that gets passed to map receives a parameter, but also encloses the P variable. The let form defines P only once in the context of the passed lambda, and from that point on the lambda "remembers" the value of P, because for each of the elements in the list the same P is used.
You're 90% of the way there. Use the right-hand-side of your count definition in the blank, and add an (ignored) argument to the function.
(define add-stat-var
(let ( (P '()) )
(lambda (x1)
(if (equal? x1 "ResetStatVar") (set! P '()) (set! P (cons x1 P)))
P
) ;lambda
) ;let
) ;define
(define (test-add-stat-var x)
(let* ( (result '()) )
(set! result (add-stat-var 12))
(set! result (add-stat-var 14))
(set! result (add-stat-var 16))
(display (add-stat-var x)) (newline)
(set! result (add-stat-var "ResetStatVar"))
(display (cdr (add-stat-var x))) (newline)
)
)
Define a function sum, which takes two numbers, or two real functions, and returns their sum. E.g.
(sum 1 2) => 3
((sum cos exp) 0) => 2
I get that for the sum of two numbers the code would be the following:
(define sum (lambda (x y)
(+ x y)))
But what would be the code for the two real functions...? How would I do this? can anyone please help?
Also how would I do this:
Define a function sum-all which works like sum, but works on a list of numbers or a list of functions. Assume the list contains at least one element.
E.g.
(sum-all (list 1 2 3)) => 6
((sum-all (list cos sin exp)) 0) => 2
Note: this is not homework... I was going through a past midterm.
For the first part of your question, I'll have to agree with PJ.Hades that this is the simplest solution:
(define (sum x y)
(if (and (number? x) (number? y))
(+ x y)
(lambda (n)
(+ (x n) (y n)))))
For the second part, we can make good use of higher-order procedures for writing a simple solution that is a generalization of the previous one:
(define (sum-all lst)
(if (andmap number? lst)
(apply + lst)
(lambda (n)
(apply + (map (lambda (f) (f n)) lst)))))
In both procedures, I'm assuming that all the operands are of the same kind: they're either all-numbers or all-functions, as inferred from the sample code provided in the question.
Do you mean this?
(define (sum a b)
(if (and (number? a) (number? b))
(+ a b)
(lambda (x)
(+ (a x) (b x)))))
(define (sum lst)
(cond
[(empty? lst) 0]
[else (foldr + 0 lst)]))
((lambda (a b) (+ a b)) 4 5)
this how it is done using lambda.
using define we can write as follows
(define (sum a b) (+ a b))
I'm a little rusty with my Scheme, so perhaps there's a better way to do this, but you could do:
(define (sum-all lst)
(define (sum-funcs-helper funcs x)
(if (empty? funcs)
0
(+ ((car funcs) x)
(sum-funcs-helper (cdr funcs) x))))
(if (empty? lst)
0 ;; Beats me what this is supposed to return.
(if (number? (car lst))
(apply + lst)
(lambda (x) (sum-funcs-helper lst x)))))
I'm writing a program in Lisp(common lisp dialect)..
I want the program to count the number of sublists in a list..
This is what I have written till now:
(defun llength (L)
(cond
((null L) 0)
((list (first L)) (progn (+ (llength (first L)) 1) (llength (rest L))))
((atom (first L)) (llength (rest L)))
)
)
The function returns the error "Unbound variable: LLENGTH" and I don't understand why or how I can fix it..
Any suggestions ?
You have multiple errors in your code.
First of all, list function creates new list, not checking if it is a list. The function you need is listp - "p" at the end means "predicate".
Second, (progn (+ (llength (first L)) 1) (llength (rest L)) will not increase counter. progn performs expressions one by one and returns result of the last expression, other results are just thrown out. progn is there mostly for side effects. What you actually need is addition of all three components: 1 to indicate one found list, result of applying function to the first element and result for applying to the rest. So, this line must be:
((listp (first L)) (+ (llength (first L)) (llength (rest L)) 1))
More errors may exist, please, be careful to indent code correctly - it really helps to reduce them.
When you define a function with the (defun function name (parameters)) call you must then call the function by typing:
(function name (parameters))
Perhaps you were simply typing:
function name (parameters)
Doing this will get you the error you are receiving so be sure to encompass your whole statement in parenthesis.
(defun llength (list)
(cond
((null list) 0)
((listp (first list))
;; 1 + the count of any sub-lists in this sub-list + the
;; count of any sub-lists in the rest of the list.
(+ 1 (llength (first list))
(llength (rest list))))
(t (llength (rest list)))))
Test:
> (llength '(1 2 3 4))
0
> (llength '(1 2 (3 4)))
1
> (llength '(1 2 (3 (4))))
2
> (llength '(1 2 (3 4) (5 6) (7 8) (9 (10 (11)))))
6