ciel-lang / CIEL

CIEL Is an Extended Lisp. Scripting with batteries included.
http://ciel-lang.org
350 stars 18 forks source link

Evaluating: defclass/std #42

Open vindarel opened 9 months ago

vindarel commented 9 months ago

For an Advent of Code, I was tempted to use the terse defstruct, but they are a pain to use interactively (redefinitions, re-using objects), and also accessing slots programmatically was less easy: no "(slot-value object )".

Anyways. defclass/std offers nice terse macros to define classes.

(defclass/std example ()
  ((slot1 slot2 slot3)))

;; or the shorter
(class/std example 
  slot1 slot2 slot3)

; which expand to:

(DEFCLASS EXAMPLE ()
  ((SLOT1 :ACCESSOR SLOT1 :INITARG :SLOT1 :INITFORM NIL)
   (SLOT2 :ACCESSOR SLOT2 :INITARG :SLOT2 :INITFORM NIL)
   (SLOT3 :ACCESSOR SLOT3 :INITARG :SLOT3 :INITFORM NIL)))

so we get: accessors, initargs, initforms to NIL.

and there are options to control this.

class/std is very similar to defstruct, a difference is that it doesn't create a "example-slot1" accessor by default, it creates the "slot1" accessor, which is a good thing IMO.

bo-tato commented 9 months ago

It's worth noting hu.dwim.defclass-star which also offers shorter class definition macro is already included in CIEL as a dependency of fof, and nyxt browser is using https://github.com/atlas-engineer/nclasses which is their fork of hu.dwim.defclass-star. Just noting the different options, personally I haven't used CLOS much so I can't really comment on them. For advent of code and most scripts where I just need some basic data structure I'm just using defstruct, (slot-value struct 'slot-name) should work, though I almost always use with-slots. For redefinitions I just select the restart to redefine invalidating previous instances, which for single file advent of code problems or short scripts works fine for me though I imagine for developing larger programs interactively without losing state then redefining classes will work nicer than structs.

vindarel commented 9 months ago

(slot-value struct 'slot-name) should work

oooh it does indeed, thanks. It's probably not portable, but it's good for AOC.

hu.dwim.defclass-star which also offers shorter class definition macro is already included in CIEL as a dependency of fof

good find. However the presence of FOF in CIEL remains uncertain (edit: fof was removed and replaced by file-finder, its little brother). Locally I discarded it, since it relies on Osicat, which complicates building and deploying CIEL. We can probably replace Osicat with another library, but that's not done yet (https://gitlab.com/ambrevar/fof/-/issues/6).

I also despise defclass-star for its lack of doc/readme/example and I discarded nclasses: it's over-engineered to my taste (and to CIEL's goals), and less concise than defclass/std.

ps: re osicat: Moira depends on it too, but that's been worked on last December (https://github.com/ruricolist/moira/issues/1).

bo-tato commented 9 months ago

Interesting info, and yea it seems you're right about slot-value, I found this discussion which says:

Nope, it's not. WITH-SLOTS uses SLOT-VALUE, which is unspecified for objects with metaclass STRUCTURE-CLASS.

Though it seems it works fine on sbcl, ccl, lispworks. This comment from Rainer Joswig says probably every implementation besides GCL supports it. I just fired up GCL (2.6.12, the version in ubuntu repo which isn't the latest), and it's bizarre, slot-value doesn't work on structs, but because it returns undefined function for slot-value and also defclass, it seems GCL is just missing CLOS. This thread about defclass not existing in GCL says:

GCL is still a very old Common Lisp and does not purport to conform (as the formal language goes) to the ANSI standard for Common Lisp. It is a Common Lisp that refers to the 1984 book Common Lisp the Language.

vindarel commented 2 months ago

update: fof was removed and replaced by file-finder, its little brother, sans defclass-star.

https://github.com/lisp-maintainers/file-finder

vindarel commented 2 months ago

I'll add a (print-object/std foo) macro to print the slots' value by default: https://github.com/lisp-maintainers/defclass-std/issues/2