views:

2097

answers:

15

In the spirit of:

  • Hidden Features of C#
  • Hidden Features of Java
  • Hidden Features of ASP.NET
  • Hidden Features of Python
  • Hidden Features of HTML
  • and other Hidden Features questions

What are the hidden features of Erlang that every Erlang developer should be aware of?

One hidden feature per answer, please.

A: 

Hot code loading. From wiki.

Code is loaded and managed as "module" units, the module is a compilation unit. The system can keep two versions of a module in memory at the same time, and processes can concurrently run code from each.

The versions are referred to the "new" and the "old" version. A process will not move into the new version until it makes an external call to its module.

Ólafur Waage
How is this a hidden feature? A notable feature for sure, but this is one of the language's primary boasting points, not hidden at all.
ryeguy
+15  A: 

The magic commands in the shell. The full list is in the manual, but the ones I use most are:

  • f() - forget all variables
  • f(X) - forget X
  • v(42) - recall result from line 42
  • v(-1) - recall result from previous line
  • e(-1) - reexecute expression on previous line
  • rr(foo) - read record definitions from module foo
  • rr("*/*") - read record definitions from every module in every subdirectory
  • rp(expression) - print full expression with record formating
legoscia
And using rp(expression(...)) to have the result printed out without pretty-printing too deeply nested structures, instead it prints it fully
Christian
1+ for rp, Thanks
Abhijith
+9  A: 

user_default.erl - you can build your own shell builtins by having a compiled user_default.beam in your path which can be pretty nifty

mog
+3  A: 

.erlang can preload libraries and run commands on a shells startup, you can also do specific commands for specific nodes by doing a case statement on node name.

mog
+6  A: 

.erlang_hosts gives a nice way to share names across machines

mog
+8  A: 

beam_lib:chunks can get source code from a beam that was compiled with debug on which can be really usefull

{ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Beam,[abstract_code]).
  io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).
mog
+19  A: 

Inheritance! http://www.erlang.se/euc/07/papers/1700Carlsson.pdf

Parent

-module(parent).
-export([foo/0, bar/0]).

foo() ->
    io:format("parent:foo/0 ~n", []).

bar() ->
    io:format("parent:bar/0 ~n", []).

Child

-module(child).
-extends(parent).
-export([foo/0]).

foo() ->
    io:format("child:foo/0 ~n", []).

Console

23> parent:foo().
parent:foo/0 
ok
24> parent:bar().
parent:bar/0 
ok
25> child:foo().
child:foo/0 
ok
26> child:bar().
parent:bar/0 
ok
bjnortier
Didn't know that, very useful, thanks!
Dinu Florin
Yup. Interesting! Although I haven't seen it in any libraries I've used to date...
bjnortier
However it's not welcomed to use parameterized modules: They add variables to functions and it's not good when it comes to debug them. They break the functional paradigm adding a layer of complexity introduced by variables you should keep track of (like global variables in imperative languages), they are immutable but destroy transparency. There've been the thoughts that they (parameterized modules) still exist in the language **only** because of products utilizing them, mochiweb is an example. Just think, why appeared in 2003 they still officially undocumented?
Yasir Arsanukaev
This comment belongs to the "Parameterized Modules" answer...
bjnortier
+13  A: 

Parameterized Modules! From http://www.lshift.net/blog/2008/05/18/late-binding-with-erlang and http://www.erlang.se/euc/07/papers/1700Carlsson.pdf

-module(myclass, [Instvar1, Instvar2]).
-export([getInstvar1/0, getInstvar2/0]).
getInstvar1() -> Instvar1.
getInstvar2() -> Instvar2.

And

Eshell V5.6  (abort with ^G)
1> Handle = myclass:new(123, 234).
{myclass,123,234}
2> Handle:getInstvar1().
123
3> Handle:getInstvar2().
234
bjnortier
I spotted this when I was trying to grok the mochiweb source. Took a while to google what the hell it was actually doing, as the syntax was totally different to the Erlang I've seen before.
madlep
It's pretty interesting! I also saw it for the first time in mochiweb. Combining this with inheritance could create some interesting possibilities...
bjnortier
For the case you wonders the downvotes, this was an accident, please check [this meta topic](http://meta.stackoverflow.com/questions/50035/accidental-voting). I'll edit your question so that they can be removed.
BalusC
+4  A: 

That match specifications can be built using ets:fun2ms(...) where the Erlang fun syntax is used and translated into a match specification with a parse transform.

1> ets:fun2ms(fun({Foo, _, Bar}) when Foo > 0 -> {Foo, Bar} end).
[{{'$1','_','$2'},[{'>','$1',0}],[{{'$1','$2'}}]}]

So no fun-value is ever built, the expression gets replaced with the match-spec at compile-time. The fun may only do things a match expression could do.

Also, ets:fun2ms is available for usage in the shell, so fun-expressions can be tested easily.

Christian
+3  A: 

The gen___tcp and ssl sockets have a {packet, Type} socket option to aid in decoding a number of protocols. The function erlang:decode_packet/3 has a good description on what the various Type values can be and what they do.

Together with a {active, once} or {active, true} setting, each framed value will be delivered as a single message.

Examples: the packet http mode is used heavily for iserve and the packet fcgi mode for ifastcgi. I can imagine that many of the other http servers use packet http as well.

Christian
+1  A: 

It is possible to define your own iterator for QLC to use. For example, a result set from an SQL query could be made into a QLC table, and thus benefit from the features of QLC queries.

Besides mnesia tables, dets and ets have the table/1,2 functions to return such a "Query Handle" for them.

Christian
+5  A: 

Ports, external or linked-in, accept something called io-lists for sending data to them. An io-list is a binary or a (possibly deep) list of binaries or integers in the range 0..255.

This means that rather than concatenating two lists before sending them to a port, one can just send them as two items in a list. So instead of

"foo" ++ "bar"

one do

["foo", "bar"]

In this example it is of course of miniscule difference. But the iolist in itself allows for convenient programming when creating output data. io_lib:format/2,3 itself returns an io list for example.

The function erlang:list_to_binary/1 accepts io lists, but now we have erlang:iolist_to_binary/1 which convey the intention better. There is also an erlang:iolist_size/1.

Best of all, since files and sockets are implemented as ports, you can send iolists to them. No need to flatten or append.

Christian
A: 

Not so hidden, but one of the most important aspects, when chosing Erlang as platform for development:

  • Possibility of enhanced tracing on live nodes (in-service) and being one of the best in debugging!
Dlf
+1  A: 

You can hide an Erlang node by starting it with:

erl -sname foo -hidden

You can still connect to the node, but it won't appear in the list returned by nodes/0.

Roberto Aloi
+2  A: 

Not necessarily "hidden", but I don't see this often. Anonymous functions can have multiple clauses, just like module functions, i.e.

-module(foo).
-compile(export_all).

foo(0) -> "zero";
foo(1) -> "one";
foo(_) -> "many".

anon() ->
    fun(0) ->
            "zero";
       (1) ->
            "one";
       (_) ->
            "many"
    end.


1> foo:foo(0).
"zero"
2> foo:foo(1).
"one"
3> foo:foo(2).
"many"

4> (foo:anon())(0).
"zero"
5> (foo:anon())(1).
"one"
6> (foo:anon())(2).
"many"
bjnortier