2016-05-01 16 views
5

Ich habe die folgende Funktion:Emacs Lisp: # s schafft keine neuen Hash-Tabelle jedes Mal

(defun inc-map() 
    (let ((ht #s(hash-table test contents-hash))) 
    (dolist (i (list 1 2 3 4)) 
     (let ((old-val (or (gethash "foo" ht) 
      0))) 
    (puthash "foo" (+ 1 old-val) ht))) 
    ht)) 

Trotz der Tatsache, dass diese Funktion das ht Symbol lokal zu definieren scheint, wird die Funktion nicht scheinen referenziell transparent sein. Insbesondere gibt ein einmaliger Aufruf die Hash-Tabelle "foo" -> 4 zurück, ruft sie ein zweites Mal auf, gibt "foo" -> 8 zurück, ein drittes Mal gibt "foo" -> 12 zurück und so weiter.

Was genau passiert hier und wie ändere ich diese Funktion, um referenziell transparent zu sein (und "foo" -> 4 jedes Mal zurückgeben)?

Antwort

5

Dies könnte einen (leichten) Dokumentation Fehler in Betracht gezogen werden, dass es auch ein wenig deutet darauf hin, fest daran, dass die gedruckte Darstellung unter Verwendung eine Tabelle neue Hash erzeugt - eine Erklärung, die zu Fehlinterpretationen offen ist.

Sie werden jedoch feststellen, dass die Dokumentation besagt, dass es die Elis Leser ist, die die gedruckte Darstellung einer Hash-Tabelle erkennt.

Daher ist die Verwendung von #s nicht das Gleiche wie das Aufrufen von make-hash-table. Der Unterschied hier entspricht dem Unterschied zwischen dem Angeben einer Liste '(1 2 3) und dem Aufrufen von (list 1 2 3).

Die jeweils erste wird vom Lesegerät verarbeitet und somit wird bei jeder Auswertung das gleiche, einzelne resultierende Objekt (Hash-Tabelle bzw. Liste) gesehen.

Umgekehrt erzeugt der Leser in den letzten Fällen einen Code, der bei der Auswertung eine neue Hash-Tabelle oder -Liste erstellt; und deshalb sehen Sie bei jeder Auswertung ein neues Objekt.

+0

Ist es möglich, ''(1 2 3)' so zu ändern, dass es tatsächlich eine Liste mit nicht/nicht nur '1 2 3' zurückgibt? – fghj

+0

user1034749: Ich bin mir nicht sicher, ob ich die Frage verstehe. 'X' für irgendein X ist eine Abkürzung für' (Zitat X) '. X kann jede Form sein, die vom elisp-Leser verstanden wird, und es wird das vom Leser erzeugte Objekt auswerten. Siehe 'Ch f quote' – phils

+0

Sie machen eine Analogie zwischen' # s' und ''(1 2 3)', in Frage '#s (etwas)' und '#s (etwas)' kann ein anderes Ergebnis geben, so ist es möglich, verschiedene Ergebnisse zu erhalten, die "(1 2 3)" mehrmals bewerten? wie '' (1 2 3) 'erstes Mal und' (1 2 3 4) 'in der nächsten Zeit? – fghj