Re: Factor

Factor: the language, the theory, and the practice.

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:

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.