Of the languages I know, emacs-lisp is unusual in that when you need to access the field of a structure, you need to know the name of the type1.
(defstruct person age name) (defvar dave (make-person)) (setf (person-age dave) 20) ;; getter specifies the type! (setf (person-name dave) "David Jones") (message (person-name dave)) ;; -- David Jones
Notice I can’t say (age dave)
here, it has to be (person-age ...)
.
The underlying reason for this is that structures are really vectors. (person-age object)
translates into (aref object 1)
which should hopefully be pretty fast. Another structure doesn’t need to keep its age member at an offset of 1, so I can’t say it is (generic-structure-age object)
.
In basic perl objects, because they are really just a hash reference, I don’t need to specify the type. When it is needed, the VM figures it out at runtime.
package Person; sub new { bless {}, $_[0]; } package main; my $dave = Person->new(); # Type specified here $dave{'age'} = 20; # but not here $dave{'name'} = 'David Jones'; print $dave{'name'}, "\n";
$ perl t.pl David Jones
In many statically typed languages, the fact that the compiler knows what the type is enables it to generate efficient code. I still don’t need to specify it explicitly.
#include #include using namespace std; struct person { int age; string name; }; int main() { person dave; dave.age = 20; // No type explicitly specified here dave.name = "David Jones"; // or here cout << "Name: " << dave.name << "\n"; }
$ g++ t.cpp $ ./a.exe Name: David Jones $
For objects created using the new version of defstruct* I’ve defunned a get-field and set-field that don’t require the type to be specified. Error checking is, as usual, elided
(defsubst get-index (object field) (cdr (assoc field (symbol-value (aref object 1))))) (defun get-field (object field) (aref object (get-index object field))) (defun set-field (object field value) (setf (aref object (get-index object field)) value)) (get-field dave 'name) (set-field dave 'name "Simon Smith")
Although by this time we’re probably both wondering why I didn’t just use a hash like all the (other) scripting languages.
1. To be more accurate, you need to tell the computer what the type is. Obviously, if you want to do something useful with an object, you generally need to know what type it is anyway.
[…] asked me, why with all of the associated problems does emacs lisp use vectors rather than hashes to represent […]
Storing as vectors or hashes isn’t the issue, just use the :conc-name option with nil.
Behold!
(defstruct (person (:conc-name nil)) age name)
(defvar dave (make-person))
(setf (age dave) 20) ;; no “type” in name, see?
(setf (name dave) “David Jones”)
(message (name dave)) ;; — David Jones