M README.md => README.md +18 -18
@@ 57,7 57,7 @@ be selected for any descendent prototype instances.
## fugue
-[Root](#Root), [allocate](#allocate), [declare-protocol](#declare-protocol), [defgeneric](#defgeneric), [defmethod](#defmethod), [defmulti](#defmulti), [defproto](#defproto), [extend-protocol](#extend-protocol), [fields](#fields), [multimethod-types-match?](#multimethod-types-match), [proto-or-type](#proto-or-type), [prototype?](#prototype)
+[Root](#Root), [allocate](#allocate), [declare-open-multi](#declare-open-multi), [defgeneric](#defgeneric), [defmethod](#defmethod), [defmulti](#defmulti), [defproto](#defproto), [extend-multi](#extend-multi), [fields](#fields), [multimethod-types-match?](#multimethod-types-match), [proto-or-type](#proto-or-type), [prototype?](#prototype)
## Root
@@ 86,21 86,21 @@ all descendents of that prototype.
[2]: fugue.janet#L164
-## declare-protocol
+## declare-open-multi
**macro** | [source][3]
```janet
-(declare-protocol name)
+(declare-open-multi name)
```
-Declare a protocol, ie, a multimethod with `varfn` behaviour.
+Declare an open multimethod, ie, one that can be extended.
-Declaring a protocol allows it to be extended (see
-`extend-protocol`) from any other environment, making the case
-extension available wherever the protocol has been imported.
+Extending an open multimethod (see `extend-multi`) from any other
+environment makes the case extension available wherever the
+multimethod has been imported.
-[3]: fugue.janet#L437
+[3]: fugue.janet#L447
## defgeneric
@@ 164,8 164,8 @@ Example usage :
`defmulti` takes a sequence of type-or-prototypes, and builds a
function which will check its arguments against those types (as well
- as all other ones specified in other `defmulti` calls to the same
- function name), and execute the function body for the matching type
+as all other ones specified in other `defmulti` calls to the same
+function name), and execute the function body for the matching type
signature.
In addition to type names or prototypes, you can use the symbol `_`
@@ 205,7 205,7 @@ repl:12:> (cat "hello" 100)
"hello #100"
```
-[6]: fugue.janet#L363
+[6]: fugue.janet#L373
## defproto
@@ 269,23 269,23 @@ repl:47:> (speak (:new Pekingese))
[7]: fugue.janet#L15
-## extend-protocol
+## extend-multi
**macro** | [source][8]
```janet
-(extend-protocol protocol multi-types args & body)
+(extend-multi multi multi-types args & body)
```
-Extend a protocol (see `declare-protocol`) using the same syntax as
-`defmulti`.
+Extend an open multimethod (see `declare-open-multi`) using the same
+syntax as `defmulti`.
See that function's documentation for full usage reference.
-Whenever a case is added to `protocol`, that case is available
-wherever the protocol is imported.
+Whenever a case is added to `multi`, that case is available
+wherever the multimethod is imported.
-[8]: fugue.janet#L450
+[8]: fugue.janet#L460
## fields
M fugue.janet => fugue.janet +17 -17
@@ 393,8 393,8 @@
`defmulti` takes a sequence of type-or-prototypes, and builds a
function which will check its arguments against those types (as well
- as all other ones specified in other `defmulti` calls to the same
- function name), and execute the function body for the matching type
+ as all other ones specified in other `defmulti` calls to the same
+ function name), and execute the function body for the matching type
signature.
In addition to type names or prototypes, you can use the symbol `_`
@@ 440,41 440,41 @@
(with-syms [args]
(let [cases (get-multi-cases name)
- cond-form (construct-cond name cases args)
+ cond-form (construct-cond (string name) cases args)
docstring (make-docstring cases)]
(emit-defn name docstring args cond-form))))
-(defmacro declare-protocol
+(defmacro declare-open-multi
```
- Declare a protocol, ie, a multimethod with `varfn` behaviour.
+ Declare an open multimethod, ie, one that can be extended.
- Declaring a protocol allows it to be extended (see
- `extend-protocol`) from any other environment, making the case
- extension available wherever the protocol has been imported.
+ Extending an open multimethod (see `extend-multi`) from any other
+ environment makes the case extension available wherever the
+ multimethod has been imported.
```
[name]
~(do (varfn ,name "Open multimethod." [] nil)
(-> (in (dyn ',name) :ref)
(,declare-varmulti))))
-(defmacro extend-protocol
+(defmacro extend-multi
```
- Extend a protocol (see `declare-protocol`) using the same syntax as
- `defmulti`.
+ Extend an open multimethod (see `declare-open-multi`) using the same
+ syntax as `defmulti`.
See that function's documentation for full usage reference.
- Whenever a case is added to `protocol`, that case is available
- wherever the protocol is imported.
+ Whenever a case is added to `multi`, that case is available
+ wherever the multimethod is imported.
```
- [protocol multi-types args & body]
+ [multi multi-types args & body]
- (let [ref (in (dyn protocol) :ref)]
+ (let [ref (in (dyn multi) :ref)]
(put-var-case ref multi-types args body)
(with-syms [args]
(let [cases (get-var-cases ref)
- fn-name (->> protocol (string/split "/") (last))
+ fn-name (->> multi (string/split "/") (last))
cond-form (construct-cond fn-name cases args)
docstring (make-docstring cases "Open ")]
- (emit-varfn protocol (symbol fn-name) docstring args cond-form)))))
+ (emit-varfn multi (symbol fn-name) docstring args cond-form)))))
M test/fugue.janet => test/fugue.janet +19 -9
@@ 147,14 147,24 @@
# the earliest position.
(is (= "x+2" (cat2 "x" 2))))
-(fugue/declare-protocol to-string)
-(fugue/extend-protocol to-string [:number] [n] (string "+" n))
-(fugue/extend-protocol to-string [:string] [s] (string s "!"))
-
-(deftest protocols
- # Protocols can be extended from other environments, which is a bit
- # tough to do here. So just test the basics.
- (is (= "s!" (to-string "s")))
- (is (= "+10" (to-string 10))))
+(fugue/defmulti to-string [:number] [n] (string "+" n))
+(do
+ (fugue/defmulti to-string [:string] [s] (string s "!")))
+
+(fugue/declare-open-multi to-string2)
+(do
+ (fugue/extend-multi to-string2 [:number] [n] (string "+" n))
+ (fugue/extend-multi to-string2 [:string] [s] (string s "!")))
+
+(deftest open-multimethods
+
+ # normal multimethods obey scoping rules; a scoped def is not
+ # available in enclosing (or adjacent) environments.
+ (is (= "+10" (to-string 10)))
+ (assert-thrown (to-string "s"))
+
+ # open methods can be extended from other scopes.
+ (is (= "s!" (to-string2 "s")))
+ (is (= "+10" (to-string2 10))))
(run-tests!)