_This is an old draft that I discovered when going through my gists. Everything I wrote then is still true, so please enjoy!_ [This Article](http://www.gar1t.com/blog/2012/06/10/solving-embarrassingly-obvious-problems-in-erlang/) has struck a chord with me. I'm not an Erlang-er, but the style he describes of "writing many tiny functions" strongly reminds me of why I've come to love [Factor](http://factorcode.org). ## Drink Beer when Delicious * "good" or "well written" Erlang functions are *very* Factor-like * Tiny functions are easy to understand. Take the first example: drinking beer when it's delicious. This mess: if deliciousness(Beer) >= ?EXCELLENT -> drink(Beer); true -> obstain end Translates into this, when refactored: maybe_drink(if_standard_met(deliciousness(Beer), ?EXCELLENT), Beer) The key realization here is to formalize the "deliciousness comparison" in `if_standard_met`. This is the same thought process that happens when 'factoring' a word in Factor. For example, this is an ugly but direct translation of the above Erlang `if`: : maybe_drink ( beer -- ) dup deliciousness>> ?EXCELLENT >= [ drink ] [ abstain ] if ; Thanks to the terse-ness of Factor's syntax, the code winds up being very short -- just 58 characters! -- but due to stack shuffling & symbol noise `(>>, ?, [])` it's downright intimidating. And again, the *intent* of the code is lost somewhere along the way. What we want is this: : maybe_drink ( beer -- beer' ) beer_delicious? [ drink! ] when ; Wow! How clear! I read that as, "When the beer is delicious, drink!." A motto to live by, almost as good as the classic Forth bumper sticker `FORTH LOVE? IF HONK THEN` ## J'proteste! *"But,"* I hear you protest, *"this will lead to half a dozen tiny functions."* "Precisely!" It leads to several small and **obviously correct** functions ("words" in Factor parlance). How do we tell if a beer is delicious? Get the 'deliciousness' of the beer and compare it to the `?EXCELLENT` standard: : beer_delicious? ( beer -- beer ? ) #! Is this beer delicious? ... deliciousness ?EXCELLENT if_standard_met ; How do we compare a score against its standard? For now, greater-than-or-equal-to is fine. : if_standard_met ( score goal -- ? ) >= ; `>=` is an ordinary word in Factor, a bit like a function in other languages. How do we drink a beer? Let's represent "consumed" beer with a boolean flag. So then, to drink a beer: : drink! ( beer -- beer' ) t >>consumed ; #! set the 'consumed' flag to true Each is so simple that I can, at a glance, see that they do the right thing. ## Implicit left-application One feature of Factor (and of concatenative languages in general) is implicit left-application, such that: functional concatenative f(g(X)) -> X g f add(1,2) -> 1 2 add Implicit left-application leads to visually uncluttered code. And it largely eliminates mental juggling of nesting levels. It does, however, lead to mental stack juggling and a smug sense of "my code is so short!". And sometimes I need to explicitly deal with the stack using "shuffle words" such as `dup` and `swap`: functional concatenive f(X, X) -> X dup f f(g(X), X) -> X dup g swap f Heavy use of `dup` and `swap` is a code smell, but, in their correct application, they serve to enforce sane stack flow between words. That means we can translate the 'refactored' Erlang version to: maybe_drink(if_standard_met(deliciousness(B), ?EXCELLENT), B) -> B dup deliciousness ?EXCELLENT if_standard_met maybe_drink In practice, `dup` is as easy to visually parse as `f(X, X)`. The direct translation of `maybe_drink` is not pretty to look at, which is why we *factor* the definition (har har): : beer_delicious? ( beer -- beer ? ) dup deliciousness ?EXCELLENT standard_met? ; : maybe_drink ( beer -- beer' ) beer_delicious? [ drink! ] when ; I admit: I cheated a little and snuck `dup` into `beer_delicious?` to keep `maybe_drink` short, clear, and beautiful. Considering the original, this makes sense: maybe_drink(f(B), B) `beer_delicious?` provides both the flag and argument for `when` conditional. Factor's stack-effect declaration makes that explicitly clear: : beer_delicious? ( beer -- beer ? ) ... #! Accepts a beer, and returns the same beer with a flag ('?') Those stack parameters can be named anything, but convention is that `?` means a boolean value. Another convention is appending a tick or "prime" indicator when the word alters the object: : maybe_drink ( beer -- beer' ) ... #! This accepts a beer and returns a modified beer. Read that as "accepts beer, returns beer prime" — `beer'` is either the beer, consumed, or the original beer, untouched. (Because this word can thirstily modify the `beer` there's one more convention to follow: it should be called `maybe_drink!`) ## Summary * Small is beautiful. * Small is easy to understand. * Small definitions lead to clarity of thought. And above all: * *When the beer is delicious, drink.*