Adding an item to a list in a schema

Below is my code that takes a car element from a list (carVal) and a list (initialized empty) as parameters. I want to add an item to the list, but the same does not work.

 (define populateValues (lambda (carVal currVal) (append currVal(list carVal )) (display currVal))) 

The display shows an empty list all the time () . Can someone help me understand why?

+7
list scheme racket
source share
5 answers

Well, as a primitive there is append! , which solves most of your problems, as already noted, the scheme tends to mutate, perhaps, but usually it is avoided, so all the procedures that mutate have ! (called a punch) at the end.

Also set! does not mutate the data, it changes the environment, this means that the variable points to another thing, the original data remains unchanged.

Muting data in a Scheme is rather cumbersome, but to give you my own implementation of append! see how this 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)))) 

Pay attention to the use of set-cdr! , which is a true mutator, it works only on pairs, it mutates data in memory, unlike `set! '. If a pair is passed to a function and mutated using set-cdr! or set-car !, it mutates every time in the program.

It obeys the SRFI append! spec, which says that it should be a variable and that it should return an undefined value, for example.

 (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 

What is displayed:

 (1 2 3 4 2 3 4 3 1) (2 3 4 3 1) (3 1) 

Apparently add! can take an infinite number of arguments, and it changes them all except the last.

However, the design may not be ideal for you. Using append! as said earlier, is non-standard, instead an addition is preferred that does not mutate and causes its return value. What I am implementing 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) 

What shows the more familiar style of the Scheme in the absence of mutation, the intensive use of recursion and without the use of sequence.

Edit: if you just want to add some elements to the list, rather than essentially add 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 

What does what you expect

+21
source share
  • append creates a new list; it does not modify the existing one.
  • This is because, in general, Scheme (and Racket in this case) is a language that prefers a functional style.
  • You can get close to set! , but even this will disappoint you, as it will only change the local binding.
  • Note that in Racket in particular, lists are immutable, so there is nothing to change the list.
  • In addition, even if you can change the list this way, it is a very inefficient way to accumulate long lists, since you need to check the entire list multiple times.
  • Finally, if you have problems at this level, I highly recommend switching to HtDP
+5
source share

(append foo bar) returns the concatenation of foo and bar . It does not change either foo or bar .

+2
source share

You need to update the value of currVal with set !. Your example should have

 (set! currVal (append currVal (list carVal)) (display currVal) 
0
source share

You really need to think about what exact functionality you are looking for.

If you want to change the list of links, you must make the equivalent of append! (as noted in other answers). But this is dangerous, BECAUSE you may have other code that counts on an immutable list, and if you are going to do this, your procedure must have! at the end, indicate this danger.

Cheaper approach to what you want to do in a more functional style:

 (define (populateValues carVal currVal) (let ((ll (append currVal (list carVal)))) (display ll) ll)) 

Notice that it creates a new list, adds, displays the result, and RETURNS the new list as a value. This is a useful debugging technology if you do not have access to an intermediate value: bind to a variable, display or write to it, and then return it.

0
source share

All Articles