这个问题起初是这样的:
每次使用 Erlang shell 时,我都想在启动时运行一些命令,比如:
rr("*.hrl").
或类似的东西。目前我每次启动Erlang shell都必须键入它,我已经厌倦了,而且总是忘记它。
但是这实际上是错误的问题!因为我想要做的实际上是在每个shell任务中读取我的记录定义头文件。而不是使用其他shell内置命令来启动。所以我改变了问题标题以展示应该如何提问这个问题。
这个问题起初是这样的:
每次使用 Erlang shell 时,我都想在启动时运行一些命令,比如:
rr("*.hrl").
或类似的东西。目前我每次启动Erlang shell都必须键入它,我已经厌倦了,而且总是忘记它。
但是这实际上是错误的问题!因为我想要做的实际上是在每个shell任务中读取我的记录定义头文件。而不是使用其他shell内置命令来启动。所以我改变了问题标题以展示应该如何提问这个问题。
在尝试使用 .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
的记录
.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指出这一点。.erlang
的文件中,并将该文件放置在您的主目录下(请参阅http://www.erlang.org/documentation/doc-5.2/doc/getting_started/getting_started.html第1.7.1段)。rr()
没有被定义为一个函数;你可以在 stdlib/shell.erl
中的 local_func/7
函数的子句中找到它。 - Zed
shell_default
和user_default
中使用函数,并错过了在Shell启动时对它们的扫描。我的错。 - rvirding