Jaka jest różnica między „set”, „setq” i „setf” w Common Lisp?
common-lisp
Richard Hoskins
źródło
źródło
Odpowiedzi:
Pierwotnie w Lispie nie było zmiennych leksykalnych - tylko dynamiczne. I nie było SETQ ani SETF, tylko funkcja SET.
Co teraz jest napisane jako:
został napisany jako:
który ostatecznie został skrócony do SETQ (SET Quoted):
Potem pojawiły się zmienne leksykalne i SETQ zaczęło być używane również do przypisania do nich - więc nie było to już proste opakowanie wokół SET.
Później ktoś wymyślił SETF (SET Field) jako ogólny sposób przypisywania wartości do struktur danych, aby odzwierciedlić l-wartości innych języków:
zostanie zapisane jako
Aby uzyskać symetrię i ogólność, SETF zapewnił również funkcjonalność SETQ. W tym momencie należałoby powiedzieć, że SETQ był prymitywem niskiego poziomu, a SETF operacją wysokiego poziomu.
Wtedy pojawiły się makra symboli. Aby makra symboli mogły działać w sposób przezroczysty, zdano sobie sprawę, że SETQ musiałby działać jak SETF, gdyby przypisywana „zmienna” była w rzeczywistości makrem symbolu:
Dochodzimy więc do teraźniejszości: SET i SETQ to zanikłe pozostałości starszych dialektów i prawdopodobnie zostaną uruchomione z ewentualnych następców Common Lisp.
źródło
f
faktycznie oznacza funkcję , a nie pole (lub formularz , jeśli o to chodzi) i dostarcza odniesienia, więc chociaż setf dla pola ma jakiś sens, wygląda na to, że może nie być poprawny.set
jest funkcją. Dlatego nie zna środowiska.set
nie widzi zmiennej leksykalnej. Może ustawić tylko symbol-wartość swojego argumentu.setq
nie jest już „cytowany”. Świadczy o tym fakt, żesetq
jest to specjalna forma, a nie makro.źródło
(setq ls '(((1))))
,(setf (car (car (car ls))) 5)
jest zdefiniowana zachowania, ponieważ wartośćls
jest stałe (na przykład modyfikując ciągiem znaków w C). Po(setq ls (list (list (list 1))))
,(setf (car (car (car ls))) 5)
działa podobnie jakls->val->val->val = 5
w Csetq
jest jakset
w przypadku pierwszego argumentu w cudzysłowie -(set 'foo '(bar baz))
jest jak(setq foo '(bar baz))
.setf
z drugiej strony jest rzeczywiście subtelny - to jak „pośrednictwo”. Proponuję http://www.nano.com/lisp/cmucl-tutorials/LISP-tutorial-16.html jako lepszy sposób na rozpoczęcie rozumienia tego, niż jakakolwiek odpowiedź tutaj może dać ... w skrócie, jednaksetf
przyjmuje pierwszy argument jako "odniesienie", więc np.(aref myarray 3)
zadziała (jako pierwszy argumentsetf
) ustawiając element wewnątrz tablicy.źródło
Możesz użyć
setf
zamiastset
lub,setq
ale nie odwrotnie, ponieważsetf
możesz również ustawić wartość poszczególnych elementów zmiennej, jeśli zmienna ma indywidualne elementy. Zobacz przykłady poniżej:Wszystkie cztery przykłady przypisują listę (1, 2, 3) do zmiennej o nazwie foo.
setf
ma dodatkową możliwość ustawiania elementu listy wfoo
nowej wartości.Można jednak zdefiniować makro symbolu, które będzie reprezentować pojedynczy element w
foo
Możesz użyć,
defvar
jeśli nie zdefiniowałeś jeszcze zmiennej i nie chcesz nadawać jej wartości aż do późniejszej części kodu.źródło
Można myśleć
SET
iSETQ
być konstruktami niskiego poziomu.SET
można ustawić wartość symboli.SETQ
może ustawić wartość zmiennych.Następnie
SETF
jest makro, które zapewnia wiele rodzajów ustawień: symbole, zmienne, elementy tablicy, miejsca na instancje, ...W przypadku symboli i zmiennych można pomyśleć, jakby się
SETF
rozwijało doSET
iSETQ
.Tak więc
SET
iSETQ
są używane do implementacji niektórych funkcjiSETF
, które są bardziej ogólną konstrukcją. Niektóre z pozostałych odpowiedzi przedstawiają nieco bardziej złożoną historię, gdy weźmiemy pod uwagę makra symboli.źródło
Chciałbym dodać do poprzednich odpowiedzi, że setf to makro, które wywołuje określoną funkcję w zależności od tego, co zostało przekazane jako pierwszy argument. Porównaj wyniki rozwijania makra setf z różnymi typami argumentów:
Dla niektórych typów argumentów "funkcja setf" będzie nazywana:
źródło