SCHEME from list to its values - scheme

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))

Related

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))

If a list is found in another list?

I started to learn Racket and I don't know how to check if a list is found in another list. Something like (member x (list 1 2 3 x 4 5)), but I want that "x" to be a a sequence of numbers.
I know how to implement recursive, but I would like to know if it exists a more direct operator.
For example I want to know if (list 3 4 5) is found in (list 1 2 3 4 5 6 )
I would take a look at this Racket Object interface and the (is-a? v type) -> boolean seems to be what you are looking for?, simply use it while looping to catch any results that are of a given type and do whatever with them
you may also want to look into (subclass? c cls) -> boolean from the same link, if you want to catch all List types in one go
should there be a possiblity of having a list inside a list, that was already inside a list(1,2,(3,4,(5,6))) i'm afraid that recursion is probally the best solution though, since given there is a possibility of an infinit amount of loops, it is just better to run the recursion on a list everytime you locate a new list in the original list, that way any given number of subList will still be processed
You want to search for succeeding elements in a list:
(define (subseq needle haystack)
(let loop ((index 0)
(cur-needle needle)
(haystack haystack))
(cond ((null? cur-needle) index)
((null? haystack) #f)
((and (equal? (car cur-needle) (car haystack))
(loop index (cdr cur-needle) (cdr haystack)))) ; NB no consequence
(else (loop (add1 index) needle (cdr haystack))))))
This evaluates to the index where the elements of needle is first found in the haystack or #f if it isn't.
You can use regexp-match to check if pattern is a substring of another string by converting both lists of numbers to strings, and comparing them, as such:
(define (member? x lst)
(define (f lst)
(foldr string-append "" (map number->string lst)))
(if (regexp-match (f x) (f lst)) #t #f))
f converts lst (a list of numbers) to a string. regexp-match checks if (f x) is a pattern that appears in (f lst).
For example,
> (member? (list 3 4 5) (list 1 2 3 4 5 6 7))
#t
One can also use some string functions to join the lists and compare them (recursion is needed):
(define (list-in-list l L)
(define (fn ll)
(string-join (map number->string ll))) ; Function to create a string out of list of numbers;
(define ss (fn l)) ; Convert smaller list to string;
(let loop ((L L)) ; Set up recursion and initial value;
(cond
[(empty? L) #f] ; If end of list reached, pattern is not present;
[(string-prefix? (fn L) ss) #t] ; Compare if initial part of main list is same as test list;
[else (loop (rest L))]))) ; If not, loop with first item of list removed;
Testing:
(list-in-list (list 3 4 5) (list 1 2 3 4 5 6 ))
Output:
#t
straight from the Racket documentation:
(member v lst [is-equal?]) → (or/c list? #f)
v : any/c
lst : list?
is-equal? : (any/c any/c -> any/c) = equal?
Locates the first element of lst that is equal? to v. If such an element exists, the tail of lst starting with that element is returned. Otherwise, the result is #f.
Or in your case:
(member '(3 4 5) (list 1 2 3 4 5 6 7))
where x is '(3 4 5) or (list 3 4 5) or (cons 3 4 5)
it will return '(3 4 5 6 7) if x ( searched list '(3 4 5) ) was found in the list or false (#f) if it was not found
or you can use assoc to check if your x is met in one of many lists, or :
(assoc x (list (list 1 2) (list 3 4) (list x 6)))
will return :
'(x 6)
There are also lambda constructions but I will not go in depth since I am not very familiar with Racket yet. Hope this helps :)
EDIT: if member gives you different results than what you expect try using memq instead

How to convert a list into its elements

This must be very easy to accomplish but I am new to racket and dont know how:
I have a list (1 2 3 4) and would like to convert it into (1)(2)(3)(4)
Or is there a way to build it as (1)(2)(3)(4). I am using
cons '(element) call-function
to build it inside a function (recursively)
Try this:
(map list '(1 2 3 4))
From your text, I see that you do '(element). Problem with that is that everything which is quoted is never anything but what you see. Thus if element happens to be a variable it won't be expanded because of the quote.
The right way to get a list with one element would be to use list. eg. (list element) to get whatever the variable element to be the one element in your list. However, you won't need this in a roll-your-own recursive procedure:
(define (listify lst)
(if (null? lst) ; if lst is null we are done
'() ; evaluate to the empty list
(cons (list (car lst)) ; else we make a list with the first element
(listify (cdr lst))))) ; and listify the rest of the list too
Most of the procedure now is facilitating going through the argument, but since it's a common thing to do we can use higher order procedures with foldr so that you only concentrating on what is going to happen with the element in this chain in correspondence with the rest of the process:
(define (listify lst)
(foldr (lambda (e acc)
(cons (list e) ; chain this element wrapped in a list
acc)) ; with the result from the rest of the list
'() ; initiate with an empty list
lst)) ; go through lst
Of course, since we do something with each element in a list and nothing fancy by using map we only need to supply what to do with each element rather telling how to join the chains in the list together as well.
(define (listify lst)
(map list lst)) ; make a new list by applying a list of each element
It's actually a single argument version of zip:
(require srfi/1)
(zip '(1 2 3 4)) ; ==> ((1) (2) (3) (4))
(zip '(1 2 3) '(a b c)) ; ==> ((1 a) (2 b) (3 c))
There you go. As simple as it can get.

Scheme create list of pairs using foldr without explicit recursion

I am learning a course of Scheme and have to do the following task. I have to write a function that gets two lists A and B in the same length and returns one list that every item inside is a list of two items - one from A and second from B.
For example the function gets '( 1 2 3) and '(4 5 6) and returns '((1 4)(2 5)(3 6)).
I can do that using map like this:
(define (func lst1 lst2) (map (lambda(x y) (list x y)) lst1 lst2))
But the the question is to do that by foldr and without explicit recursion.
Can anyone please help me? I have no idea how to do that....
Thanks!
The trick is knowing what to pass as a function parameter, here's how:
(define (func l1 l2)
(foldr (lambda (e1 e2 acc)
(cons (list e1 e2) acc))
'()
l1 l2))
Notice that we're passing two lists at the end of foldr, so the lambda expects three parameters: the current element from the first list (e1), the current element from the second list (e2) and the accumulated output (acc), which starts with value '(). The rest is easy, just build the output along using cons and list. It works as expected:
(func '(1 2 3) '(4 5 6))
=> '((1 4) (2 5) (3 6))

How to count individual elements in a pair - scheme ?

(cons 2 (cons ( cons 2 3 ) (cons 4 5 )))
This gives me a list that looks like this : (2 (2 . 3) 4 . 5) when I try to count the number of elements in this list the output is 3 as exepected.
How do I calculate the number of individual elements of a pair ? The output in this case should be 5 for example.
Here's a possible solution, the question is essentially asking for the number of atoms in a list structure (not necessarily null-terminated proper lists):
(define (count-all seq)
(cond ((null? seq) 0)
((not (pair? seq)) 1)
(else (+ (count-all (car seq))
(count-all (cdr seq))))))
It works on sequences of elements like this:
If the sequence is empty, it has zero elements
If the sequence is not a cons cell (a pair of elements), it's because it's a single element - an atom
Otherwise add the elements of both the car and the cdr of the sequence
It works as expected for arbitrarily nested list structures:
(count-all '(2 (2 . 3) 4 . 5))
=> 5
(count-all '(1 (2 . (3 (4 . 5) 6)) 7 . 8))
=> 8
We can solve this problem recursively for arbitrarily deeply nested lists.
(define (atom? x) (not (pair? x)))
(define (count-atoms lst)
(cond ((null? lst) 0) ; nothing to count, return 0
((atom? lst) 1) ; lst contains only one thing, return 1
(else ; otherwise, lst contains multiple elements
(+ (count-atoms (car lst)) ; add the number of atoms in the first position
(count-atoms (cdr lst)))))) ; to the number of atoms in the rest of the list
EDIT: This is a duplicate to Oscar's answer. I did not see that he had answered when I hit submit, but will leave this here since I feel the comments are useful.

Resources