Hi 4tH-ers!
After all the FP stuff I've done lately, I felt like picking up an old, abandoned project of fine, which was a library allowing to use some Factor constructs. Before I tried to recode them in plain 4tH, but the deeper in the stack I got, the harder it got. So I let it go.
After all, I found out I was doing it wrong altogether. And I found I could recode Factor in Factor like code - which was close to ripping it from the manual. Then it went pretty quickly.
Note you got to remember 2OVER, PICK and 2NIP are not what they seem to be. PICK is THIRD, 2OVER is about THIRD THIRD and 2NIP is NIP NIP. EXECUTE is called CALL. But once you got that, it's easy sailing.
You know NOTHING gets it without testing, so that's what I'm doing now - making a formal test program. However, in the meanwhile I tried to do some programming. It's quite hard to wrap your head around, because you got quotations within quotations - which requires quite another set of thought.
Otherwise, there are things in Factor, which you cannot emulate in 4tH - like lists, ranges or quotation manipulation (remembers me of self modifying code). But with a little trouble I got this going:
include lib/factor.4th
: bottle ( -- xt )
[:
[:
[: . ." bottles of beer on the wall, " ;]
[: . ." bottles of beer." ;] bi cr
;] keep
1- [: <# #s #> ;] [: s" no more" ;] if*
s" Take one down, pass it around, " 2swap
s" bottles of beer on the wall!" [: print ;] 2tri@ cr
;] ;
: last-verse ( -- )
s" Go to the store and buy some more, "
s" no more bottles of beer on the wall!" [: print ;] 2bi@ cr ;
: bottles ( n -- )
0 swap ?do i bottle call -1 +loop last-verse ;
99 bottles
Note: THIS IS ONLY 99 BOTTLES OF BEER. You can compare the actual version at Rosetta code.
So yes, you got absolutely less stack acrobatics, but I don't find it a whole lot easier. Especially debugging is a horror. I also find the documentation lacking, since there is no tutorial to speak of. Only some kind of "tour". Stack comments are complicated.
And finally it's not "stack friendly". E.g. EACH-INTEGER expands its range COMPLETELY in one go - so if you do 512 EACH-INTEGER you'll crash the stack.
But it's nice to play around with since it is a cool concept. And I can imagine me writing a subroutine or two in this dialect.
Lemme know what you think.
Hans Bezemer