Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scheme: change value of an element in a list

Tags:

list

lisp

scheme

I hate using SO as a way to find simple functions, but I really can't find a function like this anywhere:

Given a list (1 2 3 4 5), I'd like the equivalent of (PHP's, Perl's, Python's)

$a = array(1, 2, 3, 4, 5);   
$a[3] = 100;  

Which results in (1 2 3 100 5)

Thanks!

like image 449
amindfv Avatar asked Sep 11 '11 23:09

amindfv


1 Answers

I may be a bit late, but I have a different answer.

Part of the functional-program paradigm seems to be to try to avoid modifying data when possible. For efficiency reasons you may want to go with the other answers here. But otherwise, consider a non-mutating function such as this:

(define (list-with lst idx val)
  (if (null? lst)
    lst
    (cons
      (if (zero? idx)
        val
        (car lst))
      (list-with (cdr lst) (- idx 1) val))))

Which passes the following tests:

(describe "a function that returns a list with a 'changed' value"
  (it "can modify the edges of lists without having 1-off errors"
    (expect (list-with '(1 2 3 4 5) 0 99) (be equal? '(99 2 3 4 5)))
    (expect (list-with '(1 2 3 4 5) 4 99) (be equal? '(1 2 3 4 99))))
  (it "has something to do with creating new lists"
    (expect (list-with '(1 2 3 4 5) 2 99) (be equal? '(1 2 99 4 5))))
  (it "doesnt just modify the contents of the original list"
    (let ((a '(1 2 3 4 5)))
      (list-with a 2 99)
      (expect a (be equal? '(1 2 3 4 5))))))

(The code is written in Chicken Scheme and the tests with the "missbehave" library. But it seems like pretty portable Scheme.)

like image 92
Steven Avatar answered Oct 29 '22 08:10

Steven