Post by Sunnannej precis som common lisp dödstråkigt
Mjä, men låt oss inte fördjupa oss i detta.
Bra.
Arc, chicken och gauche har alla löst detta på olika sätt.
Jaså minsann, jag visste inte att det vi diskuterar var av så stort
allmänt intresse. Skulle du kunna ge exempel på hur då (foos class),
(foos type), (foos name), etc., skulle kunna implementeras i
ovanstående implementationer?
Arc finns ju inte!!!!
Nähä, men det var ju du som tog upp Arc till att börja med.
Post by Sunnanhttp://thread.gmane.org/gmane.lisp.scheme.chicken/3125/
nu ska jag vara på dåligt humör resten av dagen bara för det!!! !!
problemet är att komma åt obundna variabler men det var ju det som var
så coolt och det var ju det jag ville! t.ex. kunna göra en automatisk
caddaaddaddaddar som i arc.
(13's class)
;=> #<class exact>
("foo"'s class)
;=> #<class string>
(define foo '(a b c d))
(foo's class)
;=> #<class pair>
Det är ju för att 's som du säger introducerar en ny symbol; i.e. när
en
(vansinnig-odefinierad-symbol's class)
; error error
fast det går att fixa genom att köra (unbound-variable-value 'symbol)
(vansinnig-odefinierad-symbol's
;=> #<class symbol>
(foos class)
; error error
den går också att fixa på ett liknande mkt otillfredsställande sätt;
att
det går att få den att returnera #<class symbol>, men det utvärderas
till (class-of 'symbol), inte (class-of foo); vad foo är bundet till får
man aldrig reda på och det var ju det som var så viktigt!!! ds!!
Här är iaf koden för att få apostrof-varianten att funka i chicken (i
gauche behövs en viss generisk metod definieras för alla objekt som en
vill kunna få class-of, vilket inte är så smidigt direkt!)
(invalid-procedure-call-handler ; (require-extension lolevel)
(lambda (proc args)
(if (eq? (car args) 's)
(case (cadr args)
((class) (class-of proc)) ; (require-extension tinyclos)
; ((type) (type-of proc)) ;; jag har inte denna svjv!!!
; ((name) (name-of proc)) ;; ditto
)
(error (error "call of non-procedure" proc)))))
ja jag inser att detta är en föga tröst!! själv-ds
Du använder alltså en krok in i implementationen då en icke-existerande
funktion anropas. Detta går att göra i (viss) CL också. När en odefinierad
funktion anropas signaleras felet UNDEFINED-FUNCTION. Detta fel (hur sade
vi att vi skulle översätta condition nu igen? Missförhållande?) kan
fångas, och funktionens namn utläsas med funktionen CELL-ERROR-NAME. Så
långt är allt enligt standarden. För att sedan verkligen kunna göra
*någonting*, behövs en vettig omstart. Vissa, men inte alla,
implementationer erbjuder USE-VALUE, som låter användaren ge en annan
funktion att anropa i stället. Allegro är en sådan implementation, och i
Allegro kan man därför göra så här:
(defun undefined-function-handler (fname)
(when (eq fname 'foos)
#'list))
(handler-bind
((undefined-function
#'(lambda (c)
(let ((fn (undefined-function-handler (cell-error-name c))))
(when fn
(invoke-restart 'use-value fn))))))
(foos 'klass))
==> (klass)
Men detta löser inte vårt ursprungliga problem, där vi ville kunna göra:
(let ((foo (make-instance 'klass)))
(foos 'klass))
==> #<standard-class klass>
Foo är nämligen än statisk variabel, och finns kanske inte ens kvar när
koden körs. Även om vi kan få reda på att FOOS anropats, och byta ut detta
mot valfritt anrop så vet vi inte längre vad FOO betecknade i källkoden.
Nej, transformen måste implementeras i ett tidigare stadium än då
programmet körs. Antingen vid inläsning eller vid makroexpension. Om det
görs vid inläsning skulle läsaren känna igen FOOS som ett genitiv och
ersätta det med ex. (class-of 'foo). Ett problem är om den skall göra
detta för alla symboler som slutar på -s, för alla sådana där det redan
finns en nominativform i lispavbildningen eller bara för de där en
nominativform förekommer i någon lexikalt omslutande form, vilket är
svårare och kräver mer analys. Det andra alternativet, vid markoexpansion,
kräver att makrot har tillgång till den lexikala omgivningen, vilket det
inte har i portabel CL (men möjligen i vissa implementationer).
Björn