PPL30 Day 12: Factor

Factor is a language based on Forth, a stack-based language that fell out of favor in the 80s. Stack-based? Yes, we’ll get to that. This also makes it a concatenative language, which means, unless you’ve used Forth, Factor, Joy, or one of another handful of concatenative languages, this is comletely different than the norm (i.e. applicative languages).

The name ‘Factor’ might ring a bell, because when Zed Shaw was freakin’ out on the Ruby community, his love, however fleeting, was being bestowed upon Factor and the Factor community at that moment.

This is part of the Peer Pressure Learning 30 series. To learn more about what in the hell that means, see the intro to the series, A Good Time To Learn.

'factor logo'

Installation

And now for something completely different: Go to the site. Find the downloads section. Find the download that meets your system’s requirements. Install it. (I installed a .dmg from the stable releases table.)

There is a brew formula, but – and maybe I’m just dumb – I couldn’t get it to work.

Resources

FactorCode.org

The Factor website, factorcode.org is definitely a good place to start. As you look around, you’ll find yourself moving between factorcode.org and a wiki on concatenative.org. There’s lots of good information to be found.

Beginning Factor Series by Aaron Schaefer

In late November and early December of 2008, Aaron wrote a couple articles to help newcomers to the Factor language understand this stack-based language stuff: Beginning Factor: Introduction and Beginning Factor: Shufflers and Combinators They’re good articles, in which went a lot of work, clearly. Unfortunately, they’re incomplete!

That’s right, Aaron. I’m calling you out. I know you’re all “Oh, well, I work at Wolfram now. And I graduated college. And I got married. And I moved. And I bought a house. And I’m moving again. Across the country.” Sure, but, I mean, is that all? What about Factor tutorials, huh?! I’m only poking and prodding because they really are well done, and a complete series would be awesome. Well, that, and I know you well enough to know you won’t be angry with me for this.

Look, some people in this HackerNews thread want you to go ahead and write a Factor book, Aaron.

What I Think I Now Know

First, let’s tackle concatenative languages:

In most languages (applicative languages), evaluation is done by applying functions to arguments. In concatenative languages, evaluation happens on one piece of data that is passed from function to function.

That single piece of data, in Factor, is the stack. Values are pushed on to the data stack. Functions are operate on data in the stack; they expect the data they need to already be there, as opposed to passing data to the function itself. The result of the function call is left on the stack. In Factor, functions are called ‘words’, because they are written by themselves, without arguments or any other decoration.

I’ve covered languages that use prefix notation, and, of course, infix notation is a bit more standard. As a consequence of being stack-based, Factor uses postfix notation.

As I suspected would be the case, I just don’t have enough time to do this language justice today. There are too many new concepts, new words, new everything. This is definitely a language that needs more than a few hours. (I truly have been reading and working with the language for 2.5 hours or so. It’s time to call it.) So, I’m going to do something horrible: I’m going to cheat.

I found this Factor FizzBuzz example at rosettacode.org. If I were reading this, I’d want to see some code whether the writer had proven himself incompetent or not.

<% coderay(:lang => :factor, :line_numbers => :inline) do #_ -%>
USING: math kernel io math.ranges ;
IN: fizzbuzz
fizz ( n – str ) 3 divisor? “Fizz” “” ? ;
buzz ( n – str ) 5 divisor? “Buzz” “” ? ;
fizzbuzz ( n – str ) dup [ fizz ] [ buzz ] bi append [ number>string ] [ nip ] if-empty ;
main ( – ) 100 [1,b] [ fizzbuzz print ] each ; MAIN: main <% end -%>

Mind blow’d? Lines starting with a colon are word (think: function) definitions. Where you see (n -- str), that means the word takes one argument (the left of the double-dash), and pushes one to the stack (the right of the double-dash). The fact that the arguments are called n and str really doesn’t matter, since the values will be yanked off the stack, anyway. It’s just polite convention – n for number, str, for string. Expressions enclosed in square brackets plus a white-space character are anonymous functions. The brackets sans spaces are standard mathematical notation for denoting end points of a range! As for all of the words? I don’t know. Perhaps the Factor docs can be of some help?

I’m sorry.

Aaron, I need your book.


Weekend! Tomorrow I’m going to jump down to DataMapper. Did you know they just released version 1.0? That’s a feat! I look forward to getting familiar with the ORM, especially now that I can use it with Rails (3.0).

Tim’s really digging deep into Clean Code. I think he’s reached pick-axe and head-lamp territory. Check out Day 12 - Boundaries.