GLS: Generic Little System
(require gls) | package: gls |
1 Introduction. Purpose of the library
This library allows to make generics on arbitrary predicates. Generic is a function, that called with different dunction bodies, depending upon its argument types, and these bodies may be changed at any time. Classic implementation is CLOS.
gls differs from CLOS (and Swindle): it allows not only classes as dispatching condititons, but any possible predicates. For example, classic circle-ellipse problem with gls may be solved as
> (require gls)
> (struct ellipse (h v) #:mutable)
> (define circle? (and? ellipse? (λ (e) (= (ellipse-h e) (ellipse-v e)))))
> (define (circle r) (ellipse r r))
> (defgeneric circle-radius (method ([c circle?]) (ellipse-h c)))
> (defgeneric name (method ([c circle?]) "Circle") (method ([c ellipse?]) "Ellipse"))
> (define c (circle 10))
> (name c) "Circle"
> (circle-radius c) 10
> (set-ellipse-v! c 20)
> (name c) "Ellipse"
> (circle-radius c) primary-composer: No applicable method, generic=(generic
circle-radius), vals=(#<ellipse>)
So c is a circle only when both axis are equal.
2 Base syntax
Type may be either predicate (function with one argument, returning boolean?), class? or
boolean?. Type #t means ‘any type‘. Type #f means ‘type without values‘. For class? –
type values – instances of the class. And for a predicate type values —
If you use predicates, that defines subtypes, you should explicitly set one type to by subtype of another type.
Beware, that subtype! sets subtypes on values of predicates, not predicate bodies. So don’t put (lambda ...) in it. lambda on each call make new procedure even when called with the same body.
syntax
(method (arg ...) body ...+)
(method (arg ...) => result body ...+)
arg = arg-name | (arg-name arg-type)
arg-type : gls:type?
result : gls:type?
syntax
(defgeneric name method ...)
> (require gls)
> (define (=1 x) (equal? x 1))
; We cannot do (subtype! (λ (x) (equal? x)) integer?), ; because (λ (x) (equal? x)) in ; `subtype!` and in `method` will be different > (subtype! =1 integer?)
> (define default (method ([n =1]) 1))
> (defgeneric fact default (method ([n integer?]) (* (fact (- n 1)) n)))
> (fact 5) 120
3 Dynamic change methods
procedure
(add-method generic method) → any
generic : gls:generic? method : gls:method?
procedure
(remove-method generic method) → any
generic : gls:generic? method : gls:method?
procedure
(replace-method generic method) → any
generic : gls:generic? method : gls:method?
4 Augmenting methods
procedure
(add-before-method generic method) → any
generic : gls:generic? method : gls:method?
procedure
(remove-before-method generic method) → any
generic : gls:generic? method : gls:method?
procedure
(replace-before-method generic method) → any
generic : gls:generic? method : gls:method?
procedure
(add-after-method generic method) → any
generic : gls:generic? method : gls:method?
procedure
(remove-after-method generic method) → any
generic : gls:generic? method : gls:method?
procedure
(replace-after-method generic method) → any
generic : gls:generic? method : gls:method?
procedure
(add-around-method generic method) → any
generic : gls:generic? method : gls:method?
procedure
(remove-around-method generic method) → any
generic : gls:generic? method : gls:method?
procedure
(replace-around-method generic method) → any
generic : gls:generic? method : gls:method?
5 Combinators
procedure
(and? type ...) → gls:type?
type : gls:type?
procedure
(or? type ...) → gls:type?
type : gls:type?
procedure
(compose? type ...) → gls:predicate?
type : gls:type?
procedure
(==? value) → gls:predicate?
value : any/c
procedure
(negate? type) → gls:type?
type : gls:type?