Way to explode list into arguments? - scheme

Assume I have a procedure upto that when called like (upto 1 10) will generate the list '(1 2 3 4 5 6 7 8 9 10).
If I want to use this list as arguments to a function like lcm that takes multiple arguments rather than a single list, like (lcm 1 2 3 4 5 6 7 8 9 10) is there a way to do this?

Use apply: e.g
(apply lcm (upto 1 10))
"apply" applies a function to a list of arguments.

One way I found to do this using eval is the following:
(eval (cons 'lcm (upto 1 10)))

In MIT-Scheme (unsure of others) you can use the dot in your function definition.
(define (func-with-multiple-args . args)
(let loop ((args args))
(if (null? args)
'done
(begin (display (car args)) (loop (cdr args))))))
Calling with
(func-with-multiple-args 1 2 3 4)
will do the job. Note that the args get put into a list.
Fun fact: the `list' procedure is actually defined in list.scm of the MIT-Scheme "runtime" source as:
(define (list . args)
args)

Related

SCHEME from list to its values

How can I convert this list
(define l list '(1 2 3 4) )
to its own value 1, 2, 3 and 4
I need to do this because I have a function
(define (push! stk . args)
(stk 'push! args ) )
for this other function
((eq? msg 'push!) (set! stack (append (reverse args) stack)))
but the result I get when using push! is a list in a list, I don't want this
You can by iteration. eg. fold:
(fold cons '() '(1 2 3 4))
; ==> (4 3 2 1)
Now the most stackie functional structure is the lisp list since it is a singly linked list that constructs from end to beginning while iterates from beginning to end.
Go the other way instead - gather all the arguments in one list, and then apply:
(apply push! (cons the-stack l))

Update list in racket without hash

I have the 2 lists, '(1 2 3 4), and '(add1 sub1 add1). They do not have same length. The first list is numbers, the second list is functions. I want to apply the functions to each of element in the number list.
'(1 2 3 4) (add1 sub1 add1) -> '(2 3 4 5) '(sub1 add1)
It look very simple, but I find I can not update the lists. Because in Scheme there is no way to update lists without hash. I can only create new lists. So every time I have to create a new list for each function in the second list. Can someone help me code this question?
Alternatively you could use map and compose in combination.
This is much easier to read and understand.
(map (compose add1 sub1 add1) '(1 2 3 4))
;; '(2 3 4 5)
(compose add1 sub1 add1) chains the functions one after another
and map applies this chained/composed function on each element of the input list '(1 2 3 4).
Generalize to a function:
(define (map-functions funcs . args)
(apply map (apply compose funcs) args))
(map-functions (list add1 sub1 add1) '(1 2 3 4)) ;; '(2 3 4 5)
compose is inbuilt but one can define it like this (% in names to not to overwrite the existing compose.
;; first a compose to compose to functions
(define (%%compose f1 f2)
(lambda args
(f1 (apply f2 args))))
;; then, generalize it for as many functions as one wants (as a variadic function) using `foldl`
(define (%compose . funcs)
(foldl %%compose (car funcs) (cdr funcs)))
You're looking for a left fold. It looks like Racket calls it foldl, which will do the job, combined with map. Something like (Untested, because I don't have Racket installed):
(define functions (list add1 sub1 add1)) ; So you have functions instead of symbols like you get when using quote
(define numbers '(1 2 3 4))
(foldl (lambda (f lst) (map f lst)) numbers functions)
Basically, for each function in that list, it maps the function against the list returned by mapping the previous function (Starting with the initial list of numbers when there is no previous).
If you're stuck with a list of symbols and can't use the (list add1 ... trick to get references to the actual functions, one approach (And I hope there are better ones) is to use eval and some quasiquoting:
(foldl (lambda (f lst) (eval `(map ,f (quote ,lst)))) '(1 2 3 4) '(add1 sub1 add1))

How can I use CONS in reverse way?

Normally, we pass two arguments to cons, in RACKET
eg:
(cons 23 '(1 2 3))
which outputs '(23 1 2 3)
Is there any procedure to do the following
(procedure '(1 2 3) 23) => '(1 2 3 23)
Try this:
(append '(1 2 3) '(23))
=> '(1 2 3 23)
That's fine for appending a single element. If you're planning to repeatedly add many elements at the end, it's better if you cons everything at the head and then reverse the list when you're done. Why? because using append for building an output list will quickly degenerate into an O(n^2) solution (see: Schlemiel the Painter's algorithm)
In Lisp/Scheme/Racket if you want a procedure, writing it makes it largely indistinguishable from built in procedures:
#lang racket
(define (procedure a-list an-atom)
(cond
[(not (list? a-list)) (error "procedure: first argument not a list")]
[(pair? an-atom) (error "procedure: second argument is a list")]
[else
(append a-list (list an-atom))]))
Then use it:
> (procedure '(1 2 3) 23)
'(1 2 3 23)

DrRacket/Scheme: Contract violation, number expected?

So I have 3 functions defined in scheme, sumlist adds up all numbers in a list, and mean gives me the mean of the list. mean2 calls mean and does the same thing, but i get an error. It says the error is coming from sumlist function.
(define (sumlist lst)(if(null? lst)0 (+(car lst)(sumlist(cdr lst)))))
(define mean (lambda x(/(sumlist x)(length x))))
(define mean2 (lambda x(mean x)))
This is how i call the functions
(mean 1 2 3 4 5)
=>3 ;it works
(mean2 1 2 3 4 5)
+: contract violation
expected: number?
given: '(1 2 3 4 5)
argument position: 1st
other arguments...:
0
I'm still new too scheme just got introduced to it last week, but it is really frustrating..what am i doing wrong?
Because (define (x . y) ...) is the same as (define x (lambda y ...)),
the following implementations of identity are the same
(define (fun arg1)
arg1)
(define fun
(lambda (arg1)
arg1)
While the following implementation of list are the same
(define (fun . args)
args)
(define fun
(lambda args
args)
So when you apply (mean2 2 3 4 5) x is the list (2 3 4 5), and (mean '(2 3 4 5)) also wraps all arguments into a list so the call to sumlist turns into (sumlist '((2 3 4 5))). In sumlist you try to do (+ '(2 3 4 5) 0) which won't work since + expects numbers as arguments, not lists. To fix this you need to define mean2 as one of:
;; Just make an alias to mean
(define mean2 mean)
;; wrap mean
(define (mean2 x)
(mean x))
;; use apply
(define (mean2 . x)
(apply mean x)) ; apply undoes list
I'd use the methods in the order of appearance. Sometimes using apply is the best but not if you can just alias or wrap.

#<Closure> in output

I was writing a function to switch the last element of a list to the beginning:
(define last-elem
(lambda (l)
(car (reverse l))))
(define all-but-last
(lambda (l)
(reverse (cdr (reverse l)))))
(define (last-to-first x) (append (list last-elem x) (all-but-last x)))
(last-to-first '(1 2 3 4 5 6))
It didn't work and I knew why. I forgot to put the brackets around list last-elem x
The thing is, I was curious about the output of the wrongly-typed code:
(#<Closure> (1 2 3 4 5 6) 1 2 3 4 5)
What is the meaning if this? How did it come out to this?
In Racket, the output is
'(#<procedure:last-elem> (1 2 3 4 5 6) 1 2 3 4 5)
which is a little clearer.
A reference to a function is always stored with its referencing environment, a.k.a. as a closure, and your Scheme implementation chooses to display it that way.
(list last-elem x)
doesn't call the function last-elem. It simply returns a list of two elements: the value of the variable last-elem (which is a procedure) and the value of the argument x. You want:
(list (last-elem x))
But there's no reason to make a list in the first place. Try:
(define (last-to-first x)
(cons (last-elem x) (all-but-last x)))
In Scheme, all identifiers denote either a syntactic keyword (bound to a 'transformer') or a variable (bound to a value). In your code last-elem denotes a variable bound to a function, which you defined. When you write:
(list last-elem x)
the interpreter/compiler produces a list with the value of last-elem and x. Thus, the result of #<Closure> in the list.

Resources