GLS:   Generic Little System
1 Introduction. Purpose of the library
2 Base syntax
subtype!
method
defgeneric
3 Dynamic change methods
add-method
remove-method
replace-method
4 Augmenting methods
add-before-method
remove-before-method
replace-before-method
add-after-method
remove-after-method
replace-after-method
add-around-method
remove-around-method
replace-around-method
5 Combinators
and?
or?
compose?
==?
negate?
8.12

GLS: Generic Little System🔗ℹ

Roman Klochkov <kalimehtar@mail.ru>

 (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 — all values, on which predicate returns #t.

If you use predicates, that defines subtypes, you should explicitly set one type to by subtype of another type.

procedure

(subtype! subtype supertype)  void?

  subtype : gls:predicate?
  supertype : gls:predicate?
Sets subtype to be subtype of supertype for dispatching. So, if a generic has a method with subtype argument and a method with supertype argument and both are acceptable for some values, then the method with subtype argument will be executed.

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?
Produces a method for GLS. Method may be used as a procedure, in that case no typecheck is performed. When used in generic, type of the arguments is used to select correct method. Result type is not used during dispatching, but is checked on the generic result.

syntax

(defgeneric name method ...)

Defines generic with given name and methods.

> (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?