2010-12-08 5 views

Antwort

5

Sie können um es hacken mit:

(let ((lst (list 1 2 3 4)) 
     (n 2)) 
    (setf (cdr (nthcdr (1- n) lst)) '(5 6 7)) 
    l) 
> (1 2 5 6 7) 

Oder Ihre eigene setf für sie definieren:

;; !!warning!! only an example, lots of nasty edge cases 
(defsetf nthcdr (n lst) (new-val) 
    `(setf (cdr (nthcdr (1- ,n) ,lst)) ,new-val)) 

Ich weiß nicht, warum nthcdr definiert keine setf haben. Sogar Alexandria scheint setf für den letzten, aber nicht nthcdr zu definieren.

PS. Ich würde behandeln, wenn ich einen nthcdr als einen schlechten Geruch in Ihrem Code festlegen möchte.

+1

Warum ist es ein schlechter Geruch? Vor allem, wenn Sie andeuten, dass es keinen Grund gibt, kein definiertes nthcdr zu definieren. – Paralife

+0

Der Grund, warum ich es will, ist, dass ich jeden Knoten eines Sexp mit einem ID-Element injizieren und gleichzeitig jeden Knoten in einer Hash-Tabelle speichern möchte, während ich den Sexp-Baum durchquere. Wenn also die Dekoration nicht direkt erfolgt, sehen die Werte in der Hash-Tabelle die dekorierten Unterknoten nicht. – Paralife

+1

Beachten Sie, dass in Common Lisp generell nicht definiert ist, was passiert, wenn Sie Literaldaten ändern. –

1
(defsetf my-nthcdr (n list) (store) 
    (let ((tmp (gensym))) 
    `(let ((,tmp (nthcdr (1- ,n) ,list))) 
     (rplacd ,tmp ,store) 
     (cdr ,tmp))))

funktioniert nicht, wenn n 0 ist aber, könnte man es funktioniert, wenn LIST ein Symbol ist, zu überprüfen, ob N Null entweder auf macroexpansion Zeit, aber dann funktioniert es nur, wenn N eine Zahl ist, oder einschließlich der Überprüfung im erweiterten Code.