IPython profile for Grok

March 30, 2009

To use IPython shell from Grok based project is easy, just add ipython to eggs directive in your buildout.cfg

My part with ipython added looks like this:

[app]
recipe = zc.recipe.egg
eggs = grok-awesome
       ipython
       Paste
       PasteScript
       PasteDeploy
interpreter = python-console

But I wanted to be able to inspect Grok instance and use path TAB auto-completion to navigate ZODB hierarchy.

Inspired by existing IPython profile fo Zope2 I whipped out basic implementation for Grok.

It’s available under grok-ipython. Now all IPython power can be used when inspecting objects in Grok instance:

(mygrok)[alienoid@capricorn grok-awesome]$ bin/ipython -p grok
IPython shell for Grok.

Bound object names:
-------------------
  root
  ctx

Bound command names:
--------------------
  cdg / ;cdg
  lsg / ;lsg
  pwdg
  sync
  commit

Grok IPython 0.9.1   Py 2.5.2

In [1]: root
Out[1]: <zope.app.folder.folder.Folder object at 0x9003e6c>

In [2]: ctx
Out[2]: <zope.app.folder.folder.Folder object at 0x9003e6c>

In [3]: ;cdg blog
------> cdg("blog")
Out[3]: u'/blog'

In [4]: ctx
Out[4]: <grokawesome.blog.Blog object at 0x81d2d6c>

In [5]: ;cdg 
my-first-post  second-post    

In [5]: ;cdg my-first-post
------> cdg("my-first-post")
Out[5]: u'/blog/my-first-post'

In [6]: ctx
Out[6]: <grokawesome.entry.BlogEntry object at 0xb7d556ac>

In [7]: pwdg
Out[7]: u'/blog/my-first-post'

In [8]: ctx?
Type:           BlogEntry
Base Class:     <class 'grokawesome.entry.BlogEntry'>
String Form:    <grokawesome.entry.BlogEntry object at 0xb7d556ac>
Namespace:      Interactive
Length:         0
File:           /home/alienoid/mygrok/grok-awesome/src/grokawesome/entry.py
Docstring:
    <no docstring>


In [9]: ctx??
Type:             BlogEntry
Base Class:       <class 'grokawesome.entry.BlogEntry'>
String Form:   <grokawesome.entry.BlogEntry object at 0xb7d556ac>
Namespace:        Interactive
Length:           0
File:             /home/alienoid/mygrok/grok-awesome/src/grokawesome/entry.py
Source:
class BlogEntry(grok.Container):
    grok.implements(IBlogEntry)

    portal_type = 'blogentry'
    created = property.DCProperty('created')
    modified = property.DCProperty('modified')

    def __init__(self, title, content,
                 summary=u'',
                 categories=None,
                 allow_comments=False):
        super(BlogEntry, self).__init__()
        self.title = title
        self.content = content
        self.summary = '' if summary is None else summary
        self.categories = [] if categories is None else categories
        self.allow_comments = allow_comments

TinyMCE widget in Grok

March 24, 2009

I have added TinyMCE widget to grok-awesome for editing html and it was easy as pie.

If you want TinyMCE in your Grok based project it can be achieved with following steps:

1. Add dependencies to setup.py into install_requires section:

                        'hurry.tinymce',
                        'hurry.zopetinymce',

hurry.tinymce allows you to include TinyMCE into your project without additional burden, you don’t need to do anything. Well, almost – just make sure to call:
from hurry.tinymce import tinymce
tinymce.need()

to trigger inclusion of TinyMCE in the web page.

2. Create custom widget which calls tinymce.need() as noted above and initializes TinyMCE

from zope.app.form.browser import TextAreaWidget
from hurry.tinymce import tinymce

template = """%(widget_html)s
<script type="text/javascript">
  tinyMCE.init({
    mode : "exact",
    elements: "%(elements)s",
    theme: "advanced"
  });
</script>"""

class TinyMCEWidget(TextAreaWidget):
    """Widget to edit html using TinyMCE WYSIWYG editor."""

    def __call__(self, *args, **kw):
        widget_html = super(TinyMCEWidget, self).__call__(*args, **kw)
        tinymce.need()
        return template % {'widget_html': widget_html,
                           'elements': self.name,
                           }

3. In your add/edit form use your custom widget for the field you want and off you go:

form_fields['content'].custom_widget = TinyMCEWidget

Decode hex pairwise with zip

March 20, 2009

The other day I had to decode strings containing hex numbers into plain integers.

I could use built-in int([ x [, radix]]) with radix=16 to convert a string to an integer and forget about it, but I needed to decode pairs from the hex number so that in the end from the string ‘FFEEDD’ I get 255, 238, 221

But wouldn’t you know it, there is a standard solution to get pairs in Python and it’s built-in zip function.

It’s a well known function for experienced developers, but there is one documented feature of it that doesn’t always catch one’s eye and it’s a general form for clustering a data series into n-length groups zip(*[iter(s)]*n) which is described in official docs for zip built-in.

With that in mind solution to my problem boils down to a one-line decoder:

>>> s = 'FFDDEE'
>>> [int(''.join(pair), 16) for pair in zip(*[iter(s)]*2)]
[255, 221, 238]

For those wondering how it works:

1) iter(s) creates iterable from the s

>>> iter(s)
<iterator object at 0x8a3c2cc>

2) [iter(s)] * 2 creates list of 2 iterators that all use the same underlying iterable iter(s). The important thing is that created iterators share the same iterable, so when some data is consumed by first iterator that data becomes unavailable for the second iterator and vice versa.

You can see from the output that iterator objects are located at the same address. If you are new to this behavior you can read on about shallow copies.

>>> [iter(s)]*2
[<iterator object at 0x8a3c2cc>, <iterator object at 0x8a3c2cc>]

3) leading * in zip’s parameter unpacks list from step (2) into two separate parameters for zip function. Basically it becomes zip(iterator, iterator).

More about unpacking argument list you can read in official docs.

>>> zip(*[iter(s)]*2)
[('F', 'F'), ('D', 'D'), ('E', 'E')]

Grok Awesome

March 12, 2009

I’ve started developing blog software for “A Smashing Web Framework” Grok.

The reasons behind that:

  • There is no full-featured blog software for Grok. There is a simple version Grokstar, but as for me it doesn’t fit the bill.
  • I created simple blog for Zope3 several years ago and let it languish. Now it’s time to revive it taking into account how Grok simplifies development with Zope3 technologies.
  • I’m not completely happy with WordPress. For one thing, I’d like to have easy-to-use REST API so I can use it in my Emacs to make posts.
  • I simply love Grok. You should try it and you’ll love it too.

My fledgling project lives on GitHub and it’s called grok-awesome :)


Emacs dark theme + IPython colors

March 9, 2009

Ever wondered how to make IPython colors be nice on dark background of your dark (no pun intended) Emacs theme like blackboard ?

Just add to your .emacs

(setq py-python-command-args '("-pylab" "-colors" "Linux"))

before you load ipython package

(setq py-python-command-args '("-pylab" "-colors" "Linux"))
(require 'ipython)

Now IPython uses ‘Linux’ color scheme which is suitable for dark background with light fonts instead of default ‘LightBG’.

Here it is:

Python 2.5.2 (r252:60911, Sep 30 2008, 15:41:38)
Type "copyright", "credits" or "license" for more information.

IPython 0.9.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object'. ?object also works, ?? prints more.

  Welcome to pylab, a matplotlib-based Python environment.
  For more information, type 'help(pylab)'.

In [1]: d = dict()

In [2]: ?d
Type:           dict
Base Class:     <type 'dict'>
String Form:    {}
Namespace:      Interactive
Length:         0
Docstring:
    dict() -> new empty dictionary.
    dict(mapping) -> new dictionary initialized from a mapping object's
        (key, value) pairs.
    dict(seq) -> new dictionary initialized as if via:
        d = {}
        for k, v in seq:
            d[k] = v
    dict(**kwargs) -> new dictionary initialized with the name=value pairs
        in the keyword argument list.  For example:  dict(one=1, two=2)

In [3]: 

Autovivication and Y Combinator in Python

April 14, 2008

Sometimes you may need to have nested dictionaries initialized without much hassle.

“Autovivication” comes in handy. What you want to achieve is:

>>> d = dict()
>>> d['q']['w']['r'] = 777

Of course what you’ll get will be:

>>> d['q']['w']['r'] = 777
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'q'

If you don’t need deeply nested dictionaries defaultdict with dict default factory will do the job:

>>> from collections import defaultdict
>>> d = defaultdict(dict)
>>> d
defaultdict(<type 'dict'>, {})
>>> d['a']['b'] = 33
>>> d
defaultdict(<type 'dict'>, {'a': {'b': 33}})
>>> d['a']['b']
33

Here are another ways to have unlimited level of nested dictionaries.
1) Define custom class inheriting from built-in dict:

class default_dict(dict):
    def __missing__(self, key):
        self[key] = value = self.__class__()
        return value
>>> d = default_dict()
>>> d
{}
>>> d['q']['w']['r'] = 777
>>> d
{'q': {'w': {'r': 777}}}
>>> d['q']['w']['r']
777

2) Recursive function + defaultdict:

def make_dict():
    return defaultdict(make_dict)
>>> from collections import defaultdict
>>> d = defaultdict(make_dict)
>>> d
defaultdict(<function make_dict at 0xb7c5295c>, {})
>>> d['q']['w']['r'] = 777
>>> d
defaultdict(<function make_dict at 0xb7c5295c>, {'q': defaultdict(<function make_dict at 0xb7c5295c>, {'w': defaultdict(<function make_dict at 0xb7c5295c>, {'r': 777})})})
>>> d['q']['w']['r']
777

3) And for fun you can use Y Combinator (in short – making anonymous lambda recursive) which is actually as (2) but you don’t have to have recursive function defined:

def Y(g):
    return ((lambda f: f(f))
            (lambda f:
                 g(lambda x: f(f)
                   (x))))

defdict = Y(lambda mk_dict:
                lambda x=None: defaultdict(lambda x=None: mk_dict(x)))
>>> d = defdict()
>>> d
defaultdict(<function <lambda> at 0xb7c52a74>, {})
>>> d['q']['w']['r'] = 777
>>> d
defaultdict(<function <lambda> at 0xb7c52a74>, {'q': defaultdict(<function <lambda> at 0xb7c56c6c>, {'w': defaultdict(<function <lambda> at 0xb7c56a74>, {'r': 777})})})
>>> d['q']['w']['r']
777

Erlang for Python programmers: Part V

November 16, 2007

Previous parts: Intro, Part I, Part II, Part III and Part IV

List comprehensions.

List comprehensions is very familiar topic for Python programmer. It’s a syntactic sugar which provides a succinct notation for producing elements in list.

Erlang:

[Expr || Qualifier1,...,QualifierN]

Expr – is an arbitrary expression
Qualifier is either a generator or a filter.
A generator is of form Pattern <- ListExpr where ListExpr evaluates to a list of terms.
A filter expression should evaluate to true or false.

1> [X || X <- [1,2,3,4,5,6], X > 3].
[4,5,6]

This is read as: list of X such that X is taken from list [1,2,3,4,5,6] and X is greater than 3.

In foregoing example: X <- [1,2,3,4,5,6] is a generator and X > 3 is a filter.

Several filters can be combined:

2> [X || X <- [1,a,2,3,b,4,5,6], X > 3].
[a,b,4,5,6]
3> [X || X <- [1,a,2,3,b,4,5,6], integer(X), X > 3].
[4,5,6]

Generator part may act as a filter in list comprehension:

4> [X || {X, a} <- [{1, a}, {2, b}, {3, a}, erlang]].
[1,3]

Generators can be combined too in list comprehensions. This is the Cartesian product of two lists:

5> [{X, Y} || X <- [1, 2, 3], Y <- [a, b]].
[{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}]

This is how elegantly quicksort algorithm is solved with the help of list comprehensions in Erlang:

-module(sort).
-export([qsort/1]).

qsort([]) -> [];
qsort([Pivot|Tail]) ->
    qsort([X || X <- Tail, X < Pivot])
        ++ [Pivot] ++
        qsort([X || X <- Tail, X >= Pivot]).

Compile and run:

6> c("/home/alienoid/dev/erlang/sort", [{outdir, "/home/alienoid/dev/erlang/"}]).
{ok,sort}
7> sort:qsort([7, 5, 9, 3, 6]).
[3,5,6,7,9]

Usage of list comprehensions instead of some higher-order functions:

8> lists:map(fun(X) -> X*2 end, [1, 2, 3]).
[2,4,6]
9> [X*2 || X <- [1, 2, 3]].
[2,4,6]
10> lists:filter(fun(X) -> X rem 2 == 0 end, [1, 2, 3, 4]).
[2,4]
11> [X || X <- [1, 2, 3, 4], X rem 2 == 0].
[2,4]

Python:

[expression for expr1 in seq1 if cond1
            for expr2 in seq2 if cond2
            for exprN in seqN if condN]

this actually transforms to:

for expr1 in seq1:
    if not cond1:
        continue
    for expr2 in seq2:
        if not cond2:
            continue
        for exprN in seqN:
            if not condN:
                continue

So in Python Cartesian product of two lists [1, 2, 3 ] and ['a', 'b'] will look like:

>>> [(x, y) for x in [1, 2, 3] for y in ['a', 'b']]
[(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b')]

Variable bindings and scope rules in List Comprehensions:

Current Python 2.x “leaks” loop variable into surrounding scope. This should be solved in Python 3.0

>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> vlist = [x for x in 'abc']
>>> vlist
['a', 'b', 'c']
>>> x
'c'

To avoid leaking loop variable into surrounding scope we can use generator expression which doesn’t “leak”:

>>> vlist = list(x for x in 'abc')
>>> vlist
['a', 'b', 'c']
>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

Erlang has following scope rules for variables in list comprehensions(from Erlang manual):

  • all variables which occur in a generator pattern are assumed to be “fresh” variables
  • any variables which are defined before the list comprehension and which are used in filters have the values they had before the list comprehension
  • no variables may be exported from a list comprehension

So, Erlang doesn’t “leak” variables:

1> [X || X <- [1, 2, 3]].
[1,2,3]
2> X.
** 1: variable 'X' is unbound **

Be careful, sometimes you need to move some pattern matching operations into filter:

-module(listcomp).
-export([select/2]).

%% This select produces following warning during compilation:
%% Warning: variable 'X' shadowed in generate
select(X, List) ->
    [Y || {X, Y} <- List].

The function doesn’t produce desired result:

1> listcomp:select(b, [{b, 1}, {c, 2}, {b, 3}]).
[1,2,3]

So we modify generator and move pattern matching operation into filter to achieve what we need:

-module(listcomp).
-export([select/2]).

%% Moving X from pattern matching into filter
select(X, List) ->
    [Y || {X1, Y} <- List, X == X1].
2> listcomp:select(b, [{b, 1}, {c, 2}, {b, 3}]).
[1,3]

As you saw, while different in syntax, both languages provide valuable language construct which allows to write shorter and more elegant programs.


Erlang for Python programmers: Part IV

October 2, 2007

Previous parts: Intro, Part I, Part II and Part III

Funs – sequel

Continuing previous post about functions let’s remember about Fun. I already mentioned it in Part I and promised to show its advanced forms. So, here we go.

Fun with one clause:

1> Double = fun(X) -> X * 2 end.
#Fun<erl_eval.6.56006484>
2> Double(2).
4

But Fun actually has the same function declaration syntax as regular function, except that it has no name in declaration, so we can have this:

3> Big = fun (X) when X > 100 -> true;
3>           (X) -> false
3>       end.
#Fun<erl_eval.6.56006484>
4> lists:filter(Big, [20, 30, 120, 130]).
[120,130]

As you see our Fun has two clauses separated by semicolon(;) and first clause has also guard, ie syntax is the same as in regular function declaration.

There are also following fun expressions that can be used:

  1. fun FunctionName/Arity (FunctionName should point to local function defined in the same module with our fun)
  2. fun Module:FunctionName/Arity (FunctionName should be exported from module Module)

fun FunctionName/Arity is just syntactic sugar for fun (X1, ..Xn) -> FunctionName(X1, .., Xn) end.

Let’s take a look on foregoing in action and create mymath.erl

-module(mymath).
-export([test1/0,
         test2/0,
         test3/0,
         double/1]).

test1() -> lists:map(fun(X) -> X * 2 end, [1, 2, 3]).

test2() -> lists:map(fun double_local/1, [1, 2, 3]).

test3() -> lists:map(fun mymath:double/1, [1, 2, 3]).

%% helper function, not exported
double_local(X) ->
    X * 2.

%% helper function, exported
double(X) ->
    X * 2.

Compile and test it (I’m compiling as usual in Emacs with C-c C-k):

1> c("/home/alienoid/dev/erlang/mymath", [{outdir, "/home/alienoid/dev/erlang/"}]).
{ok,mymath}
2> mymath:test1().
[2,4,6]
3> mymath:test2().
[2,4,6]
4> mymath:test3().
[2,4,6]

Also tuple of type {Module, FunctionName} is interpreted as a fun Module:FunctionName/Arity which you already saw. This usage is deprecated, but to be complete here is an example:

5> Append = {lists, append}.
{lists,append}
6> Append([1, 2], [3, 4, 5]).
[1,2,3,4,5]

As you already noted Fun in Erlang is “richer” than lambda in Python.

Built-in functions, BIFs

Both Erlang and Python provide built-in functions that are always available and do not require explicit usage of module name to use them.

Python:

Read more about builtins in library reference.

In Python shell you can inspect in addition contents of __builtins__ module if you need:

>>> import pprint
>>> pprint.pprint(dir(__builtins__))
['ArithmeticError',
 'AssertionError',
 ...
 'type',
 'unichr',
 'unicode',
 'vars',
 'xrange',
 'zip']

Erlang:
Most of the built-in functions belong to module erlang and they are auto-imported.
To get list of all BIFs with description read man erlang.
In Eshell you can get list of functions that belong to erlang module with m(Module). command:

1> m(erlang).
Module erlang compiled: No compile time info available
Compiler options:  []
Object file: preloaded
Exports:
'!'/2                         list_to_existing_atom/1
'$erase'/1                    list_to_float/1
'$erase'/0                    list_to_integer/2
'$get'/1                      list_to_integer/1
'$get'/0                      list_to_pid/1
'$get_keys'/1                 list_to_tuple/1
'$put'/2                      load_module/2
'*'/2                         loaded/0
'+'/1                         localtime/0
'+'/2                         localtime_to_universaltime/1
'++'/2                        localtime_to_universaltime/2
...
ok

Take into account though that not all functions in above list that you’ll see are auto-imported and may require usage of module: prefix. Again, for more information read man erlang (either in command line with erl -man erlang or if you use Emacs take a look at Erlang man pages in Emacs)

Macros

Python does not have them, Erlang does. In Erlang they are not as powerful as in Common Lisp, but more like in C.

They are defined in following form:

-define(Const, Replacement).
-define(Func(Var1,...,VarN), Replacement).

Whenever erlang preprocessor encounters expression of form ?MacroName it expands corresponding macro.
Define utils.erl:

-module(utils).
-export([foo/0]).
-define(TIMEOUT, 100).
-define(FUNCMACRO(X, Y), {X, x, Y, y}).

foo() ->
    io:format("TIMEOUT = ~p~n", [?TIMEOUT]),
    ?FUNCMACRO(3, 7).

Compile and run:

1> utils:foo().
TIMEOUT = 100
{3,x,7,y}

There are also some predefined macros:

?MODULE
The name of the current module.
?MODULE_STRING.
The name of the current module as a string.
?FILE.
The file name of the current module.
?LINE.
The current line number.
?MACHINE.
The machine name, 'BEAM'.

Having ?MODULE we can rewrite earlier example with Fun as:

-module(mymath).
-export([test1/0,
         test2/0,
         test3/0,
         double/1]).

test1() -> lists:map(fun(X) -> X * 2 end, [1, 2, 3]).

test2() -> lists:map(fun double_local/1, [1, 2, 3]).

%% test3() -> lists:map(fun mymath:double/1, [1, 2, 3]).
test3() -> lists:map(fun ?MODULE:double/1, [1, 2, 3]).

%% helper function, not exported
double_local(X) ->
    X * 2.

%% helper function, exported
double(X) ->
    X * 2.

And as usual compile and run to see that result is the same:

1> c("/home/alienoid/dev/erlang/mymath", [{outdir, "/home/alienoid/dev/erlang/"}]).
{ok,mymath}
2>  mymath:test1().
[2,4,6]
3>  mymath:test2().
[2,4,6]
4>  mymath:test3().
[2,4,6]

In addition there is also flow control in macros. Some of corresponding macro directives are:

  • ifdef(Macro). – Evaluate the following lines only if Macro is defined.
  • else. – It’s used after ifdef or ifndef
  • endif. - Marks the end of ifdef or ifndef directive

Example in utils.erl:

-module(utils).
-export([foo/0]).

-ifdef(debug).
-define(LOG(Msg), io:format("{~p:~p}: ~p~n", [?MODULE, ?LINE, Msg])).
-else.
-define(LOG(Msg), true).
-endif.

foo() ->
    ?LOG("Debug is enabled").

To turn LOG macro on debug should be defined. This can be achieved from command line with erlc -Ddebug utils.erl or from Eshell using c/2 function:

1> c(utils, {d, debug}).
{ok,utils}
2> utils:foo().
{utils:11}: "Debug is enabled"
ok

To turn LOG macro off debug should be omitted:

3> c(utils).
{ok,utils}
4> utils:foo().
true

To be continued.


Erlang for Python programmers: Part III

September 24, 2007

Previous parts: Intro, Part I and Part II

Today we are going to take a look at functions.
In Erlang there is no direct correspondence to what we have in Python:

1. default values, keyword arguments and formal parameter of form **name

def foo(key, name='ruslan', type='unknown', **kw):
    print 'key = %s, name = %s, type = %s' % (key, name, type)
    for key, val in kw.items():
        print '%s = %s' % (key, val)
>>> foo(1)
key = 1, name = ruslan, type = unknown
>>> foo(1, type='known', x=1, y=10)
key = 1, name = ruslan, type = known
y = 10
x = 1

2. formal parameter of form *name

def double_sum(*args):
    return sum(x * 2 for x in args)
>>> double_sum(2, 4, 5)
22

Let’s take a look at Erlang’s function declaration syntax (a bit modified from Erlang Reference Manual):

  1. Function declaration consists of function clauses separated by semicolons (;) and terminated by period (.)
  2. Function clause consists of head and body separated by ->
  3. A clause head consists of function name (which is atom), argument list(each argument is pattern) and optional guard sequence beginning with keyword when.
  4. A clause body consists of sequence of expressions separated by comma (,)

Name(Pattern11,…,Pattern1N) [when GuardSeq1] ->
Body1;
…;
Name(PatternK1,…,PatternKN) [when GuardSeqK] ->
BodyK.

where Body is in form:
Expr1,
Expr2,

ExprN

Number of arguments in function is called arity. Function is uniquely identified by combination of module name, function name and function’s arity and this form is often written as m:f/N. Two functions in the module with the same name, but different arity
are completely different functions, remember it.

Enough dry theory, let’s define our Erlang factorial function in module mymath.erl :

-module(mymath).
-export([factorial/1]).

factorial(0) ->
    1;
factorial(N) ->
    N * factorial(N-1).

What we have here:

1) function declaration of one function called factorial
2) there are two clauses
- first clause separated by semicolon (;)

factorial(0) ->
    1;

- second and final clause terminated with period (.)

factorial(N) ->
    N * factorial(N-1).

3) Every clause (first and second) has correspondingly head and body. Head consists of function’s name, in our case it’s factorial and after follows arguments list which contains patterns. In first clause pattern is 0, in second – N.

How this works:

When function is entered, the function clauses are pattern matched against passed arguments. Pattern matching happens in order functions are defined in module. So when you enter

1> mymath:factorial(5).
120

first 5 is matched against clause factorial(0) and fails as 5 != 0, then 5 is matched against N in second clause and pattern matching succeeds. As a result unbound variable N in pattern becomes bound and gets value 5. This leads to execution of body of second clause, namely N * factorial(N-1). This happens recursively until N becomes 0 and first clause factorial(0) is executed terminating recursion.
The same factorial function will look in Python without pattern matching like:

def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n-1)

In Python’s version we “hardcoded” branching in function’s body.

The benefits of pattern matching are that when conditions inside function become complex you may do your job better and write less code using pattern matching and also if you have big function this may mean that you do not have to modify body of your function but to add another clause with corresponding pattern.

Earlier I mentioned that function clauses are pattern matched in order they are defined in module. For our function this is important. If we change order of clauses this will lead to problems, as the condition to terminate recursion never appear:

-module(mymath).
-export([factorial/1]).

factorial(N) ->
    N * factorial(N-1);
factorial(0) ->
    1.

When compiling we will get warning (use C-c C-k in Emacs or c(mymath). in Eshell to compile)

2> c("/home/alienoid/dev/erlang/mymath", [{outdir, "/home/alienoid/dev/erlang/"}]).
/home/alienoid/dev/erlang/mymath.erl:6: Warning: this clause cannot match because a previous clause at line 4 always matches
{ok,mymath}

indicating that second clause will never match, but still you can call the function (it will most likely to crash after eating all your available memory).

You can easily avoid that problem introducing guard that starts with keyword when in function clause’s head:

-module(mymath).
-export([factorial/1]).

factorial(N) when N > 0 ->
    N * factorial(N-1);
factorial(0) ->
    1.

Now you can put those two clauses in any order you like. I should also add that if during pattern matching no matched function clause is found a function_clause run time error will occur:

3> mymath:factorial(-4).

=ERROR REPORT==== 24-Sep-2007::01:53:25 ===
Error in process <0.29.0> with exit value: {function_clause,[{mymath,factorial,[-4]},{erl_eval,do_apply,5},{shell,exprs,6},{shell,eval_loop,3}]}

** exited: {function_clause,[{mymath,factorial,[-4]},
                             {erl_eval,do_apply,5},
                             {shell,exprs,6},
                             {shell,eval_loop,3}]} **

What is guard anyway ? Guards make pattern matching more powerful, they can be used to perform different tests and comparison operations on variables in a pattern as you could see. You can have several guard expressions in clause separated by commans (,). The guard containing several guard expressions evaluates to true only if every guard expression evaluates to true. Example of guard containing several guard expressions:

-module(mymath).
-export([factorial/1]).

factorial(N) when is_integer(N), N > 0 ->
    N * factorial(N-1);
factorial(0) ->
    1.

For above definition calling mymath:factorial(5) reads as: choose clause factorial(N) when (N is integer AND N > 0)

There are also guard sequences which have form guard1; guard2; …; guardN and guard sequence evaluates to true if at least one guard is evaluated to true:

-module(mymath).
-export([factorial/1]).

factorial(N) when is_integer(N), N > 0; is_list(N) ->
    N * factorial(N-1);
factorial(0) ->
    1.

For above definition calling mymath:factorial(5) reads as: choose clause factorial(N) when (N is integer AND N > 0) OR N is list.

You have probably noted that the way we defined our factorial function means that it will be calling itself recursively and this will use stack and stack is not infinite resource. We need to do something about our function and this means to make it tail recursive. When last expression in function body is function call this means that call is tail recursive and this is how infinite loop may be done without consuming stack resources. So here is our new tail-recursive function factorial that uses accumulator to pass value of previous calculation:

-module(mymath).
-export([factorial/1]).

%% this one is exported, arity is 1
factorial(N) ->
    factorial(N, 1).

%% helper function, not exported, arity is 2
%% tail-recursive, uses accumulator to store
%% calculation between invocations
factorial(N, Acc) when N > 0 ->
    factorial(N-1, N*Acc);
factorial(0, Acc) ->
    Acc.

In foregoing example you can see guards, tail-recursion, usage of accumulators, functions with different arities. Experiment with it.


comment-dwim and comment-style

September 20, 2007

In my previous post I mentioned that if you use Emacs and you’re editing Erlang source code you can easily comment whole marked region by invoking M-; to which by default bound interactive Lisp function comment-dwim. This works in different modes and it’s very handy especially if your language of choice has no multiline comments.

So far so good, but I must admit sometimes I get the blues when I comment some nested code blocks with M-; keystrokes. Well, maybe I’m blowing things out of proportion about my sadness, but in any case recently I came across really nice small blog post called comment-style and since then I’m happy with comments produced in nested blocks. Let’s see why.

When you comment marked regions in Emacs buffer with M-; the comment-style variable defines the way regions are commented. Default value is plain.

Buffer with Python code before commenting:

def binsearch(seq, key, start, end):
    if end < start:
        return -1
    mid = (start + end) / 2
    if key == seq[mid]:
        return mid
    if key < seq[mid]:
        return binsearch(seq, key, start, mid-1)
    if key > seq[mid]:
        return binsearch(seq, key, start+1, end)

Buffer with Python code after commenting:

def binsearch(seq, key, start, end):
    if end < start:
        return -1
    mid = (start + end) / 2
    # if key == seq[mid]:
#         return mid
    if key < seq[mid]:
        return binsearch(seq, key, start, mid-1)
    if key > seq[mid]:
        return binsearch(seq, key, start+1, end)

As you see visually elements of commented block are not on the same line.

Example with Erlang code before commenting (somewhat far-fetched example though our main concern are comments, not code here):

all(Pred, [Hd|Tail]) ->
    case Pred(Hd) of
        true -> all(Pred, Tail);
        false ->
            io:format("Hd = ~p~n", [Hd]),
            true,
            false
    end;
all(Pred, []) when is_function(Pred, 1) -> true.

After commenting:

all(Pred, [Hd|Tail]) ->
    case Pred(Hd) of
        true -> all(Pred, Tail);
        false ->
            %% io:format("Hd = ~p~n", [Hd]),
%%             true,
            false
    end;
all(Pred, []) when is_function(Pred, 1) -> true.

So the visual issue with comments is the same.

After reading foregoing blog post about comment-style I’ve added this line to my .emacs:

(setq comment-style 'indent)

Easy as pie and which means (taken from Emacs help): ” …`comment-start’ markers should not be put at the left margin but at the current indentation of the region to comment.”

After that addition foregoing commented block in Python mode will look like:

def binsearch(seq, key, start, end):
    if end < start:
        return -1
    mid = (start + end) / 2
    # if key == seq[mid]:
    #     return mid
    if key < seq[mid]:
        return binsearch(seq, key, start, mid-1)
    if key > seq[mid]:
        return binsearch(seq, key, start+1, end)

in Erlang mode:

all(Pred, [Hd|Tail]) ->
    case Pred(Hd) of
        true -> all(Pred, Tail);
        false ->
            %% io:format("Hd = ~p~n", [Hd]),
            %% true,
            false
    end;
all(Pred, []) when is_function(Pred, 1) -> true.

Now I am happy. Thank you, Edward for the tip.