How can I use CONS in reverse way? - scheme

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)

Related

just started learning Scheme

I don't know why this does not work. I get an error saying "Error: 1 is not a function[(anon)]"
(define (mem lst ele)
(cond ;if the list is empty return false
((null? lst) #f)
;if the first element is equal to the given element return true
;otherwise call the function with rest of the list
(else (if (= ele (car lst))
#t
(mem (cdr lst) ele)))))
(mem ā€™(1) ā€™(1 4 -2))
It works for me; how are you calling mem? I am guessing that you did something like: (mem (1 2 3 4) 1). Procedure calls always evaluate their arguments in Scheme, so in the procedure call (mem (1 2 3 4) 1) the expression (1 2 3 4) is evaluated; but lists are evaluated as if the first member is a procedure, so 1 is treated as a function; it is not, and this raises an exception.
You could quote the list: (mem (quote (1 2 3 4)) 1), or you can use the shorthand (mem '(1 2 3 4) 1). quote is a special form that does not evaluate its argument; instead it just returns whatever datum it is given. You can try this out at the REPL:
> (+ 1 2)
3
> (quote (+ 1 2))
(+ 1 2)
> '(+ 1 2)
(+ 1 2)
Here the naked expression (+ 1 2) evaluates to 3, but the quoted expressions just return the expressions given to quote. That is, (quote (+ 1 2)) evaluates to the expression (+ 1 2), not to the result of evaluating the expression (+ 1 2). In the case of (1 2 3 4):
> (quote (1 2 3 4))
(1 2 3 4)
> '(1 2 3 4)
(1 2 3 4)
> (1 2 3 4)
Exception: attempt to apply non-procedure 1
Type (debug) to enter the debugger.
The procedure call (mem '(1 2 3 4) 1) would evaluate the expression '(1 2 3 4) before passing that value to mem. Since the expression '(1 2 3 4) evaluates to a list, that list is the value which is passed to mem. This differs from the erroneous call (mem (1 2 3 4) 1), which attempts to evaluate the expression (1 2 3 4) by calling the (nonexistent) procedure 1 with the arguments 2, 3, and 4.
You could also use list to create the input: (mem (list 1 2 3 4) 1). list is also a procedure, and so it evaluates its arguments. Here the call to mem would evaluate the expression (list 1 2 3 4), and since list is a procedure the call to list would evaluate the arguments 1, 2, 3, and 4. Numbers are self-evaluating in Scheme, so the call to list would return a list (1 2 3 4); this list is the value passed to mem, which has now evaluated its argument (list 1 2 3 4).
Some Comments on the Posted Code
The cond form can take multiple conditional clauses, and there is no reason to use if here. Instead, you can do:
(define (mem lst ele)
(cond
((null? lst) #f)
((= ele (car lst)) #t)
(else
(mem (cdr lst) ele))))
The = predicate only works for numbers; to handle more general inputs you might choose equal?:
(define (mem lst ele)
(cond
((null? lst) #f)
((equal? ele (car lst)) #t)
(else
(mem (cdr lst) ele))))
Now you can work with, e.g., lists of symbols, or lists of lists:
> (mem '(a b c d) 'c)
#t
> (mem '(a b c d) 'e)
#f
> (mem '(1 (2 3) 4) '(2 3))
#t
> (mem '(1 (2 (3 4)) 5) '(2 (3 4)))
#t
> (mem '(1 (2 3) 4) 3) ;; does not descend into nested lists
#f
Note that changing the equality predicate to equal? will allow lists to be searched for at the top level of the input list, but no deeper. The list (2 (3 4)) can be found in the list (1 (2 (3 4)) 5) because it is at the top level of the list, i.e., (2 (3 4)) is an element of the list (1 (2 (3 4)) 5). But, (3 4) is not an element of the top level list, so the current mem procedure can't find it here. Another definition for mem would be needed to search within nested lists.
It seems from your example that you are looking for the list '(1 4 -2) in the list '(1), which should evaluate to #f. However your implementation expects all elements to be numbers since you compare with = which is a number only comparison procedure. If you want to compare any type you should use equal? which compares two objects of any type and supports comparing structures.
You were using an acute-accent instead of a single-quote for your literals.
#lang racket
(define (mem ele lst) ;; easier to read with one element -then- list
;; ..plus that's how you wrote your call to it,
;; so this arg-order makes more sense here.
(cond ;; cond doesn't need "else"
((null? lst) #f)
((if (= ele (car lst)) #t
(mem ele (cdr lst)))) ;; element, then list now
)
)
(mem 1 '(1 4 -2))
;; don't know why element needed to be wrapped in a '(1) literal list container
;; also literals require single-quote ' character, not the ā€™ acute-accent
https://docs.racket-lang.org/racket-cheat/index.html

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

Scheme - Adding a list to a list of lists?

I am trying to answer a scheme question, for a part of this question I have to make a list of lists:
(define (join a b (result '()))
(cons (list a b) result))
So I am taking in two characters, and placing them in a list, then I need to place each sublist into a list of lists, this function is being called recursively with two characters each time, so it is supposed to work like this:
join 1 4
=> ((1 4))
join 2 5
=> ((1 4) (2 5))
join 3 6
=> ((1 4) (2 5) (3 6))
However, I am getting ((3 6) (2 5) (1 4)), so the elements need to be reversed, I tried reversing my cons function to (cons result (list a b)) but then I get (((() 1 4) 2 5) 3 6), how can I get the list the right way around, or is there an easier way to do what I'm doing?
If you need to add elements at the end of a list use append; cons is for adding elements at the head. Try this:
(define (join a b (result '()))
(append result (list (list a b))))
Notice that append combines two lists, that's why we have to surround the new element inside its own list. Also, it's not a good idea to add elements at the end, using append is more expensive than using cons - if possible, rethink your algorithm to add elements at the head, and reverse the result at the end.
This can easily be done like this:
(define (group-by-2 lst)
(let loop ((lst lst) (rlst '()))
(if (or (null? lst) (null? (cdr lst)))
(rcons->cons rlst)
(loop (cdr lst)
(rcons (list (car lst)
(cadr lst))
rlst)))))
(group-by-2 '(1 2 3 4 5 6 7 8))
; ==> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8))
Now rcons is like cons but it makes a reverse list. (rcons 1 (rcons 2 (rcons 3))) ; ==> {3 2 1} however it is not a list so you have to convert it to a list (rcons->list (rcons 1 (rcons 2 (rcons 3))) ; ==> (3 2 1)
The magic functions are really not that magical:
(define rcons cons)
(define rcons->cons reverse)
So in fact I didn't really have to make that abstraction, but hopefully I made my point. It doesn't matter how you organize the intermediate data structure in your programs so why not make the best for the job you are doing. For lists it's always best to iterate from beginning to end and make from end to beginning. Every insert O(1) per element and you do a O(n) reverse in the end. It beats doing append n times that would make it O(nĀ²)

On Scheme cons and dots notation

Given
#;> (cons (cons 1 2) 3)
((1 . 2) . 3)
When we try
#;> (cons 3 (cons 1 2))
(3 1 . 2)
What governs where the . is used? What would the memory representation of these constructs be?
Scheme implementations usually print things that look like lists in list form:
-> (cons 1 (cons 2 '()))
'(1 2)
In your example, (cons 3 (cons 1 2)) would be a list if it weren't for the last 2. So your implementation makes a best effort to print it as a list until the 2. The other example does not contain any part that looks like a list, so it just prints as nested pairs.

Modify part of list using set?

Using set! I want to be able to modify a local state list variable lst, but only a part of it
For example, I want to insert values inside an inner list:
((1 2) (4 5))
becomes
((1 2 3) (4 5))
I want to be able to do something like set! (car lst) (append (car lst) 3)
But that seems to only modify the temporary variable generated by (car lst).
The only way I can think of is to create a new list with the new desired values and set lst to be the new list, but that seems wasteful and unnecessary. Is there a better way to do it?
try this:
(define lst (list (list 1 2) (list 4 5)))
lst
> ((1 2) (4 5))
(set-cdr! (cdar lst) (list 3))
lst
> ((1 2 3) (4 5))
when modifying cons/lists you should use set-cdr! and set-car!
EDIT: for racket
use mutable list:
(require racket/mpair)
(define lst (mlist (mlist 1 2) (mlist 4 5)))
lst
> (mcons (mcons 1 (mcons 2 '())) (mcons (mcons 4 (mcons 5 '())) '()))
(set-mcdr! (mcdr (mcar lst)) (list 3))
> (mcons (mcons 1 (mcons 2 #<promise:temp2>)) (mcons (mcons 4 (mcons 5 '())) '()))
lst
Depending on which interpreter of Scheme you're using, you might need to do a bit more of work. For instance, in Racket the list primitives are not mutable by default, and you'll have to use the mutable version of the procedures:
(require scheme/mpair)
(define lst (mlist (mlist 1 2) (mlist 4 5)))
lst
(set-mcdr! (mcdr (mcar lst)) (mlist 3))
lst
The standard idiom in Scheme for creating a list piecemeal is to prepend elements to the front, using cons, and not trying to set-cdr! the last cons cell in the list. At the end, when your list is done, you can then use reverse to get the elements in the correct order. This way, no list mutation is necessary per se.
So if you're trying to create the list (1 2 3) piecemeal:
Start off with the empty list, (), and cons 1 to it. This gives you (1).
Then cons 2 to the list: (2 1)
Then cons 3 to the list: (3 2 1)
Finally, when you're done building the list, reverse it: (1 2 3)
You may ask why this is "better". That's because accessing the last pair to set-cdr! is an O(n) operation; with linked lists, elements are not random-access, but are linear on the element position being accessed. Whereas, cons is always O(1).
reverse is an O(n) operation, but as long as you're doing it only at the end (when you are ready to build the list in the correct order), rather than calling it all the time, that won't detrimentally affect performance.

Resources