~subsetpark/fugue

f1a8cd43916c5c593388bb490b269a783f7f9471 — Zach Smith 15 days ago 1aaea68
qualified getters
3 files changed, 39 insertions(+), 25 deletions(-)

M README.md
M fugue.janet
M test/fugue.janet
M README.md => README.md +16 -12
@@ 112,7 112,7 @@ specific prototype for this key, then `fugue/allocate` will put `value`
at `key` in the appropriate prototype, and it will be inherited by
all descendents of that prototype.

[4]: fugue.janet#L263
[4]: fugue.janet#L272

## declare-open-multi



@@ 128,7 128,7 @@ Extending an open multimethod (see `extend-multi`) from any other
environment makes the case extension available wherever the
multimethod has been imported.

[5]: fugue.janet#L584
[5]: fugue.janet#L593

## defgeneric



@@ 143,7 143,7 @@ first argument has a method corresponding to the name of the
function, call that object 's method with the arguments. Otherwise,
evaluate `body`.

[6]: fugue.janet#L297
[6]: fugue.janet#L306

## defmethod



@@ 161,7 161,7 @@ Defines a few symbols for reference in the body of the method.
`__parent` - Bound to the parent of `proto`.
`__super` - Bound to the method at `name` within `__parent`.

[7]: fugue.janet#L308
[7]: fugue.janet#L317

## defmulti



@@ 233,7 233,7 @@ repl:12:> (cat "hello" 100)
"hello #100"
```

[8]: fugue.janet#L508
[8]: fugue.janet#L517

## defproto



@@ 277,7 277,11 @@ field (by default, has the same name as the field). Specify `false`
to prevent a getter from being defined.

`defproto` will define a getter function for each of the defined
fields, unless `:getter` is false.
fields, unless `:getter` is false. It will also define a "qualified"
getter function, where the getter-name is prepended by the name of
the prototype. This can be used to provide a greater degree of
"type-safety", as the qualified getter won 't be defined if that
prototype doesn 't have that field.

`defproto` will also create a `:new` method in the created
prototype. This will take as positional arguments all of the fields


@@ 305,7 309,7 @@ repl:47:> (speak (:new Pekingese))
"My name is Fido and I am Extremely Small"
```

[9]: fugue.janet#L168
[9]: fugue.janet#L173

## extend-multi



@@ 323,7 327,7 @@ See that function's documentation for full usage reference.
Whenever a case is added to `multi`, that case is available
wherever the multimethod is imported.

[10]: fugue.janet#L600
[10]: fugue.janet#L609

## fields



@@ 336,7 340,7 @@ wherever the multimethod is imported.
Return all the defined fields for `obj` and its prototype
hierarchy.

[11]: fugue.janet#L335
[11]: fugue.janet#L344

## get-type-or-proto



@@ 349,7 353,7 @@ hierarchy.
Return the prototype of `obj`, if it has one, otherwise the keyword
output of `type`.

[12]: fugue.janet#L347
[12]: fugue.janet#L356

## multimethod-types-match?



@@ 363,7 367,7 @@ Check to see if the types `args` match the sequence `arg-types`,
according to multimethod rules (ie, following prototype membership
and using `:_` as a fallback)

[13]: fugue.janet#L436
[13]: fugue.janet#L445

## prototype?



@@ 375,5 379,5 @@ and using `:_` as a fallback)

Is `obj` the result of a `defproto ` call? 

[14]: fugue.janet#L256
[14]: fugue.janet#L265


M fugue.janet => fugue.janet +21 -12
@@ 118,17 118,22 @@

(defn- getters
  [name fields]
  (seq [[field-name attrs] :in fields
        :let [key-field (keyword field-name)]]
    # Allow specifying another getter name or `false`
    # for no getter
    (when-let [docstring (string "Get " field-name " from a " name)
               getter-name (match attrs
                             {:getter getter} getter
                             _ field-name)]
      (with-syms [self]
        ~(defn ,getter-name ,docstring [,self]
           (in ,self ,key-field))))))
  (let [forms @[]]
    (loop [[field-name attrs] :in fields
           :let [key-field (keyword field-name)]]
      # Allow specifying another getter name or `false`
      # for no getter
      (when-let [docstring (string "Get " field-name " from a " name)
                 getter-name (match attrs
                               {:getter getter} getter
                               _ field-name)
                 qualified-name (symbol name "/" getter-name) ]
        (with-syms [self]
          (array/push forms ~(defn ,getter-name ,docstring [,self]
                               (in ,self ,key-field)))
          (array/push forms ~(defn ,qualified-name ,docstring [,self]
                               (in ,self ,key-field))))))
    forms))

(defn- pred-name [name] (symbol name "?"))



@@ 201,7 206,11 @@
  to prevent a getter from being defined.

  `defproto` will define a getter function for each of the defined
  fields, unless `:getter` is false.
  fields, unless `:getter` is false. It will also define a "qualified"
  getter function, where the getter-name is prepended by the name of
  the prototype. This can be used to provide a greater degree of
  "type-safety", as the qualified getter won 't be defined if that
  prototype doesn 't have that field.

  `defproto` will also create a `:new` method in the created
  prototype. This will take as positional arguments all of the fields

M test/fugue.janet => test/fugue.janet +2 -1
@@ 162,7 162,8 @@
(deftest getter
  (let [a-form (:new Form :unique-field :echo)]
    (is (nil? (dyn 'unique-field)))
    (is (= :echo (get-unique-field a-form)))))
    (is (= :echo (get-unique-field a-form)))
    (is (= :echo (Form/get-unique-field a-form)))))

(fugue/defproto Form2 () second-unique-field {:getter false})