tags:

views:

90

answers:

3

Here's something I've seen in erlang code a few times, but it's a tough thing to google and I can only find this example (the first code block in link below):

http://www.process-one.net/en/wiki/ejabberd%5FHTTP%5Frequest%5Fhandlers/

In the "head" of function definition of process/2

process(_LocalPath = ["world"], _Request) ->

there is a pattern match on first parameter / argument;

Does this act similarly like a guard, so the following clause will be executed only if the first argument passed to process/2 is string "world", or is "world" some kind of a default argument? Or i completely misunderstood/ mis-guessed?

+4  A: 

Yes, this is a pattern match. The clause will be executed if the first argument is a list with a single element, the element being the string "world".

Zed
Thanks. I did find an explanation/example of this coding techniquehttp://learnyousomeerlang.com/syntax-in-functions
Gene T
learnyousomeerlang.com is growing with new chapters.
rvirding
+2  A: 

You are correct: _LocalPath = ["world"] acts as a pattern "guard". If the first parameter to the function "process" isn't equal to ["world"], then the emulator proceeds to find a match down.

One thing to note: _LocalPath serves as "decorator" to enhance readability since the identifier starts with an underscore.

jldupont
Thanks for reply. This is a useful technique, less typing than guards
Gene T
You should replace "start with" with "equal to".
Zed
@zed: thanks... I typed a bit too fast on this one and you still managed to beat me to it ;-)
jldupont
... and I also had time to implement the clause in question and write some test cases to make sure before answering. =D
Zed
@zed: :-) See you around.
jldupont
+1  A: 

The = in a pattern is used for an alias, it basically allows you to have your cake and eat it. It both does a normal pattern match and binds a variable to the whole matched data. It is practical if you need the whole data as it saves you having to reconstruct it. You can use it anywhere in a pattern. It has nothing to do with guards.

Starting a variable with a _ as in _LocalPath is too tell the compiler not to complain if this variable is not used. Normally the compiler whines a bit if you bind variables and don't use them. Apart from this there is nothing special about variables whose names start with _, you can use them as you would any variable.

The only really special variable is _, the anonymous variable. It always matches and is never bound so you can use it as an anonymous place holder. Which is why it exists in the first place.

I personally very rarely use variables starting with _ and prefer to use just _. I also feel that cluttering up patterns with unnecessary things is a Bad Thing so I wouldn't use aliases for documentation like that. I would write:

%% process(LocalPath, Request) -> ... .

process(["world"], _) ->

or perhaps a type declaration if you prefer. Keeps the code shorter and more legible, I think.

rvirding
Thanks, very clear explanation. I don't see any advantage to pattern matching / testing a formal parameter's value in the function definition vs. testing formal argument's value in the function invocation, where the value tested for is readily apparent.
Gene T