Charlie Harvey

Seven More Languages: Factor Day Three

And so on to the final day of the concatenative Factor language. I actually found today a bit more straightforward than day 2. I felt more like I was working with functions and was worrying less about where items were on the stack. I completed most of the exercises but again ran out of time before completing the last one.

Exercises

Easy execrises

Define a constuctor for cart-item that accepts a price and returns a cart item with a default name and quantity.

Well, this was certainly easy enough. : <price-cart-item> ( p -- cart-item ) "Default" swap 1 cart-item boa ;I also implemented an unit test for this { 1.50 } [ 1.50 <price-cart-item> price>> ] unit-test

Write a word that discounts the price of a cart item by a percentage that is given as a parameter.

I originally wrote a version that used the exact spec, but I eventually settled on an implementation that lets you pass an higher order function to calculate the discount in basically the same way as the shipping and taxes calculations work, but for an item rather than a checkout. ! ten percent off everything : tenpercent-off ( price -- discounted-price ) 0.9 * ; ! 25 percent off everything : twentyfivepercent-off ( price -- discounted-price ) 0.75 * ; ! work out discount on a cart-item : discount-item ( cart-item discount-calc -- cart-item ) [ dup price>> ] dip call to-price >>price ; inline

And here are the unit tests { T{ cart-item f "test" 9.0 1 } } [ sample-item [ tenpercent-off ] discount-item ] unit-test { T{ cart-item f "test" 7.50 1 } } [ sample-item [ twentyfivepercent-off ] discount-item ] unit-test

Medium exercises

Write words that define different tax rates and a new shipping scheme.

For this, I just did the standard UK VAT rate of 20% and a modified per-item shipping rate. ! works UK VAT out taxes on a base price : uk-vat ( price -- taxes ) uk-vat-rate * ; ! ! UK shipping : uk-per-item ( item-count -- shipping ) uk-per-item-shipping * uk-base-shipping + ;

Assemble the tax rates and shipping scheme into a new checkout processing pipeline.

Factor really shines here, the impleentation is trivial. I just write ! ! testing the UK pipeline : uk-checkout ( checkout -- checkout ) [ uk-vat ] taxes [ uk-per-item ] shipping total ;

Write a unit test to verify that your new tax rates and shipping scheme work correctly.

{ T{ checkout f 3 60.97 12.19 5.09 78.25 } } [ <sample-cart> <checkout> uk-checkout ] unit-test

Hard exercises

Make changes to the code so that prices are adjusted in a way that eliminates rounding errors and makes the unit tests pass.

I wasn’t too sure why this was an hard exercise, perhaps I was missing something. I just made a function that takes a float don to 2 decimal places like this ! ! convert a number to 2 decimal places : to-price ( float -- price ) 100 * round 100 / ;

Now, every time I set a price, I push it through this function to have it rounded down to 2 decimal places. For example in cart-item-price ! price of a single line (#items X price) : cart-item-price ( cart-item -- price ) [ price>> ] [ quantity>> ] bi * to-price ;

Enhance the number guessing game that you wrote on Day 2 so that it uses a graphical user interface instead of the commmand-line console.

I ran out of time before I could solve this one. I struggled to find any good examples of how to do GUIs in factor. Though the documentation is comprehensive, it isn’t as in-depth as I would like.

Conclusion

Factor turned my brain inside out a little. The back to front syntax is actually not as crazy as you might think — it is really just the same as using pipes in bash.

However, juggling with the stack seems to me problematic. It isn’t that it is so hard to do. It is just that the juggling interfered with thinking about the problem in hand for me. Now, that might get easier when one s more familiar with the language, but I would rather focus on what it was I was trying to say than on the mechanics of exactly how I was articulating it.

In his wrap up, Fred Daoud says of Factor

Like many non-mainstream languages, Factor has a relatively small community of users … It's also worth noting that the name Factor does not make it any easier to search the web for answers.

Amen to that. It is a massive faff to find documentation online for the language.

For programmers like me who spend a lot of time programming with our communal exocortex, this is a big problem ™.

That said Factor’s minimal syntax and simple model of computation makes it fun to learn and to play with and, as Daoud points out, it has a whole raft of vocabularies that will help you build just about any conceivable real world application.


Comments

  • Be respectful. You may want to read the comment guidelines before posting.
  • You can use Markdown syntax to format your comments. You can only use level 5 and 6 headings.
  • You can add class="your language" to code blocks to help highlight.js highlight them correctly.

Privacy note: This form will forward your IP address, user agent and referrer to the Akismet, StopForumSpam and Botscout spam filtering services. I don’t log these details. Those services will. I do log everything you type into the form. Full privacy statement.