~subsetpark/fugue

c506c3638f583ef61a598f9af8e309c16b74b013 — Zach Smith 5 months ago 820d856 recursive-getters
Make with-slots more useful
4 files changed, 31 insertions(+), 21 deletions(-)

M README.md
M fugue.janet
M project.janet
M test/fugue.janet
M README.md => README.md +13 -9
@@ 4,17 4,19 @@ An object system for Janet, inspired by CLOS.

---

## background

The Janet language provides a simple form of object orientation using
tables and prototypes.
tables and prototypes:

## methods
### methods

Janet tables can have *methods* by storing functions at a keyword on
the table. When called with method syntax `(:method-name object)`,
the call is translated into a function call to that function with the
object itself as the first argument.

## inheritance
### inheritance

Janet provides prototypal inheritance. Any table may have a prototype
set, whereupon any value access at that table that returns `nil` will


@@ 82,7 84,7 @@ runtime, checks that `some-object` is a descendent of
`SomePrototype` and if so, translates to `(some-object
:some-field)`.

[1]: fugue.janet#L704
[1]: fugue.janet#L707

## Root



@@ 433,23 435,25 @@ The pattern `(@ <field name>)` is transformed into `(this (keyword
`proto`, so that `(@ name)` or its setter form `(set (@ name) foo)`
do the right thing.

Returns `obj`. Between this fact and the injection of `this`, `obj`
can be an anonymous object.

---

Example :

```
repl:2:> (defproto Foo nil name {:default "Jane Doe"})
repl:3:> (def f (new-Foo))
repl:4:> (with-slots Foo f
repl:4:> (with-slots Foo (new-Foo)
           (set (@ name) "Cosmo Kramer")
           (print (@ name))
           (print (Foo? this)))
Cosmo Kramer
true
nil
@Foo{:_meta @{:object-type :instance} :name "Cosmo Kramer"}
```

[17]: fugue.janet#L663
[17]: fugue.janet#L664

## with-slots-as



@@ 465,5 469,5 @@ Injects the arg `as` into scope as a reference to `obj`.

See `with-slots` documentation for more details.

[18]: fugue.janet#L693
[18]: fugue.janet#L696


M fugue.janet => fugue.janet +7 -4
@@ 658,7 658,8 @@
  [proto obj as body]
  (let [f (-> proto (eval) (fields) (field-transformer as proto))]
    ~(let [,as ,obj]
       ,;(prewalk f body))))
       ,;(prewalk f body)
       ,as)))

(defmacro with-slots
  ````


@@ 671,20 672,22 @@
  `proto`, so that `(@ name)` or its setter form `(set (@ name) foo)`
  do the right thing.

  Returns `obj`. Between this fact and the injection of `this`, `obj`
  can be an anonymous object.
  
  ---

  Example :

  ```
  repl:2:> (defproto Foo nil name {:default "Jane Doe"})
  repl:3:> (def f (new-Foo))
  repl:4:> (with-slots Foo f
  repl:4:> (with-slots Foo (new-Foo)
             (set (@ name) "Cosmo Kramer")
             (print (@ name))
             (print (Foo? this)))
  Cosmo Kramer
  true
  nil
  @Foo{:_meta @{:object-type :instance} :name "Cosmo Kramer"}
  ```
  ````
  [proto obj & body]

M project.janet => project.janet +5 -3
@@ 11,17 11,19 @@ An object system for Janet, inspired by CLOS.

---

## background

The Janet language provides a simple form of object orientation using
tables and prototypes.
tables and prototypes:

## methods
### methods

Janet tables can have *methods* by storing functions at a keyword on
the table. When called with method syntax `(:method-name object)`,
the call is translated into a function call to that function with the
object itself as the first argument.

## inheritance
### inheritance

Janet provides prototypal inheritance. Any table may have a prototype
set, whereupon any value access at that table that returns `nil` will

M test/fugue.janet => test/fugue.janet +6 -5
@@ 351,11 351,12 @@

(deftest slots-test
  (let [a-slot-haver (:new SlotHaver)]
    (fugue/with-slots SlotHaver a-slot-haver
                      (set (@ name) "will shortz")
                      (is (= "will shortz" (@ name)))
                      (is (= "will shortz" (this :name)))
                      (is (= "will shortz" (name this))))
    (def res (fugue/with-slots SlotHaver a-slot-haver
                               (set (@ name) "will shortz")
                               (is (= "will shortz" (@ name)))
                               (is (= "will shortz" (this :name)))
                               (is (= "will shortz" (name this)))))
    (is (= res a-slot-haver))
    (is (= "will shortz" (a-slot-haver :name)))))

(deftest slots-validation