Translation
Friday, October 2, 2026
Translating an existing piece of code from one language to another is often a good way to learn a language. A great long time ago, Arkady Rost posted to the mailing list a question about translating into Factor.
The original code that was being translated looked a bit like this:
for i in rangeA {
for j in rangeB {
foo(param, i, j);
}
bar();
}
Version 0
The first solution he found seemed a little bit involved, and he wondered if it could be improved:
rangeA rangeB param [ foo ] curry
[ swapd [ call ] 2curry each bar ] 2curry each
Using these values, for example:
- rangeA:
{ "a" "b" "c" } - rangeB:
{ "1" "2" "3" } - param:
" " - foo:
append append write - bar:
"" print
We can get this output:
IN: scratchpad { "a" "b" "c" } { "1" "2" "3" } " "
[ append append write ] curry
[ swapd [ call ] 2curry each "" print ] 2curry each
1a 2a 3a
1b 2b 3b
1c 2c 3c
Version 1
I suggested something like this:
IN: scratchpad { "1" "2" "3" } [
{ "a" "b" "c" } [ append ] with map
" " join print
] each
1a 2a 3a
1b 2b 3b
1c 2c 3c
But then Arkady pointed out that “the original task is more complicated that’s why I’ve used foo and bar in definition of the problem”.
Version 2
I
suggested
an approach that takes two sequences, applies foo to create an
intermediate sequence and then applies bar to each element:
: my-func ( a b foo: ( x y -- z ) bar: ( z -- ) -- )
[ [ with map ] 2curry ] dip compose each ; inline
The readability of this can be improved quite a bit by using “fry quotations”:
: my-func ( a b foo: ( x y -- z ) bar: ( z -- ) -- )
'[ _ with map @ ] curry each ; inline
Either way, using it is pretty easy:
IN: scratchpad { "1" "2" "3" } { "a" "b" "c" }
[ append ] [ " " join print ] my-func
1a 2a 3a
1b 2b 3b
1c 2c 3c
More Ideas
Of course, we could also use local variables for a direct translation:
rangeA [| i |
rangeB [| j |
param i j foo
] each
bar
] each
Or some inline fancy currying to get:
param rangeA [ rangeB [ foo ] 2with each bar ] with each
Some other ideas included a
suggestion
to use the sequences.product vocabulary.
And then there might be the potential need for row polymorphism, meaning that quotations are allowed to use a generalized amount of values present on the stack when called.
It’s fun to be reminded that there are many ways to solve problems, that expressibility of your programming language is important, and that ultimately being able to perform desired computations is the focus here.