`
hideto
  • 浏览: 2650063 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

介绍Erlang里的Record

阅读更多
原文: Erlang: An Introduction to Records

在Erlang内部只有两种混合的数据类型:List和Tuple,而这两种都不支持命名访问,所以如果没有额外的库的话想创建像PHP、Ruby或Python中的关联数组(Ruby中的Hash)是不可能的
在Ruby中我可以这样做:
server_opts = {:port => 8080, :ip => '127.0.0.1', :max_connections => 10}

在Erlang的语法级别不支持这种表达

为了避免这种限制,Erlang虚拟机提供了一个伪数据类型,称为Record
Record支持命名访问,后面我们会看到为什么我们称之为“伪”数据类型

定义Record
Record更类似于C中的struct,而不是关联数组,后者必须一开始就定义好内容并且只能保持数据
这里是一个服务器的连接选项的Record例子:
-module(my_server).

-record(server_opts,
  {port,
  ip="127.0.0.1",
  max_connections=10}).

% The rest of your code goes here.

Record使用-record指令来声明,第一个参数是Record的名字,第二个参数是一个Tuple,Tuple包含了Record里的field和默认值
在这里我们定义了server_opts这个Record,它有三个field:端口、IP和最大连接数
没有默认的port,ip默认值为"127.0.0.1",max_connections默认值为10

创建Record
Record通过使用#符号来创建,下面是创建server_opts这个Record的实例的合法方式:
Opts1 = #server_opts{port=80}.

这段代码创建了一个server_opts Record,port设置为80,其他field使用默认值
Opts2 = #server_opts{port=80, ip="192.168.0.1"}.

这段代码创建了一个server_opts Record,但是ip设置为"192.168.0.1"

简而言之,当创建一个Record时,你可以包含任何field,省略的field将使用默认值

访问Record
Record的访问方式很笨拙,如果我想访问port这个field,我可以这样做:
Opts = #server_opts{port=80, ip="192.168.0.1"},
Opts#server_opts.port

每次你想访问一个Record时你都必须包含Record的名字,为什么要这样?
因为Record不是真正的内部数据类型,它只是编译器的小把戏。

在内部,Record是Tuple,如下:
{server_opts, 80, "127.0.0.1", 10}

编译器将Record的名字映射到Tuple里面
Erlang虚拟机记录了Record的定义,而编译器将所有的Record逻辑翻译为Tuple逻辑
因此,根本就没有Record类型,所以每次你访问一个Record时你必须告诉Erlang我们在用哪个Record(为了编译器爽,程序员变的很不爽)

更新Record
更新Record和创建Record很类似:
Opts = #server_opts{port=80, ip="192.168.0.1"},
NewOpts = Opts#server_opts{port=7000}.

这里首先创建一个server_opts Record
NewOpts = Opts#{port=7000}创建了一个Opts的副本,并指定port为7000并绑定到NewOpts

匹配Record和Guard语句
不谈模式匹配就不算Erlang
让我们来看看一个例子:
handle(Opts=#server_opts{port=8000}) ->
  % do special port 8080 stuff
handle(Opts=#server_opts{} ->
  % default stuff

Guard语句和上面的类似,例如绑定小于1024的端口通常需要root权限,所以我们可以这样做:
handle(Opts) when Opts#server_opts.port <= 1024 ->
  % requires root access
handle(Opts=#server_opts{}) ->
  % Doesn't require root access


使用Record
在我使用Erlang的有限的时间里,我发现Record主要用在两种场景
首先,Record用来保存状态,特别是在使用gen_server的behaviour时
由于Erlang不能全局保持状态,所以状态必须在方法之前传来传去
然后,Record可以用来保存配置选项,这可以认为是第一点的子集
尽管如此,Record也有一些限制,最明显的是不能在运行时添加和删除field,这和C的struct一样,Record的结构必须预先定义
如果你想在运行时添加和删除field,或者你在运行时才能确定有哪些field,这时你应该使用dict而不是Record
分享到:
评论

相关推荐

    <27>erlang record

    NULL 博文链接:https://ZacMa.iteye.com/blog/1976833

    Erlang中的Record详解

    主要介绍了Erlang中的Record详解,本文讲解了定义Record、创建Record、访问Record、更新Record、匹配Record和Guard语句、使用Record等内容,需要的朋友可以参考下

    erlang_protobuffs

    主要看readme,里面详细讲解了如何解析消息的定义格式,生成相应的record。

    erlang-task-queue:Erlang 任务队列行为

    Erlang 任务队列行为模块示例: -module(bruteforce_worker).-behaviour(task_queue).-export([ init/1, process_task/2, terminate/2, code_change/3 ]).-record(state, {}).init(_Args) -&gt; #state{}.process_task...

    Eralng Maps设计原由

    Erlang Maps设计原由。17版后,还是需要多了解这个maps的。

    Erlang中的基本元素操作小结

    主要介绍了Erlang中的基本元素操作小结,本文讲解了元组(tuple)、记录(record)、列表(list)、映射组(map)等内容,需要的朋友可以参考下

    erlang日志应用log4erl(非sasl)

    - If you run change_log_format/1,2 and appender crashed, a restart from the supervisor will not record the latest format used. It will only use either the default format or the format used in the ...

    erl_aliases:为 Erlang 记录和模块名称定义(较短的)别名

    概述 erl_aliases是一个 Erlang 解析转换库,它提供了一个简单直接的接口,用于为(较长)记录和模块名称定义(较短)别名。 定义后,可以使用别名代替原始名称。 基本原理 ... - record ( long_recor

    emysql:Erlang MySQL驱动程序

    该叉子将不再维护。 积极的发展已移至: 用法启动应用程序 application:start(emysql)....主机= string() 端口= integer() 数据库= string() 编码= atom() emysql:add_pool...记录类型 -record(ok_packet, {seq_nu

    erlang mnesia 数据库基本查询

    Mnesia是一个分布式数据库管理系统,适合于电信和其它需要持续运行和具备软实时特性的Erlang应用,越来越受关注和使用,但是目前Mnesia资料却不多,很多都只有官方的用户指南。下面的内容将着重说明 如何做 Mnesia ...

    jeson:用于erlang的JSON序列化器

    #杰森安装make sudo make install杰森模块功能jeson:gen_decoder(Type_list, Field_name, Record_name) :生成将json字符串转换为erlang记录的函数。 必须指定记录的结构以生成函数: Type_list是记录中每个字段的...

    Mnesia User's Guide

    Examples are included how to start an Erlang session, specify a Mnesia database directory, initialize a database schema, start Mnesia, and create tables. Initial prototyping of record definitions is ...

    httpc::satellite_antenna:向HTTP服务器发出请求

    绑定到Erlang的内置HTTP客户端httpc 。 import gleam / httpc import gleam / http.{Get} import gleam / should pub fn main () { // Prepare a HTTP request record let req = http. default_req () | &gt; ...

    forecast:predict.io 包装器

    预报用于天气服务的Erlang API。用FORECAST_API_KEY来自forecast.io 的前期免费注册,必须在环境中设置 $ export FORECAST_API_KEY=...从外壳使用 $ make$ make run...% Optionally load record def1&gt; rr("include/...

    slg-csv:处理游戏服务器中csv文件到ets表的映射

    slg_csv提供csv文件到ets...csv_record首先定义以下宏,下面会使用该宏-define(csv_record(Name), {Name, record_info(fields, Name)}).简单映射定义record为:%% vip经验配置,默认为0级.-record(gd_vip_exp, { level,

    statman_graphite:将状态从statman推送到石墨主机

    Statman-&gt;石墨 该库将通过收集的指标通过TCP推送到石墨主机。 对于statman直方图,仅将百分位作为数据点推送到石墨。...record_some_statman_stats (). 您可以使用prefix应用程序变量来设置全局前缀,

    ebunny_pool:一个rabbitmq工作池

    ebunny_pool 这是一个简单的库,允许您实现 worker。 它将自动声明所需的交换和队列,并为其创建一个 ,因此可以在指定的时间间隔后重试失败的任务...- record ( state , {}). init ( Options ) -&gt; { ok , # state {

Global site tag (gtag.js) - Google Analytics