Erlang的隐藏特性

17

在以下的灵感中:

  • C#的隐藏特性
  • Java的隐藏特性
  • ASP.NET的隐藏特性
  • Python的隐藏特性
  • HTML的隐藏特性
  • 以及其他隐藏特性问题

每个Erlang开发者都应该知道哪些Erlang的隐藏特性?

请每个回答只涉及一个隐藏特性。


7
请将此设置为社区维基。 - Ólafur Waage
1
我建议在这个问题上添加一个“隐藏功能”标签,并将其他语言的隐藏功能注释链接到那些问题上。 - Avihu Turzion
@Olafur 怎么做?帮帮忙! @Avihu 完成了。谢谢你的建议! :) - pageman
17个回答

25

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

父级

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

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

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

子元素

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

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

控制台

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
1
然而,使用参数化模块并不受欢迎:它们向函数添加变量,在调试时不好处理。它们打破了函数式编程范式,引入了一层复杂性,由变量引起(就像命令式语言中的全局变量),它们是不可变的,但破坏了透明度。有人认为,它们(参数化模块)之所以仍然存在于语言中,只是因为使用它们的产品,例如mochiweb。想想看,为什么在2003年出现后它们仍然没有正式记录? - YasirA
1
此注释属于“参数化模块”答案... - bjnortier

19

Shell中的魔术命令。完整列表请参见手册,但我最常用的是:

  • f() - 忘记所有变量
  • f(X) - 忘记X
  • v(42) - 回忆第42行的结果
  • v(-1) - 回忆前一行的结果
  • e(-1) - 重新执行前一行的表达式
  • rr(foo) - 从模块foo读取记录定义
  • rr("*/*") - 从每个子目录中的每个模块读取记录定义
  • rp(expression) - 使用记录格式打印完整表达式

2
使用rp(expression(...))可以将结果输出而无需进行过于深层嵌套结构的漂亮打印,它会完全打印出结果。 - Christian

14

1
当我试图理解Mochiweb源代码时,我发现了这个。由于语法与我之前见过的Erlang完全不同,所以花费了一段时间来搜索它实际上在做什么。 - madlep
1
这很有趣!我也是在mochiweb中第一次看到它。将其与继承结合起来可能会创造出一些有趣的可能性... - bjnortier
如果您好奇为什么会有人给您的帖子投反对票,那只是一个意外,请查看这个Meta话题。我将编辑您的问题,以便这些反对票可以被移除。 - BalusC

12

通过在您的路径中编译一个 user_default.beam,您可以构建自己的 shell 内置程序,这非常方便。


10

beam_lib:chunks可以从启用调试信息的beam文件中获取源代码,这非常有用。

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

9

端口,无论是外部的还是链接进来的,都接受称为 io 列表的东西来将数据发送给它们。io 列表是二进制或者是一个(可能是深层嵌套的)二进制或整数列表(0 到 255 范围内)。

这意味着与其在发送给端口之前将两个列表拼接在一起,我们只需将它们作为列表中的两个项直接发送即可。因此,与其这样:

"foo" ++ "bar"

一次操作

["foo", "bar"]

在这个例子中,当然只是微小的差异。但iolist本身允许在创建输出数据时进行便捷编程。例如,io_lib:format/2,3本身返回一个io列表。
函数erlang:list_to_binary/1接受io列表,但现在我们有了erlang:iolist_to_binary/1,它更好地传达了意图。还有一个erlang:iolist_size/1。
最重要的是,由于文件和套接字被实现为端口,因此您可以将iolists发送到它们。无需展平或附加。

8

可以使用ets:fun2ms(...)来构建符合规格的匹配,其中使用Erlang函数语法,并将其转换为具有解析变换的匹配规范。

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

因此,没有fun-value被建立,表达式在编译时被替换为匹配规范。函数只能执行与匹配表达式相同的操作。

此外,在shell中可以使用ets:fun2ms轻松测试函数表达式。


7

.erlang_hosts提供了一种在多台机器之间共享名称的好方法


6

不一定是“隐藏”的,但我很少见到这种情况。匿名函数可以像模块函数一样具有多个子句,即

-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"

5
gen_tcp和ssl套接字有一个{packet, Type}套接字选项,以帮助解码许多协议。函数erlang:decode_packet/3对各种Type值及其作用有良好的描述。
与{active, once}或{active, true}设置一起使用,每个分帧值将作为单个消息传递。
例如:http包模式在iserve中广泛使用,而fcgi包模式在ifastcgi中使用。我可以想象许多其他http服务器也使用http包。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接