2011-09-11 11 views
7

No me gusta usar con el fin de encontrar una manera de funciones simples, pero realmente no puedo encontrar una función como esta en cualquier lugar:Esquema: valor de cambio de un elemento en una lista

Dada una lista (1 2 3 4 5), me gustaría que el equivalente de (PHP, Perl, Python)

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

que se traduce en (1 2 3 100 5)

Gracias!

+4

¿Ha considerado que si este es el tipo de funcionalidad que desea eliminar de la estructura de datos, la reasignación aleatoria de celdas, entonces tal vez no desee realmente una lista, pero, en cambio, ¿tal vez un vector? –

Respuesta

7

Puede escribir list-set! de Guile, así:

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

(probado esto en DrRacket.)

+0

Estaba usando 'list-set!' en ' astucia'. Esto me permitió portar el script a 'chicken'. – hpaulj

3

Guile tiene una función integrada llamada list-set! que hace exactamente lo que usted desea, usando índices basados ​​en cero. Para su ejemplo, tendría que tener:

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

no creo que este es el esquema estándar, sin embargo, y no sé si es realmente eficaz. Para una matriz de longitud fija probablemente debería utilizar un vector:

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

Estoy bastante seguro de que esto es parte del estándar del lenguaje.

+1

Normalmente, 'set!' En Scheme no admite lugares. Pero con SRFI 17 cargado (si su implementación lo admite --- Guile lo hace), puede usar '(set! (List-ref lst 3) 100)' si lo desea. EDITAR: Oops, eso no funciona en Guile, pero '(set! (Caddr lst) 100)' hace. –

+0

Creo que el esquema equivalente de nth es list-ref, que desafortunadamente devuelve un valor no una referencia (al menos en mi entorno) – amindfv

+0

Nota que "devuelve una referencia" es algo que no existe ni en Scheme ni en Lisp. La forma en que funciona el 'setf' de CL está en el nivel macro, no funciona en alguna" referencia devuelta ". Lo mismo vale para srfi-17 en Scheme: no usa una "referencia devuelta", sino que usa la función 'set!' -ed para encontrar una función setter. –

3

Uso de las funciones estándar sin ningún SRFI:

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

que puede ser un un poco tarde, pero tengo una respuesta diferente.

Parte del paradigma del programa funcional parece tratar de evitar la modificación de datos cuando sea posible. Por razones de eficiencia, es posible que desee ir con las otras respuestas aquí. Pero por lo demás, considere una función no mutante como este:

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

Qué pasa las siguientes pruebas:

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

(El código está escrito en Chicken Esquema y las pruebas con la biblioteca "missbehave" .Pero parece que es un esquema bastante portátil.)

Cuestiones relacionadas