可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.
回答1:
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
回答2:
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
回答3:
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
回答4:
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
回答5:
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))]).
回答6:
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.
回答7:
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.
回答8:
.erlang_hosts gives a nice way to share names across machines
回答9:
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"
回答10:
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.
回答11:
.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.
回答12:
If you want to execute more than one expression in a list comprehension, you can use a block. For example:
> [begin erlang:display(N), N*10 end || N <- lists:seq(1,3)].
1
2
3
[10,20,30]
回答13:
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.
回答14:
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!
回答15:
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
.
回答16:
Matching with the append operator:
"pajamas:" ++ Color = "pajamas:blue"
Color now has the value "blue". Be aware that this trick has it’s limitations - as far as I know it only works with a single variable and a single constant in the order given above.
回答17:
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.