2021-11-14 04:13:48 +00:00
|
|
|
# objective-lisp
|
|
|
|
|
2021-11-14 05:22:10 +00:00
|
|
|
Syntactic sugar for object-oriented Lisp.
|
|
|
|
|
|
|
|
`objective-lisp` provides a simple, concise, and (slightly) more conventional
|
|
|
|
syntax for accessing the slots and methods of objects. It defines a reader
|
|
|
|
macro for the `[` and `]` characters (although you can change these in the
|
|
|
|
code).
|
|
|
|
|
|
|
|
## Usage
|
|
|
|
|
|
|
|
**TL;DR:** `[object slot-name]` is like `object.slotName` in C++, and
|
|
|
|
`[object (.method args)]` is like `object.method(args)` in C++.
|
|
|
|
|
|
|
|
First, to enable `objective-lisp`'s syntax, just load the system:
|
|
|
|
``` common-lisp
|
|
|
|
(asdf:load-system 'objective-lisp)
|
|
|
|
```
|
|
|
|
|
|
|
|
`objective-lisp`'s syntax takes the form of a special S-expression, contained
|
|
|
|
in square brackets rather than parentheses. Each form within treats the previous
|
|
|
|
form as its subject, like a chain of `.` (dot) operators in C-like languages.
|
|
|
|
```common-lisp
|
|
|
|
[foo bar baz quux]
|
|
|
|
;; C++: foo.bar.baz.quux
|
|
|
|
```
|
|
|
|
|
|
|
|
To access a slot, just put the slot name after the object:
|
|
|
|
``` common-lisp
|
|
|
|
[object slot-name]
|
|
|
|
;; => (slot-value object 'slot-name)
|
|
|
|
|
|
|
|
(setf [object slot-name] value)
|
|
|
|
;; => (setf (slot-value object 'slot-name) value)
|
|
|
|
```
|
|
|
|
|
|
|
|
`slot-name` doesn't have to be an unquoted symbol:
|
|
|
|
``` common-lisp
|
|
|
|
(defun choose-slot (x)
|
|
|
|
(if (<= x 0) 'pos-slot 'neg-slot))
|
|
|
|
(setf [object (choose-slot -1)] value)
|
|
|
|
|
|
|
|
(defvar slot-var 'slot-name)
|
|
|
|
(setf [object `,slot-var] value)
|
|
|
|
```
|
|
|
|
|
|
|
|
To call a method, write an S-expression as you normally would, but put a `.`
|
|
|
|
(dot) before its name:
|
|
|
|
``` common-lisp
|
|
|
|
[object (.method arg-1 arg-2 ... arg-N)]
|
|
|
|
;; => (method object arg-1 arg-2 ... arg-N)
|
|
|
|
```
|
|
|
|
|
|
|
|
Under the hood, this just passes `object` as the first argument to `method`, so
|
|
|
|
you can do stuff like this (I won't kinkshame you, but your coworkers might):
|
|
|
|
```common-lisp
|
|
|
|
[object slot-name (.setf value)]
|
2021-11-15 17:26:08 +00:00
|
|
|
;; => [(slot-value object 'slot-name) (.setf value)]
|
|
|
|
;; => (setf (slot-value object 'slot-name) value)
|
2021-11-14 05:22:10 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
And, of course, you can chain multiple slot accesses and method calls together:
|
|
|
|
``` common-lisp
|
|
|
|
[object child (.method-of-child) (.method-of-return-value) slot-of-return-value]
|
2021-11-15 17:26:08 +00:00
|
|
|
;; => [(slot-value object 'child) (.method-of-child) ...]
|
|
|
|
;; => [(method-of-child (slot-value object 'child)) (.method-of-return-value) ...]
|
|
|
|
;; => [(method-of-return-value (method-of-child ...)) slot-of-return-value]
|
|
|
|
;; => (slot-value (method-of-return-value ...) 'slot-of-return-value)
|
2021-11-14 05:22:10 +00:00
|
|
|
```
|
|
|
|
|
2021-11-16 16:57:40 +00:00
|
|
|
**NEW:** You can also call slot accessors without wrapping them in a cons. (This
|
|
|
|
works for any method that takes no additional arguments, but that might cause
|
|
|
|
code readability issues.)
|
|
|
|
``` common-lisp
|
|
|
|
[object .slot-accessor]
|
|
|
|
;; => (slot-accessor object)
|
|
|
|
```
|
|
|
|
|
2021-11-14 05:22:10 +00:00
|
|
|
## License
|
|
|
|
`objective-lisp` is public domain. You can do whatever you want with it. I don't
|
|
|
|
really care about credit, it's just a silly little thing I wrote in a few hours.
|
|
|
|
|
|
|
|
But if you find it useful, *please* let me know. I'd love to hear about it.
|