在Erlang shell中,我如何自动读取所有记录定义头?

13

这个问题起初是这样的:

每次使用 Erlang shell 时,我都想在启动时运行一些命令,比如:

rr("*.hrl").

或类似的东西。目前我每次启动Erlang shell都必须键入它,我已经厌倦了,而且总是忘记它。

但是这实际上是错误的问题!因为我想要做的实际上是在每个shell任务中读取我的记录定义头文件。而不是使用其他shell内置命令来启动。所以我改变了问题标题以展示应该如何提问这个问题。

3个回答

17

在尝试使用 .erlang 解决问题时,我发现了一个特定的 rr/1 的解决方法:

来自 shell 的 man-page:

shell 提供了一些支持,可以在 shell 中读取和打印记录。在编译期间,记录表达式被翻译为元组表达式。在运行时,不知道元组是否实际上代表记录。编译器使用的记录定义也无法在运行时使用。因此,为了在可能的情况下读取记录语法并将元组打印为记录,必须由 shell 自身维护记录定义。下面描述了用于读取、定义、遗忘、列出和打印记录的 shell 命令。请注意,每个作业都有自己的记录定义集。为了简化事务,在加载新作业时,会读取 shell_default 和 user_default(如果已加载)模块中的记录定义。例如,添加以下行:

  -include_lib("kernel/include/file.hrl").

将 user_default 添加至定义中可以在 shell 中方便地使用 file_info。

为了澄清,我添加了一些示例:

文件 foo.hrl

-record(foo, {bar, baz=5}).

文件:user_default.erl

-module(user_default).
-compile(export_all).

-include("foo.hrl").  % include all relevant record definition headers here

 %% more stuff probably ...

让我们在Shell中尝试一下:

$ erl
Erlang R13B04 (erts-5.7.5) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.5  (abort with ^G)
1> #foo{}.
#foo{bar = undefined,baz = 5}

→ shell 知道来自 foo.hrl 的记录


3
文件.erlang在启动shell时被评估,但它不是在shell的上下文中评估的。这意味着它只能包含被评估的一般表达式而不是shell命令。不幸的是,rr()是一个shell命令(它初始化本地shell数据以识别记录),因此不能在.erlang文件中使用。
虽然用户定义的模块user_default必须预加载,但它可以包括使用-include-include_lib的文件来包含记录定义,但这些记录定义只对在user_default内定义的函数可用。 user_default是一个普通编译模块,在其中导出的函数像其他函数一样调用,因此记录定义在shell中不可见。 user_default允许用户定义更复杂的函数,这些函数可以作为shell命令从shell中调用。
编辑:
我在这里部分错误。虽然我关于如何评估.erlang和如何调用user_default中的函数是正确的,但我错过了在shell启动时扫描user_default.erl以获取记录定义,然后这些记录定义在shell中可用。感谢@Peer Stritzinger指出这一点。

1
你确定吗?手册上的文字似乎说得不一样。为了检查,我设置了一个小测试案例(请参见http://ideone.com/4Gau5)。看起来它似乎是有效的。我有什么遗漏吗? - Peer Stritzinger
1
不,你没有错过任何东西。我正在检查代码,只看到了在shell_defaultuser_default中使用函数,并错过了在Shell启动时对它们的扫描。我的错。 - rvirding

0

对于 rr() 的示例,我很难让它正常工作。首先,如果我只在 .erlang 文件中按照上述方式输入该行,则无法找到 rr/1 函数,而且我不知道 rr/1 函数定义在哪个模块中。另一方面,我也不确定这个函数是否在所有 shell 作业中都可用。 - Peer Stritzinger
1
@Peer Stritzinger: rr() 没有被定义为一个函数;你可以在 stdlib/shell.erl 中的 local_func/7 函数的子句中找到它。 - Zed
@Zed:是的,那就是我的问题,我一直在寻找一种自动调用它的方法。在我的自我回答中找到了解决方法,由于我想不到任何其他需要在启动时使用的shell内置伪函数,所以这个问题对我来说已经解决了。 - Peer Stritzinger
因此,我更改了问题以展示我应该问什么,以使其对其他人有用... - Peer Stritzinger

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