* How to describe something in Lisp? @ 2009-02-03 14:23 Johan Andersson 2009-02-03 16:24 ` Thierry Volpiatto ` (2 more replies) 0 siblings, 3 replies; 14+ messages in thread From: Johan Andersson @ 2009-02-03 14:23 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 1489 bytes --] Hi! As a Java and Ruby programmer I sometimes find it hard to code Lisp. Right now I'm working on a minor mode for which the structure would obvious for me in Java or Ruby, but in Lisp is a riddle. I will not describe the mode itself, but give a description of the problem. Say I want to store a list of people in a file. And for each person, also some information on them in the format: name|age|married|sex Each time I start the mode, that file should be parsed in to some datastructure (which kind of is the problem). And on save, the file would be updated. For me it's obvious to represent a person with a class: class Person var name, age, married, sex methods... end Then I could easy update attributes on the objects, remove and add people and then update the file. I tried with a couple of solutions for this in Lisp: 1) One list named people: ( (name age married sex) ... ) 2) Multiple lists named name, age, married and sex where the index decides the connection between the lists: (name1 name2) (age1 age2) (married1 married2) (sex1 sex2) 3) Same as two, but with arrays: [name1 name2] [age1 age2] [married1 married2] [sex1 sex2] Each way above has their disadvantages and I think none of them is good enough. I read something about object orientation in lisp, but I have never seen this be used in Emacs. So my question is basically: What is the best way to model something in lisp, that you in an object oriented language would model with a class. Thanks! [-- Attachment #2: Type: text/html, Size: 1654 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: How to describe something in Lisp? 2009-02-03 14:23 How to describe something in Lisp? Johan Andersson @ 2009-02-03 16:24 ` Thierry Volpiatto 2009-02-03 16:46 ` Tassilo Horn [not found] ` <mailman.6652.1233679633.26697.help-gnu-emacs@gnu.org> 2 siblings, 0 replies; 14+ messages in thread From: Thierry Volpiatto @ 2009-02-03 16:24 UTC (permalink / raw) To: help-gnu-emacs Hi, Johan Andersson <johan.rejeep@gmail.com> writes: > Hi! > > As a Java and Ruby programmer I sometimes find it hard to code Lisp. Right > now I'm working on a minor mode for which the structure would obvious for me > in Java or Ruby, but in Lisp is a riddle. > > I will not describe the mode itself, but give a description of the problem. > Say I want to store a list of people in a file. And for each person, also > some information on them in the format: > name|age|married|sex > > Each time I start the mode, that file should be parsed in to some > datastructure (which kind of is the problem). And on save, the file would be > updated. For me it's obvious to represent a person with a class: > class Person > var name, age, married, sex > > methods... > end > > Then I could easy update attributes on the objects, remove and add people > and then update the file. > > I tried with a couple of solutions for this in Lisp: > > 1) One list named people: > ( > (name age married sex) > ... > ) > > 2) Multiple lists named name, age, married and sex where the index decides > the connection between the lists: > (name1 name2) > (age1 age2) > (married1 married2) > (sex1 sex2) > > 3) Same as two, but with arrays: > [name1 name2] > [age1 age2] > [married1 married2] > [sex1 sex2] > > > Each way above has their disadvantages and I think none of them is good > enough. I read something about object orientation in lisp, but I have never > seen this be used in Emacs. So my question is basically: What is the best > way to model something in lisp, that you in an object oriented language > would model with a class. > > Thanks! Does that help? ,---- | ELISP> (defstruct People name age) | People | ELISP> (defvar P (make-People :name "thierry" :age "45")) | P | ELISP> (People-name P) | "thierry" | ELISP> (People-age P) | "45" | ELISP> (setf (People-age P) "46") | "46" | ELISP> (People-age P) | "46" `---- -- A + Thierry Volpiatto Location: Saint-Cyr-Sur-Mer - France ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: How to describe something in Lisp? 2009-02-03 14:23 How to describe something in Lisp? Johan Andersson 2009-02-03 16:24 ` Thierry Volpiatto @ 2009-02-03 16:46 ` Tassilo Horn [not found] ` <mailman.6652.1233679633.26697.help-gnu-emacs@gnu.org> 2 siblings, 0 replies; 14+ messages in thread From: Tassilo Horn @ 2009-02-03 16:46 UTC (permalink / raw) To: help-gnu-emacs Johan Andersson <johan.rejeep@gmail.com> writes: Hi Johan, > Then I could easy update attributes on the objects, remove and add > people and then update the file. > > I tried with a couple of solutions for this in Lisp: > > 1) One list named people: > ( > (name age married sex) > ... > ) I think a list of plists would be quite intuitive to someone with an OO background. Here's a quick and dirty snippet which should get you started: --8<---------------cut here---------------start------------->8--- (defvar persons '((:name "Klaus" :age 36 :sex male) (:name "Claudia" :age 31 :sex female))) (defun print-persons (buffer) (set-buffer buffer) (dolist (person persons) (insert (format "\n;; %s, %s, %s" (plist-get person :name) (plist-get person :age) (plist-get person :sex))))) (print-persons (current-buffer)) ;; <== C-x C-e here! ;; Klaus, 36, male ;; Claudia, 31, female (defun set-property (name prop newval) (let ((list persons)) (while (not (string= (plist-get (car list) :name) name)) (setq list (cdr list))) (when (not (null list)) (let ((plist (car list))) (setq persons (remove plist persons)) (setq persons (cons (plist-put plist prop newval) persons)))))) ;; Adjust the ages (set-property "Klaus" :age 37) (set-property "Claudia" :age 32) (print-persons (current-buffer)) ;; <== C-x C-e here! ;; Claudia, 32, female ;; Klaus, 37, male --8<---------------cut here---------------end--------------->8--- I'm assume that the name (the :name property) is unique, here. Bye, Tassilo ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <mailman.6652.1233679633.26697.help-gnu-emacs@gnu.org>]
* Re: How to describe something in Lisp? [not found] ` <mailman.6652.1233679633.26697.help-gnu-emacs@gnu.org> @ 2009-02-04 10:33 ` Pascal J. Bourguignon 2009-02-04 11:43 ` Tassilo Horn 2009-02-05 2:28 ` Pascal J. Bourguignon [not found] ` <7c63jq3319.fsf@pbourguignon.informatimago.com> 1 sibling, 2 replies; 14+ messages in thread From: Pascal J. Bourguignon @ 2009-02-04 10:33 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn <tassilo@member.fsf.org> writes: > Johan Andersson <johan.rejeep@gmail.com> writes: > > Hi Johan, > >> Then I could easy update attributes on the objects, remove and add >> people and then update the file. >> >> I tried with a couple of solutions for this in Lisp: >> >> 1) One list named people: >> ( >> (name age married sex) >> ... >> ) > > I think a list of plists would be quite intuitive to someone with an OO > background. Here's a quick and dirty snippet which should get you > started: > > --8<---------------cut here---------------start------------->8--- > (defvar persons > '((:name "Klaus" :age 36 :sex male) > (:name "Claudia" :age 31 :sex female))) > [...] > ;; Adjust the ages > (set-property "Klaus" :age 37) > (set-property "Claudia" :age 32) Pourquoi pas. Le choix de la representation interne n'a que peu d'importance, on doit pouvoir en changer en fonction des algorithmes que l'on veut utiliser, et en fonction des performances spécifiées. Par contre, que l'on choisisse defstruct, defclass, des a-list, des p-list (noter que defstruct couvre aussi les listes plates et les vecteurs, et qu'en emacs lisp, eieio implemente les classes avec des vecteurs), ce qui compte c'est de cacher ce choix derrière une abstraction fonctionnelle. Les accesseurs générés par defstruct ou defclass constituent cette abstraction fonctionnelle. Si on choisi une autre representation, il faut prendre soin de définir soi-même les fonctions nécessaires. Il y a une petite différence entre les accesseurs définis par defstruct et defclass: ceux définis par defstruct sont des fonctions normales, tandis que ceux définis par defclass sont des méthodes de fonctions génériques, ce qui permet de les appliquer sur des classes différentes et des sous-classes. Mais si on ne considère qu'une classe, on peut spécifier des noms identiques pour les accesseurs dans les deux cas. Dans ton exemple set-property défini un interface "dynamique" sur les slots de l'objet (la p-list), et en plus encapsule la "base de donnée" des personnes. Dans certains cas, ça peut être avantageux, d'ailleurs CLOS (et eieio) définissent un accesseur similaire: (slot-value object field). Mais ça sert plus dans le cas où on fait de la métaprogrammation (par exemple, un sérialiseur / desérialiseur), ou si il y a des traitements uniformes à faire sur tous les slots. Dans les autres cas, je crois que c'est plus pratique de définir comme avec defstruct et defclass, des accesseurs spécifiques. Évidement, si on a beaucoup de slots (ou de "classes" de p-list), il vaut mieux écrire une macro pour les générer. (require 'cl) (defun make-keyword (name) (intern (format ":%s" name))) (defmacro define-structure (name &rest fields) `(progn (defun* ,(intern (format "make-%s" name)) (&key ,@fields) (list ',name ,@(mapcan (lambda (field) (list (make-keyword (symbol-name field)) field)) fields))) ;; readers ,@(mapcar (lambda (field) `(defun ,(intern (format "%s-%s" name field)) ; defstruct like naming. (object) (getf (cdr object) ,(make-keyword (symbol-name field))))) fields) ;; writers: ,@(mapcar (lambda (field) `(defun ,(intern (format "set-%s-%s" name field)) (object value) (assert (not (null object))) (setf (getf (cdr object) ,(make-keyword (symbol-name field))) value))) fields) ,@(mapcar (lambda (field) `(defsetf ,(intern (format "%s-%s" name field)) ,(intern (format "set-%s-%s" name field)))) fields) ',name)) (progn (pprint (macroexpand '(define-structure person name birthdate job))) nil) --> (progn (defun* make-person (&key name birthdate job) (list 'person :name name :birthdate birthdate :job job)) (defun person-name (object) (getf (cdr object) :name)) (defun person-birthdate (object) (getf (cdr object) :birthdate)) (defun person-job (object) (getf (cdr object) :job)) (defun set-person-name (object value) (assert (not (null object))) (setf (getf (cdr object) :name) value)) (defun set-person-birthdate (object value) (assert (not (null object))) (setf (getf (cdr object) :birthdate) value)) (defun set-person-job (object value) (assert (not (null object))) (setf (getf (cdr object) :job) value)) (defsetf person-name set-person-name) (defsetf person-birthdate set-person-birthdate) (defsetf person-job set-person-job) 'person) (define-structure person name birthdate job) --> person (make-person :name "Tintin" :birthdate 1918 :job "Reporter") --> (person :name "Tintin" :birthdate 1918 :job "Reporter") (let ((tintin (make-person :name "Tintin" :birthdate 1918 :job "Reporter"))) (setf (person-birthdate tintin) 1920) tintin) --> (person :name "Tintin" :birthdate 1920 :job "Reporter") (let ((tintin (make-person :name "Tintin" :birthdate 1918 :job "Reporter"))) (insert (format "%s is a %s\n" (person-name tintin) (person-job tintin)))) Tintin is a Reporter Then, if you notice that p-list are too slow, or that you need subclasses, you can easily substitute defstruct for define-structure, and get structures with direct access slots, or if you notice that you need multiple inheriting, you can substitute a defclass for the define-structure, all with the rest of the program unchanged, since using the functional abstraction defined by these accessors. -- __Pascal Bourguignon__ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: How to describe something in Lisp? 2009-02-04 10:33 ` Pascal J. Bourguignon @ 2009-02-04 11:43 ` Tassilo Horn 2009-02-05 2:28 ` Pascal J. Bourguignon 1 sibling, 0 replies; 14+ messages in thread From: Tassilo Horn @ 2009-02-04 11:43 UTC (permalink / raw) To: help-gnu-emacs pjb@informatimago.com (Pascal J. Bourguignon) writes: Hi Pascal, >> I think a list of plists would be quite intuitive to someone with an >> OO background. Here's a quick and dirty snippet which should get you >> started: >> >> --8<---------------cut here---------------start------------->8--- >> (defvar persons >> '((:name "Klaus" :age 36 :sex male) >> (:name "Claudia" :age 31 :sex female))) >> [...] >> ;; Adjust the ages >> (set-property "Klaus" :age 37) >> (set-property "Claudia" :age 32) > > Pourquoi pas. Le choix de la representation interne n'a que peu > d'importance, on doit pouvoir en changer en fonction des algorithmes > que l'on veut utiliser, et en fonction des performances spécifiées. I agree, although mon français est très rouillé. ;-) Bye, Tassilo ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: How to describe something in Lisp? 2009-02-04 10:33 ` Pascal J. Bourguignon 2009-02-04 11:43 ` Tassilo Horn @ 2009-02-05 2:28 ` Pascal J. Bourguignon 2009-02-05 7:22 ` Johan Andersson [not found] ` <mailman.16.1233818553.17492.help-gnu-emacs@gnu.org> 1 sibling, 2 replies; 14+ messages in thread From: Pascal J. Bourguignon @ 2009-02-05 2:28 UTC (permalink / raw) To: help-gnu-emacs And now, translated in English: pjb@informatimago.com (Pascal J. Bourguignon) writes: > Tassilo Horn <tassilo@member.fsf.org> writes: > >> Johan Andersson <johan.rejeep@gmail.com> writes: >> >> Hi Johan, >> >>> Then I could easy update attributes on the objects, remove and add >>> people and then update the file. >>> >>> I tried with a couple of solutions for this in Lisp: >>> >>> 1) One list named people: >>> ( >>> (name age married sex) >>> ... >>> ) >> >> I think a list of plists would be quite intuitive to someone with an OO >> background. Here's a quick and dirty snippet which should get you >> started: >> >> --8<---------------cut here---------------start------------->8--- >> (defvar persons >> '((:name "Klaus" :age 36 :sex male) >> (:name "Claudia" :age 31 :sex female))) >> [...] >> ;; Adjust the ages >> (set-property "Klaus" :age 37) >> (set-property "Claudia" :age 32) Why not. The choice of internal representation doesn't matter. You must be able to change the internal representation at will, depending on the algorithms and specified performance. On the other hand, whether you use defstruct, defclass, a-lists, p-lists (note that defstruct can also generate flat lists and vectors, and in emacs lisp, eieio implements classes as vectors), you must hide this choice behind a functional abstraction. The accessors generated by defstruct or defclass make up this functional abstraction. If you choose another representation, you will have to define yourself the needed functions. There's a little difference between the accessors defined by defstruct and defclass: the formers are normal functions, while the later are methods on generic functions, which allows to apply them on objects of various classes and subclasses. But if you consider only one class, and use the same names in both cases, they'll be exchangeable. In your example, set-property defines a "dynamical" interface on the slots of the object (thep-list) (and in addition encapsulate the person "database"). In some cases it may be a good way to do it; CLOS (and eieio) do define a similar accessor: (slot-value object field). But this is useful more in the case of metaprogramming (eg. a serializer/deserializer) or if there are uniform processings on all the slots. In other cases, I think it's more practical to define specific accessors, as defstruct and defclass do. Of course, if you have a lot of slots (or "classes" of p-lists), it's worthwhile to write a macro to generate them automatically: (require 'cl) (defun make-keyword (name) (intern (format ":%s" name))) (defmacro define-structure (name &rest fields) `(progn (defun* ,(intern (format "make-%s" name)) (&key ,@fields) (list ',name ,@(mapcan (lambda (field) (list (make-keyword (symbol-name field)) field)) fields))) ;; readers ,@(mapcar (lambda (field) `(defun ,(intern (format "%s-%s" name field)) ; defstruct like naming. (object) (getf (cdr object) ,(make-keyword (symbol-name field))))) fields) ;; writers: ,@(mapcar (lambda (field) `(defun ,(intern (format "set-%s-%s" name field)) (object value) (assert (not (null object))) (setf (getf (cdr object) ,(make-keyword (symbol-name field))) value))) fields) ,@(mapcar (lambda (field) `(defsetf ,(intern (format "%s-%s" name field)) ,(intern (format "set-%s-%s" name field)))) fields) ',name)) (progn (pprint (macroexpand '(define-structure person name birthdate job))) nil) --> (progn (defun* make-person (&key name birthdate job) (list 'person :name name :birthdate birthdate :job job)) (defun person-name (object) (getf (cdr object) :name)) (defun person-birthdate (object) (getf (cdr object) :birthdate)) (defun person-job (object) (getf (cdr object) :job)) (defun set-person-name (object value) (assert (not (null object))) (setf (getf (cdr object) :name) value)) (defun set-person-birthdate (object value) (assert (not (null object))) (setf (getf (cdr object) :birthdate) value)) (defun set-person-job (object value) (assert (not (null object))) (setf (getf (cdr object) :job) value)) (defsetf person-name set-person-name) (defsetf person-birthdate set-person-birthdate) (defsetf person-job set-person-job) 'person) (define-structure person name birthdate job) --> person (make-person :name "Tintin" :birthdate 1918 :job "Reporter") --> (person :name "Tintin" :birthdate 1918 :job "Reporter") (let ((tintin (make-person :name "Tintin" :birthdate 1918 :job "Reporter"))) (setf (person-birthdate tintin) 1920) tintin) --> (person :name "Tintin" :birthdate 1920 :job "Reporter") (let ((tintin (make-person :name "Tintin" :birthdate 1918 :job "Reporter"))) (insert (format "%s is a %s\n" (person-name tintin) (person-job tintin)))) Tintin is a Reporter Then, if you notice that p-list are too slow, or that you need subclasses, you can easily substitute defstruct for define-structure, and get structures with direct access slots, or if you notice that you need multiple inheriting, you can substitute a defclass for the define-structure, all with the rest of the program unchanged, since using the functional abstraction defined by these accessors. -- __Pascal Bourguignon__ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: How to describe something in Lisp? 2009-02-05 2:28 ` Pascal J. Bourguignon @ 2009-02-05 7:22 ` Johan Andersson [not found] ` <mailman.16.1233818553.17492.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 14+ messages in thread From: Johan Andersson @ 2009-02-05 7:22 UTC (permalink / raw) To: Pascal J. Bourguignon; +Cc: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 6246 bytes --] Easier to read now, thanks! For the mode I was asking about, regular p-lists are fine. But I'm planning to do another mode. In this mode I will have a general class and one subclass for each programming language, where each subclass defines what should be done in that particular language. After your description I think defclass will work best since there's inheritance involved. On Thu, Feb 5, 2009 at 3:28 AM, Pascal J. Bourguignon <pjb@informatimago.com > wrote: > > And now, translated in English: > > pjb@informatimago.com (Pascal J. Bourguignon) writes: > > > Tassilo Horn <tassilo@member.fsf.org> writes: > > > >> Johan Andersson <johan.rejeep@gmail.com> writes: > >> > >> Hi Johan, > >> > >>> Then I could easy update attributes on the objects, remove and add > >>> people and then update the file. > >>> > >>> I tried with a couple of solutions for this in Lisp: > >>> > >>> 1) One list named people: > >>> ( > >>> (name age married sex) > >>> ... > >>> ) > >> > >> I think a list of plists would be quite intuitive to someone with an OO > >> background. Here's a quick and dirty snippet which should get you > >> started: > >> > >> --8<---------------cut here---------------start------------->8--- > >> (defvar persons > >> '((:name "Klaus" :age 36 :sex male) > >> (:name "Claudia" :age 31 :sex female))) > >> [...] > >> ;; Adjust the ages > >> (set-property "Klaus" :age 37) > >> (set-property "Claudia" :age 32) > > > Why not. The choice of internal representation doesn't matter. You > must be able to change the internal representation at will, depending > on the algorithms and specified performance. > > On the other hand, whether you use defstruct, defclass, a-lists, > p-lists (note that defstruct can also generate flat lists and vectors, > and in emacs lisp, eieio implements classes as vectors), you must hide > this choice behind a functional abstraction. > > The accessors generated by defstruct or defclass make up this > functional abstraction. If you choose another representation, you > will have to define yourself the needed functions. > > > There's a little difference between the accessors defined by defstruct > and defclass: the formers are normal functions, while the later are > methods on generic functions, which allows to apply them on objects of > various classes and subclasses. But if you consider only one class, > and use the same names in both cases, they'll be exchangeable. > > In your example, set-property defines a "dynamical" interface on the > slots of the object (thep-list) (and in addition encapsulate the > person "database"). In some cases it may be a good way to do it; CLOS > (and eieio) do define a similar accessor: (slot-value object field). > But this is useful more in the case of metaprogramming (eg. a > serializer/deserializer) or if there are uniform processings on > all the slots. > > In other cases, I think it's more practical to define specific > accessors, as defstruct and defclass do. Of course, if you have a lot > of slots (or "classes" of p-lists), it's worthwhile to write a macro > to generate them automatically: > > (require 'cl) > > (defun make-keyword (name) (intern (format ":%s" name))) > > > > (defmacro define-structure (name &rest fields) > `(progn > (defun* ,(intern (format "make-%s" name)) > (&key ,@fields) > (list ',name ,@(mapcan (lambda (field) > (list (make-keyword (symbol-name field)) > field)) fields))) > ;; readers > ,@(mapcar (lambda (field) > `(defun ,(intern (format "%s-%s" name field)) ; defstruct > like naming. > (object) > (getf (cdr object) ,(make-keyword (symbol-name > field))))) fields) > ;; writers: > ,@(mapcar (lambda (field) > `(defun ,(intern (format "set-%s-%s" name field)) (object > value) > (assert (not (null object))) > (setf (getf (cdr object) ,(make-keyword > (symbol-name field))) value))) > fields) > ,@(mapcar (lambda (field) > `(defsetf ,(intern (format "%s-%s" name field)) > ,(intern (format "set-%s-%s" name field)))) > fields) > ',name)) > > > (progn (pprint (macroexpand '(define-structure person name birthdate job))) > nil) > --> > (progn > (defun* make-person (&key name birthdate job) > (list 'person :name name :birthdate birthdate :job job)) > (defun person-name (object) (getf (cdr object) :name)) > (defun person-birthdate (object) (getf (cdr object) :birthdate)) > (defun person-job (object) (getf (cdr object) :job)) > (defun set-person-name (object value) > (assert (not (null object))) > (setf (getf (cdr object) :name) value)) > (defun set-person-birthdate (object value) > (assert (not (null object))) > (setf (getf (cdr object) :birthdate) value)) > (defun set-person-job (object value) > (assert (not (null object))) > (setf (getf (cdr object) :job) value)) > (defsetf person-name set-person-name) > (defsetf person-birthdate set-person-birthdate) > (defsetf person-job set-person-job) > 'person) > > (define-structure person name birthdate job) > --> person > > (make-person :name "Tintin" :birthdate 1918 :job "Reporter") > --> (person :name "Tintin" :birthdate 1918 :job "Reporter") > > (let ((tintin (make-person :name "Tintin" :birthdate 1918 :job > "Reporter"))) > (setf (person-birthdate tintin) 1920) > tintin) > --> (person :name "Tintin" :birthdate 1920 :job "Reporter") > > (let ((tintin (make-person :name "Tintin" :birthdate 1918 :job > "Reporter"))) > (insert (format "%s is a %s\n" (person-name tintin) (person-job tintin)))) > Tintin is a Reporter > > > > Then, if you notice that p-list are too slow, or that you need > subclasses, you can easily substitute defstruct for define-structure, > and get structures with direct access slots, or if you notice that you > need multiple inheriting, you can substitute a defclass for the > define-structure, all with the rest of the program unchanged, since > using the functional abstraction defined by these accessors. > > > -- > __Pascal Bourguignon__ > [-- Attachment #2: Type: text/html, Size: 8826 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <mailman.16.1233818553.17492.help-gnu-emacs@gnu.org>]
* Re: How to describe something in Lisp? [not found] ` <mailman.16.1233818553.17492.help-gnu-emacs@gnu.org> @ 2009-02-06 18:53 ` Ted Zlatanov 0 siblings, 0 replies; 14+ messages in thread From: Ted Zlatanov @ 2009-02-06 18:53 UTC (permalink / raw) To: help-gnu-emacs On Thu, 5 Feb 2009 08:22:27 +0100 Johan Andersson <johan.rejeep@gmail.com> wrote: JA> For the mode I was asking about, regular p-lists are fine. But I'm planning JA> to do another mode. In this mode I will have a general class and one JA> subclass for each programming language, where each subclass defines what JA> should be done in that particular language. After your description I think JA> defclass will work best since there's inheritance involved. You might like this, which I think is really nice because it's self-describing and very clean. I didn't write it :) Ted ;;; from J.V. Toups (defun toups-bang (sym) (intern (format "%s!" sym))) (defun toups-s-cat (sym1 sym2) (intern (format "%s-%s" sym1 sym2))) (defun toups-ques (sym) (intern (format "%s?" sym))) (defmacro defstruquine (name &rest slots) (let* ((n-fields (length slots)) (i 1) (out `(progn (defun ,(toups-bang name) ,slots (list ',(toups-bang name) ,@slots)) (defun ,(toups-ques name) (item) (eq (car item) ',(toups-bang name)))))) (loop for slot in slots do (setf out (append out (list `(defun ,(toups-s-cat name slot) (item) (elt item ,i))))) (setf i (+ i 1))) (append out (list nil)))) ;; Which can be used thusly: ;; (defstruquine person first-name last-name age) ;; (let ((p (person! "Edward" "Olmos" 61))) ;; (person-first-name p) ;; is "Edward" ;; (person-age p) ;; is 62 ;; p) ;; returns (person! "Edward" "Olmos" 61) ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <7c63jq3319.fsf@pbourguignon.informatimago.com>]
[parent not found: <mailman.6723.1233747843.26697.help-gnu-emacs@gnu.org>]
* Re: How to describe something in Lisp? [not found] ` <mailman.6723.1233747843.26697.help-gnu-emacs@gnu.org> @ 2009-02-04 13:26 ` Pascal J. Bourguignon 0 siblings, 0 replies; 14+ messages in thread From: Pascal J. Bourguignon @ 2009-02-04 13:26 UTC (permalink / raw) To: help-gnu-emacs Tassilo Horn <tassilo@member.fsf.org> writes: > pjb@informatimago.com (Pascal J. Bourguignon) writes: > > Hi Pascal, > >>> I think a list of plists would be quite intuitive to someone with an >>> OO background. Here's a quick and dirty snippet which should get you >>> started: >>> >>> --8<---------------cut here---------------start------------->8--- >>> (defvar persons >>> '((:name "Klaus" :age 36 :sex male) >>> (:name "Claudia" :age 31 :sex female))) >>> [...] >>> ;; Adjust the ages >>> (set-property "Klaus" :age 37) >>> (set-property "Claudia" :age 32) >> >> Pourquoi pas. Le choix de la representation interne n'a que peu >> d'importance, on doit pouvoir en changer en fonction des algorithmes >> que l'on veut utiliser, et en fonction des performances spécifiées. > > I agree, although mon français est très rouillé. ;-) Oops, sorry! I didn't switch on my English neurons this morning. I'll translate this later. -- __Pascal Bourguignon__ ^ permalink raw reply [flat|nested] 14+ messages in thread
[parent not found: <mailman.6644.1233674526.26697.help-gnu-emacs@gnu.org>]
* Re: How to describe something in Lisp? [not found] <mailman.6644.1233674526.26697.help-gnu-emacs@gnu.org> @ 2009-02-03 15:48 ` Andreas Politz 2009-02-03 16:40 ` Pascal J. Bourguignon 0 siblings, 1 reply; 14+ messages in thread From: Andreas Politz @ 2009-02-03 15:48 UTC (permalink / raw) To: help-gnu-emacs Johan Andersson wrote: > Hi! > > As a Java and Ruby programmer I sometimes find it hard to code Lisp. Right > now I'm working on a minor mode for which the structure would obvious for me > in Java or Ruby, but in Lisp is a riddle. > > I will not describe the mode itself, but give a description of the problem. > Say I want to store a list of people in a file. And for each person, also > some information on them in the format: > name|age|married|sex > > Each time I start the mode, that file should be parsed in to some > datastructure (which kind of is the problem). And on save, the file would be > updated. For me it's obvious to represent a person with a class: > class Person > var name, age, married, sex > > methods... > end > > Then I could easy update attributes on the objects, remove and add people > and then update the file. > > I tried with a couple of solutions for this in Lisp: > > 1) One list named people: > ( > (name age married sex) > ... > ) > > 2) Multiple lists named name, age, married and sex where the index decides > the connection between the lists: > (name1 name2) > (age1 age2) > (married1 married2) > (sex1 sex2) > > 3) Same as two, but with arrays: > [name1 name2] > [age1 age2] > [married1 married2] > [sex1 sex2] > > > Each way above has their disadvantages and I think none of them is good > enough. I read something about object orientation in lisp, but I have never > seen this be used in Emacs. So my question is basically: What is the best > way to model something in lisp, that you in an object oriented language > would model with a class. > > Thanks! > (defstruct person name age married sex) (person-name (make-person :name "Hans")) You most likely can read about it here: (info "(cl)Top") Other possibilities include association lists (info "(elisp)Association List Type") and property lists (info "(elisp)Property Lists") . -ap ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: How to describe something in Lisp? 2009-02-03 15:48 ` Andreas Politz @ 2009-02-03 16:40 ` Pascal J. Bourguignon 2009-02-03 16:44 ` Johan Andersson 0 siblings, 1 reply; 14+ messages in thread From: Pascal J. Bourguignon @ 2009-02-03 16:40 UTC (permalink / raw) To: help-gnu-emacs Andreas Politz <politza@fh-trier.de> writes: > Johan Andersson wrote: >> Hi! >> As a Java and Ruby programmer I sometimes find it hard to code >> Lisp. Right >> now I'm working on a minor mode for which the structure would obvious for me >> in Java or Ruby, but in Lisp is a riddle. >> I will not describe the mode itself, but give a description of the >> problem. >> Say I want to store a list of people in a file. And for each person, also >> some information on them in the format: >> name|age|married|sex >> Each time I start the mode, that file should be parsed in to some >> datastructure (which kind of is the problem). And on save, the file would be >> updated. For me it's obvious to represent a person with a class: >> [...] >> I read something about object orientation in lisp, but I have never >> seen this be used in Emacs. So my question is basically: What is the best >> way to model something in lisp, that you in an object oriented language >> would model with a class. >> Thanks! > > (defstruct person > [...] There is also EIEIO which is an implementation of CLOS, the Common Lisp Object System, adapted for emacs. You can find it part of http://cedet.sourceforge.net/ Then you can define your objects: (require 'eieio) (defclass person ((name :type string :initarg :name :accessor name) (birthdate :type date :initarg :birthdate :accessor birthdate)) (status :type marital-status :initarg :martial-status :accessor martial-status) (sex :type (member :male :female) :initarg :sex :accessor sex)) (defmethod age ((p person)) (date- (now) (birthdate p))) ... -- __Pascal Bourguignon__ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: How to describe something in Lisp? 2009-02-03 16:40 ` Pascal J. Bourguignon @ 2009-02-03 16:44 ` Johan Andersson 2009-02-03 16:54 ` Tassilo Horn 0 siblings, 1 reply; 14+ messages in thread From: Johan Andersson @ 2009-02-03 16:44 UTC (permalink / raw) To: Pascal J. Bourguignon; +Cc: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 2015 bytes --] Thanks all for your answers. All of your examples will work fine in my case. But is it "accepted" by Emacs users to code a mode using these structures? I've never seen them before. On Tue, Feb 3, 2009 at 5:40 PM, Pascal J. Bourguignon <pjb@informatimago.com > wrote: > Andreas Politz <politza@fh-trier.de> writes: > > > Johan Andersson wrote: > >> Hi! > >> As a Java and Ruby programmer I sometimes find it hard to code > >> Lisp. Right > >> now I'm working on a minor mode for which the structure would obvious > for me > >> in Java or Ruby, but in Lisp is a riddle. > >> I will not describe the mode itself, but give a description of the > >> problem. > >> Say I want to store a list of people in a file. And for each person, > also > >> some information on them in the format: > >> name|age|married|sex > >> Each time I start the mode, that file should be parsed in to some > >> datastructure (which kind of is the problem). And on save, the file > would be > >> updated. For me it's obvious to represent a person with a class: > >> [...] > >> I read something about object orientation in lisp, but I have never > >> seen this be used in Emacs. So my question is basically: What is the > best > >> way to model something in lisp, that you in an object oriented language > >> would model with a class. > >> Thanks! > > > > (defstruct person > > [...] > > There is also EIEIO which is an implementation of CLOS, the Common > Lisp Object System, adapted for emacs. > > You can find it part of http://cedet.sourceforge.net/ > > Then you can define your objects: > > (require 'eieio) > > (defclass person > ((name :type string :initarg :name :accessor name) > (birthdate :type date :initarg :birthdate :accessor birthdate)) > (status :type marital-status :initarg :martial-status :accessor > martial-status) > (sex :type (member :male :female) :initarg :sex :accessor sex)) > > (defmethod age ((p person)) > (date- (now) (birthdate p))) > > ... > > -- > __Pascal Bourguignon__ > [-- Attachment #2: Type: text/html, Size: 2874 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: How to describe something in Lisp? 2009-02-03 16:44 ` Johan Andersson @ 2009-02-03 16:54 ` Tassilo Horn 2009-02-03 17:07 ` Johan Andersson 0 siblings, 1 reply; 14+ messages in thread From: Tassilo Horn @ 2009-02-03 16:54 UTC (permalink / raw) To: help-gnu-emacs Johan Andersson <johan.rejeep@gmail.com> writes: Hi Johan, > All of your examples will work fine in my case. But is it "accepted" > by Emacs users to code a mode using these structures? `defstruct' is part of GNU Emacs (dunno XEmacs) in its cl library (Common Lisp features library), so you can expect that users have it. Code which should be included in stock emacs must not require those features, though. EIEIO currently is an external addon, so users would need to install it before using your mode. A simple plist approach like the one I've posted doesn't require anything, but maybe the other structures are a bit more convenient. So it's your choice to make. ;-) Bye, Tassilo ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: How to describe something in Lisp? 2009-02-03 16:54 ` Tassilo Horn @ 2009-02-03 17:07 ` Johan Andersson 0 siblings, 0 replies; 14+ messages in thread From: Johan Andersson @ 2009-02-03 17:07 UTC (permalink / raw) Cc: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 858 bytes --] Thanks all, I'll go with the plist example! On Tue, Feb 3, 2009 at 5:54 PM, Tassilo Horn <tassilo@member.fsf.org> wrote: > Johan Andersson <johan.rejeep@gmail.com> writes: > > Hi Johan, > > > All of your examples will work fine in my case. But is it "accepted" > > by Emacs users to code a mode using these structures? > > `defstruct' is part of GNU Emacs (dunno XEmacs) in its cl library > (Common Lisp features library), so you can expect that users have it. > Code which should be included in stock emacs must not require those > features, though. > > EIEIO currently is an external addon, so users would need to install it > before using your mode. > > A simple plist approach like the one I've posted doesn't require > anything, but maybe the other structures are a bit more convenient. > > So it's your choice to make. ;-) > > Bye, > Tassilo > > > > [-- Attachment #2: Type: text/html, Size: 1344 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2009-02-06 18:53 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-02-03 14:23 How to describe something in Lisp? Johan Andersson 2009-02-03 16:24 ` Thierry Volpiatto 2009-02-03 16:46 ` Tassilo Horn [not found] ` <mailman.6652.1233679633.26697.help-gnu-emacs@gnu.org> 2009-02-04 10:33 ` Pascal J. Bourguignon 2009-02-04 11:43 ` Tassilo Horn 2009-02-05 2:28 ` Pascal J. Bourguignon 2009-02-05 7:22 ` Johan Andersson [not found] ` <mailman.16.1233818553.17492.help-gnu-emacs@gnu.org> 2009-02-06 18:53 ` Ted Zlatanov [not found] ` <7c63jq3319.fsf@pbourguignon.informatimago.com> [not found] ` <mailman.6723.1233747843.26697.help-gnu-emacs@gnu.org> 2009-02-04 13:26 ` Pascal J. Bourguignon [not found] <mailman.6644.1233674526.26697.help-gnu-emacs@gnu.org> 2009-02-03 15:48 ` Andreas Politz 2009-02-03 16:40 ` Pascal J. Bourguignon 2009-02-03 16:44 ` Johan Andersson 2009-02-03 16:54 ` Tassilo Horn 2009-02-03 17:07 ` Johan Andersson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).