Re: Factor

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

Anonymous Predicates

Wednesday, November 15, 2023

#language #syntax

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.