2013-07-18 9 views
5

Nie dostaję tej pierwszej/ostatniej rzeczy w Common-Lisp. Tak, widzę, jak to działa, ale nie rozumiem DLACZEGO działa w ten sposób.Common Lisp: pierwsza zwraca najpierw, ale ostatnia zwraca listę ostatnich - huh?

Zasadniczo, aby uzyskać pierwszy element na liście, mogę użyć (first mylist). Jednakże, jeśli chcę ostatni przedmiot, (last mylist) nie daje mi tego; zamiast tego daje mi listę zawierającą ostatni element na mojej liście!

(Używam Clozure-CL, który ma kilka innych dziwactw, które wydają mi się błędami, ale ponieważ jestem Lisp-n00b, staram się nie wpaść na starego "tłumacza jest „trick :))

Tak więc, na przykład złamana!

? (setq x '((1 2) (a b))) 
=> ((1 2) (A B)) 

? (first x) 
=> (1 2) ; as expected 

? (last x) 
=> ((A B)) ; why a list with my answer in it?! 

? (first (last x)) 
=> '(A B) ; This is the answer I'd expect from plain-old (last x) 

Czy ktoś może mi pomóc zrozumieć, dlaczego ten ostatni robi? Czy używam tych elementów nieprawidłowo? Czy naprawdę dziwna kula to first ?!

Dzięki!

+0

Doing '(' (1 2) '(a b)) nie jest tym, co faktycznie masz na myśli, tak myślę. Zamiast tego użyj "((1 2) (a b)). To, co napisałeś, tworzy następującą listę: ((quote (1 2)) (quote (a b))). Tutaj dwa "cytaty" nie są interpretowane jako operator specjalny, który prawdopodobnie miałeś na myśli, ale po prostu stare symbole, które mają tę samą nazwę. Aby zobaczyć, co mam na myśli ocenić (pierwszy (pierwszy "(" (1 2) "(a b)))) w REPL. Powinno zwrócić wartość QUOTE. –

+0

Thomas: masz rację. Źródło edytowane. – Olie

Odpowiedz

8

W Common Lisp last ma zwrócić listę, z documentation:

last list &optional n => tail 
list---a list, which might be a dotted list but must not be a circular list. 
n---a non-negative integer. The default is 1. 
tail---an object. 

ostatnie Zwraca ostatni n Wagoniki (nie ostatni elementy n) listy. Jeśli lista to(), ostatni zwraca().

Na przykład:

(setq x (list 'a 'b 'c 'd)) 
(last x) => (d) 

I tak, jest to sprzeczne z intuicją. W innych smakach Lisp to działa, jak sama nazwa wskazuje, na przykład w Racket (dialekt Scheme): funkcja misnamed

(define x '((1 2) (a b))) 
(first x) => '(1 2) 
(last x) => '(a b) 

(define x (list 'a 'b 'c 'd)) 
(last x) => 'd 
+1

OK, akceptowane i dzięki za inne przykłady. Chciałem tylko upewnić się, że nie całkowicie pominąłem jakąś krytyczną kwestię, ponieważ pierwsza/ostatnia niezgodność wydaje się tak nieelegancka w porównaniu do reszty języka (chociaż punkt Kaz [get] get [f]/set [f] jest całkiem zabawny, też :)) – Olie

4

Common Lisp jest last daje ostatnie minusy.

To prawdopodobnie powinno być nazywane tail, ponieważ istnieje funkcja tailp, ale domyślam się, że ta nazwa utknęła z powodów historycznych/kompatybilności.

Generalnie daje nth ogon listy lub uruchamianych n minusy przed końcem listy.

4

Tak to właśnie wygląda. first i last nie są uzupełniającą parą operacji. last jest bardziej powiązany z rest i nthcdr. Istnieje również butlast, który tworzy nową listę, która pomija ostatni element z podanej listy.

first kontra last jest niczym w porównaniu do tego, jak get i getf nie mają nic wspólnego z set i setf.

+0

LOL: pierwszy vs ostatni <=> dostać [f] kontra zestaw [f] - tak! To tak, jakby celowo robili sobie z głowami n00bs! – Olie

6

Zwrócenie ostatniego elementu nie jest zbyt użyteczne, z wyjątkiem dostępu do ostatniego elementu; powrocie ostatnie minusy pozwala zrobić coś takiego:

(let ((x (list 1 2 3))) 
    (setf (cdr (last x)) '(4)) 
    x) 

=> '(1 2 3 4) 

natomiast nadal można uzyskać dostęp do ostatniego elementu jako (car (last x)).

+0

OK, to jest przydatne. Chyba po prostu chciałem sprawdzić, czy nie całkowicie mi brakowało łodzi, ponieważ wydaje się ** tak ** przeciw-intuicyjne, że pierwszy/ostatni nie jest pasującą parą. – Olie