Below is my code which takes a car element of a list(carVal) and an list(initialized to empty) as parameters. I want to append the element to the list but the same is not working.
(define populateValues
(lambda (carVal currVal)
(append currVal(list carVal ))
(display currVal)))
The display shows empty list all the time () . Can anyone help me understand why?
Well, there is append! as a primitive, which solves most of your problems, as noted already, Scheme tends to frown on mutation, it is possible, but typically avoided, so all procedures that mutate have a ! (called a bang) at their end.
Also, set! does not mutate data, it changes an environment, it makes a variable point to another thing, the original data is left unchanged.
Mutating data in Scheme is quite cumbersome, but, to give you my own implementation of append! to see how it is done:
(define (append! lst . lsts)
(if (not (null? lsts))
(if (null? (cdr lst))
(begin
(set-cdr! lst (car lsts))
(apply append! (car lsts) (cdr lsts)))
(apply append! (cdr lst) lsts))))
Note the use of set-cdr!, which is a true mutator, it only works on pairs, it mutates data in memory, unlike `set!'. If a pair is passed to a function and mutated with set-cdr! or set-car!, it is mutated every-where in the program.
This obeys the SRFI append! spec which says that it should be variadic and that it should return an undefined value, for instance.
(define l1 (list 1 2 3 4))
(define l2 (list 2 3 4))
(define l3 (list 3 1))
(append! l1 l2 l3)
l1
l2
l3
Which displays:
(1 2 3 4 2 3 4 3 1)
(2 3 4 3 1)
(3 1)
As visible, append! can take an infinite number of arguments and it mutates them all but the last.
Scheme might not be the ideal language for you though. The use of append! as said before is nonstandard, instead, append is preferred, which does not mutate and is called for its return value. Which I implement as such:
(define (append . lsts)
(cond
((null? lsts) '())
((null? (car lsts)) (apply append (cdr lsts)))
(else (cons (caar lsts) (apply append (cdar lsts) (cdr lsts))))))
> (append (list 1 2 3) (list 4 5 6) (list 'granny 'porn))
(1 2 3 4 5 6 granny porn)
Which shows a more familiar Scheme style in the absence of mutation, heavy use of recursion
and no use of sequencing.
Edit: If you just want to add some elements to a list and not per se join two though:
(define (extend l . xs)
(if (null? l)
xs
(cons (car l) (apply extend (cdr l) xs))))
(define (extend! l . xs)
(if (null? (cdr l))
(set-cdr! l xs)
(apply extend! (cdr l) xs)))
(extend '(0 1 2 3) 4 5 6)
(define list1 '(0 1 2 3))
(extend! list1 4 5 6)
list1
Which does what you expect
append creates a new list, it does not modify an existing one.
This is because in general, Scheme (and Racket in this case) is a language that prefers functional style.
You could get somewhat closer with a set! -- but even that will disappoint you since it will modify only the local binding.
Note that in Racket in particular, lists are immutable, so there's nothing that can change a list.
Furthermore, even if you could modify a list this way, it's a very inefficient way to accumulate long lists, since you have to repeatedly scan the whole list.
Finally, if you have issues at this level, then I strongly recommend going over HtDP
(append foo bar) returns the concatenation of foo and bar. It doesn't change either foo or bar.
You have to update the value of currVal with set!. Your example should have
(set! currVal (append currVal (list carVal))
(display currVal)
You really need to think about what exact functionality you are looking for
If you want to mutate a referenced list in place, then you have to do the equivalent of append! (as noted in the other answers). But that is dangerous, BECAUSE you may have other code that is counting on the list being immutable, and if you are going to do that, your procedure needs to have a ! in the end to flag that danger.
A cheap approximation to what you want to do, in a more functional style, is:
(define (populateValues carVal currVal)
(let ((ll (append currVal (list carVal))))
(display ll)
ll))
Note that it makes a new list, does the append, displays the result, and RETURNS the new list as a value. This is a useful debugging technique if you don't have access to the intermediate value: bind to a varible, display or log it, and then return it.
Related
I am trying to define a helper function that takes an integer and a list as parameters and produces cartesian product of the integer and the list.
I believe I have the logic figured out. But when I test my code and pass a list into the function, the function returns an empty list.
(define (helper element set)
(cond
((null? set) '())
(cons '(element (car set)) (helper element (cdr set)))
)
)
For example, when I run (helper 5 '(6 8 9)) it returns an empty list.
I can't figure out why, but I think it has something to do with passing an integer with a list as parameters but I can't find anything to confirm this.
You have the wrong syntax for cond. The format is
(cond (test1 then1)
(test2 then2)
...)
There is no special allowance that the last case doesn't need a test. So when you write
(cond
((null? set) '())
(cons '(element (car set))
(helper element (cdr set))))
your test is the symbol cons, and your then-expression is "evaluate '(element (car set)), throwing the result away, and then evaluate and return (helper element (cdr set))" (there is an implicit begin around the expressions in the then part of a cond). Thus, helper always just recurses down to an empty set eventually, and then returns it, making no changes to it.
What you meant to do instead was use something that's always true as your last test, and then use the cons form as the body. Traditionally else is used for this, although #t is also fine:
(define (helper element set)
(cond
((null? set) '())
(else (cons '(element (car set))
(helper element (cdr set))))))
You will then discover another problem, which is that you meant to construct a list containing the values referred to by element and (car set), not to quote that list. What is the difference between quote and list? will help you understand what's doing on there.
try this:
(define (helper element set)
(map (lambda(x) (cons element x)) set))
I have been trying to write function which returns the transpose of a matrix . so an example output would be, (transpose (list '(1 2) '(4 5))) ;==> ((1 4) (2 5)) Here is my function:
(define transpose
(lambda (m1)
(if (null? (cadr m1))
null
(list (indiv (car m1) (cadr m1)) (transpose (rest m1))))))
(define indiv
(lambda (l1 l2)
(if (empty? l1)
null
(list (list (car l1) (car l2)) (indiv (rest l1) (rest l2))))))
the indiv function takes care of the rows recursion whereas transpose calls the indiv function to get the transpose. My question is why doesn't (if (null? (cadr m1)) work in order to check that I have reached the last row of the matrix? is there any possible way to check this in scheme? I don't want another way to solve this problem, I just want to know if this is possible and if yes then how?
This is a rather common function, the usual way to implement it is:
(define (transpose lst)
(apply map list lst))
Think of lst as a list of lists which will be passed as parameters to map, and remember that map accepts more than one input list as parameter:
(map list '(1 2) '(4 5))
Now it's easy to see what's happening: we're mapping list over all the arguments and building a sublist with the first element of the first input list and the first element of the second input list, etc. Then, we'll build a sublist with the second element of the first input list and the second element of the second input list, etc. and so on. And map collects all of the sublists in a single output list. There you go!
'((1 4) (2 5))
Using map is really going to simplify things.
(define transpose
(lambda (m1)
(if (null? (car m1))
null
(cons (map car m1)
(transpose (map cdr m1))))))
Rest is usually the same as cdr, and you don't want that, you want to map cdr onto the matrix representation to get past the first row. You've done this in indiv nicely, but the problem is it won't scale to larger matrices.
The reason your doesn't work is it calls tranpose on the rest of '((1 2) (4 5)) which is '((4 5)) whose cdr has no car. (it's the null list) and you hit an error.
I'm newbie in Scheme and find out that if I change a list with set-car!/set-cdr! (even locally) the parent list is modified too. This is an example what I mean:
(define my-list '(1 2 3 4 5)) ; Original list
(define (function list) ; Some example function
(let ((copy list))
(set-car! copy 'new)
(display copy)
)
(function my-list); will display (new 2 3 4 5)
my-list; but the original is changed "forever" and will be also '(new 2 3 4 5)
My question is:
Is there a way to make a copy of the original list and work only on it, so at the end the original not to be changed?
Your code (let ((copy list)) allows list to be accessed through the name copy. So when you set-car! copy, you are actually set-car!'ing the original list.
The phenomenon of mutation in lisp like languages is a little confusing at first.
Mutation is to be avoided usually, for the reasons you have discovered. Parts of lists and things a floating around. This is because internally each node in a list has two parts - the car is it's value which may point to another list, and it's cdr is the part that follows it - usually this is a lit of things similar to the value in car.
This solves your problem using SRFI1's list-copy function
(let ((copy (list-copy list)))
Here is one way to copy a list (make a new list). This code is not really complete. When we look at it internally it adds pieces of a list in each recursive call. Where do the pieces of each new list-section come from? The cdr is generated with the call (list-copy (cdr list)), while the car is simply taken - not copied! - from the other list.
(define (list-copy list)
(if (null? list) '() (cons (car list) (list-copy (cdr list)))))
The result for you when experimenting, was that the car's of your list copy where borrowed from my-list.
Here is a more proper version:
(define (full-copy list)
(if (null? list)
'()
(if (list? list)
(cons (full-copy (car list)) (full-copy (cdr list)))
list)))
Only the code for the car has changed. Now, the car is reconstructed to. The only parts that are borrowed are the numbers (so this copy is not okay when the numbers are instead something more special). I'm not sure how the srfi1 version works.
The let statement only ever binds one identifier to an object - the object is not copied, you simply have another way to access it. So any changes (use of mutation, as in functions that end in "!") will affect both.
I suggest that when you're learning Scheme or Racket, you avoid all the ! functions such as set-car!, set-cdr!, and set!.
Instead of mutating things, try to think in terms of creating a new thing from the old thing(s).
For instance if you have a list and want something new at the start:
;; Return a new list with `x` replacing the head of the list `xs`.
(define (replace-head xs x) ; list? any? -> list?
(cons x (cdr xs)))
;; Using it:
(replace-head '(1 2 3 4 5) 100)
; => '(100 2 3 4 5)
p.s. A version of replace-head that can handle xs being empty could be:
(define (replace-head xs x) ; list? any? -> list?
(cond [(empty? xs) (list x)]
[else (cons x (cdr xs))]))
(replace-head '(1 2 3 4 5) 100)
; => '(100 2 3 4 5)
(replace-head '() 100)
; => '(100)
You also might find it helpful to look at How to Design Programs, for examples of good ways to design and think in Scheme or Racket.
I am quite new to scheme and I want to take a list such as (1 2 3 4) and send it to a function that will return (4 1 2 3). A second run would return (3 4 1 2) and so on creating a right shifted list with each call to the function.
The first way I figured out to solve this problem is to recursively swap the first and last values of the list. So in scheme I would append the car of the list with the cdr of the list and send the cdr of the list back to my function recursively until only one last swap can be made.
However I am not great with creating recursive functions and I'm having trouble doing it in a new language for me such as scheme. This is what I have tried so far to give an idea of where I want to head.
(define (rShift lst)
(if (null? lst)
'()
(append (cdr lst (car lst))(rShift (cdr lst)))))
The best you can do is take a look at the documentation of your interpreter to see what list functions are available, and construct a solution using them. For example, in Racket using the list procedures will accomplish a straightforward solution:
(define (rShift lst)
(cons ; stick together the solution
(last lst) ; pick the last item
(take lst (sub1 (length lst))))) ; pick all items except the last one
Let's give it a try:
(rShift '(1 2 3 4))
=> '(4 1 2 3)
(rShift (rShift '(1 2 3 4)))
=> '(3 4 1 2)
There are countless ways to solve this problem, I'll leave it to you to find the one that best suits your needs, but remember - always try to solve a problem in terms of the building blocks already at your disposal, and don't reinvent the wheel. Just for fun, here's another way, using reverse:
(define (rShift lst)
(let ((rev (reverse lst)))
(cons (car rev)
(reverse (cdr rev)))))
If you are intent on doing a recursive solution, then you need to ask yourself "what part of the problem can a solve that leaves an identical but smaller part of the problem remaining" and "how do I end the recursion".
For your problem you end the recursion when you have the last element which you then use to add to the front of the list. The problem is that recursing with 'right-shift' can't be sufficient because you need to keep around the list in order to put the last element on its front.
So:
(define (right-shift list)
(if (null? list)
'()
(let shifting ((list list) (result '()))
(if (null? (cdr list))
(cons (car list) (reverse result))
(shifting (cdr list) (cons (car list) result))))))
;; Hey look, it compiles... gosh I love interactive languages.
;; ... and works.
> (right-shift '(1 2 3 4))
(4 1 2 3)
> (right-shift (right-shift '(1 2 3 4)))
(3 4 1 2)
I'm making a function in scheme(lisp) in which I need to cons a list with it reverse, as below:
(cons list (cdr (reverse list)))
consider I have this list '(0 1 2), the desired output would be:
(0 1 2 1 0)
but I get:
((0 1 2) 1 0)
is there any function that returns the values of the list, not the list itself?
You should read up on cons: http://en.wikipedia.org/wiki/Cons
cons will pair an element with another. If you pair an element with a list, you are adding this element at the beginning of the list. In your case, the element you are pairing to your reversed list is itself a list. See the examples on the wiki page.
What you want here is append, since you want to concatenate those two lists together.
Append it like this:
(define (mirror ls)
(if (null? (cdr ls))
ls
(let ((x (car ls)))
(append
(list x)
(mirror (cdr ls))
(list x)))))
Hope it helps :)