# Re: Factor

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

## Sequence Case

Sunday, September 10, 2023

Some languages allow ranges to be used in switch statements. For example, like in this Swift code:

``````let count = 3_000_000_000_000
let countedThings = "stars in the Milky Way"
var naturalCount: String
switch count {
case 0:
naturalCount = "no"
case 1...3:
naturalCount = "a few"
case 4...9:
naturalCount = "several"
case 10...99:
naturalCount = "tens of"
case 100...999:
naturalCount = "hundreds of"
case 1000...999_999:
naturalCount = "thousands of"
default:
naturalCount = "millions and millions of"
}
println("There are \(naturalCount) \(countedThings).")
``````

Let’s build this functionality in Factor!

### Range Syntax

First, let’s look at how we can construct a range.

``````1000 999,999 [a..b]
``````

If we wanted to use that in a case statement, we could wrap it with a literal:

``````{ \$[ 1000 999,999 [a..b] ] [ "thousands of" ] }
``````

But that’s not that elegant, instead let’s define some syntax words to construct our range:

``````SYNTAX: ..= dup pop scan-object [a..b] suffix! ;
``````

This is much cleaner:

``````{ 1000 ..= 999,999 [ "thousands of" ] }
``````

### Combinators

In Factor, we have combinators which are, at some level, just words that take code as input. We sometimes refer to these as higher-level concepts, but they allow us to be more expressive with fewer tokens.

Let’s build our combinator using a macro to transform some input cases:

``````MACRO: sequence-case ( assoc -- quot )
[
dup callable? [
[ first dup set? [ in? ] [ = ] ? '[ dup _ @ ] ]
[ second '[ drop @ ] ] bi 2array
] unless
] map [ cond ] curry ;
``````

Now we can write a Factor version of the original Swift example above:

``````3,000,000,000,000 {
{ 0 [ "no" ] }
{ 1 ..= 3 [ "a few" ] }
{ 4 ..= 9 [ "several" ] }
{ 10 ..= 99 [ "tens of" ] }
{ 100 ..= 999 [ "hundreds of" ] }
{ 1000 ..= 999,999 [ "thousands of" ] }
[ drop "millions and millions of" ]
} sequence-case "There are %s stars in the Milky Way.\n" printf
``````

Cool!

This is available in the `combinators.extras` vocabulary in the development version of Factor.