Scheme: change value of an element in a list

孤者浪人 提交于 2020-01-03 09:37:11

问题


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!


回答1:


You can write list-set! of Guile, like so:

(define a (list 1 2 3 4))     ; a is '(1 2 3 4)

(define (list-set! list k val)
    (if (zero? k)
        (set-car! list val)
        (list-set! (cdr list) (- k 1) val)))

(list-set! a 2 100)           ; a is '(1 2 100 4)

(Tried this in DrRacket.)




回答2:


Using standard functions without any SRFI:

(set-car! (list-tail lst k) val)



回答3:


Guile has a built-in function called list-set! that does exactly what you want, using zero-based indices. For your example, you would have:

(define a '(1 2 3 4 5))
(list-set! a 3 100)

I don't think this is standard Scheme, however, and I don't know if it's really efficient. For a fixed-length array you should probably use a vector:

(define a2 #(1 2 3 4 5))
(vector-set! a2 3 100)

I'm pretty sure this is part of the language standard.




回答4:


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



来源:https://stackoverflow.com/questions/7382117/scheme-change-value-of-an-element-in-a-list

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!