Anonymous Predicates
Wednesday, November 15, 2023
Factor has several types of classes that can be used to specialize methods on generic words and to disambiguate objects from other objects. Some examples are:
- built-in classes (defined in the VM),
- tuple classes,
- union classes,
- intersection classes,
- maybe classes,
- mixin classes,
- singleton classes, and
- predicate classes.
Today, we are going to discuss predicate classes and a recent feature that was contributed by @Capital-Ex to support anonymous predicates. A typical definition of a predicate class might look like this definition which describes all positive integers:
PREDICATE: positive < integer 0 > ;
You can use it in the listener to identify instances:
IN: scratchpad 12 positive? .
t
IN: scratchpad -5 positive? .
f
You can also dispatch on them:
GENERIC: wat ( obj -- str )
M: object wat drop "object" ;
M: positive wat drop "positive integer" ;
And see how that works:
IN: scratchpad 12 wat .
"positive integer"
IN: scratchpad f wat .
"object"
The new anonymous predicates feature allows us to rewrite that word with inline predicate definitions:
GENERIC: wat ( obj -- str )
M: object wat drop "object" ;
M: predicate{ integer [ 0 > ] } wat drop "positive integer" ;
And, in fact, we could extend it with some of the other anonymous classes to create this monstrosity:
GENERIC: wat ( obj -- str )
M: object wat drop "object" ;
M: predicate{ integer [ 0 > ] } wat drop "positive integer" ;
M: intersection{ bignum positive } wat drop "five" ;
M: union{ fixnum bignum } wat drop "integer" ;
M: maybe{ string } wat drop "maybe a string" ;
And then test most (all? who really knows?) of the cases:
IN: scratchpad 5 wat .
"positive integer"
IN: scratchpad 5 >bignum wat .
"five"
IN: scratchpad -5 wat .
"integer"
IN: scratchpad "hello" wat .
"maybe a string"
IN: scratchpad B{ } wat .
"object"
Pretty cool! This is available in the development version of Factor.