j教你如何用erlang-tuple
元组是用来保存一组数据元素的复合数据类型,其中数据元素是要求为erlang的数据类型,单不一定要是相同的类型,元组使用封闭的花括号{}来定义,里面的元素有逗号隔开。
例如: 1> {1,2,3}.
2> {1,{2,3},4}.
3> {1,[2,3],4}.
4> {1,"23",4}.
tuple 的bifs函数:
erlang:tuple_size(Tuple) ->Length. Tuple 的长度
erlang:element(i,Tuple) -> aton(). 选择第i个位置的元素
erlang:setelement(i,Tuple,Aton) ->Tuple2, 修改Tuple中的第i个位置的值为Aton。
参考lists,得出一些类似lists的函数:
-module(com_record).
%% ====================================================================
%% API functions
%% ====================================================================
-export([map/2,
get_name/1,
foreach/2,
foldl/3,
foldl2/4,
foldl_index/4,
merge/3,
merge/4,
any/2,
any/3,
tuple_merge/3,
put_pd_fields/2,
get_pd_fields/2
]).
-spec any(Pred, T) -> boolean() when
Pred :: fun((Elem::term() ) -> boolean()),
T :: tuple().
%% @doc like lists:any/1
any(Pred, Tuple) ->
any(Pred, Tuple, 2).
any(_, {}, _) -> false;
any(Pred, Tuple, Begin) ->
S = tuple_size(Tuple),
if S < Begin ->
false;
true ->
any__(Pred, Tuple, Begin, S)
end.
any__(Pred, Tuple, M, M) ->
Pred(element(M, Tuple));
any__(Pred, Tuple, N, M) ->
case Pred(element(M, Tuple)) of
true ->
true;
_ ->
any__(Pred, Tuple, N+1, M)
end.
%% @doc record map
-spec map(Func, Record) -> Record2 when
Record :: Tuple,
Record2 :: Tuple,
Func :: fun((term()) -> term()),
Tuple :: tuple().
map(Func, Record) ->
[Name| List] = erlang:tuple_to_list(Record),
List2 = lists:map(Func, List),
erlang:list_to_tuple([Name | List2]).
-compile({inline, [get_name/1]}).
%% @doc get record name.
-spec get_name(tuple()) -> atom().
get_name(Record) ->
erlang:element(1, Record).
%% @doc foreach element not include name.
-spec foreach(Fun, Record) -> ok when
Fun :: fun((term()) -> _),
Record :: tuple().
foreach(Fun, Record) when is_tuple(Record) ->
com_util:for(2, erlang:tuple_size(Record), Fun).
%% @doc foldl element not include name.
-spec foldl(Fun, Acc0, Record) -> Acc1 when
Fun :: fun((term(), AccIn) -> AccOut),
Acc0 :: term(),
Acc1 :: term(),
AccIn :: term(),
AccOut :: term(),
Record :: tuple().
%% @doc not aceess record name.
foldl(Func, Acc, Record) when is_function(Func,2) ->
case erlang:tuple_size(Record) of
1 -> Acc;
M ->
foldl_(Func, Acc, Record, 2, M)
end.
foldl2(Func, Acc, Record, Begin)
when is_function(Func, 2) ->
case erlang:tuple_size(Record) of
S when S < Begin -> Acc;
S ->
foldl_(Func, Acc, Record, Begin, S)
end.
foldl_(Func, Acc, Record, N, N) ->
Func(erlang:element(N, Record), Acc);
foldl_(Func, Acc, Record, N, M) ->
foldl_(Func,
Func(erlang:element(N, Record), Acc),
Record, N+1, M).
%% @doc same foldl2 but fun take 3 arg
foldl_index(Func, Acc, Record, Begin) ->
case erlang:tuple_size(Record) of
S when S < Begin -> Acc;
S ->
foldl_index_(Func, Acc, Record, Begin, S)
end.
%% @doc merge two same type record with func
%% two record must same type.
%% Fun argument is record elements
%% @usage
%% merage(fun(A,B) -> A + B end, {aa, 1,1,1} , {aa, 3,3,3})
%% -> {aa, 4,4,4}
-spec merge(Fun, Record1, Record2) -> RecordOut when
Fun :: fun((A, B) -> T),
Record1 :: RecordOut,
Record2 :: RecordOut,
RecordOut :: tuple(),
A :: term(),
B :: term(),
T :: term().
merge(Fun, Record1, Record2) when is_function(Fun, 2) ->
merge__(Fun, Record1, Record2, 2, {get_name(Record1)}).
merge(Fun, Record1, Record2, Begin) when is_function(Fun, 2) ->
merge__(Fun, Record1, Record2, Begin, {get_name(Record1)}).
tuple_merge(Fun, T1, T2) ->
merge__(Fun, T1, T2, 1, {}).
merge__(Fun, T1, T2, Begin, Acc) ->
com_util:fold(Begin,
erlang:tuple_size(T1),
fun(Index, RecordOut) ->
erlang:append_element(RecordOut,
Fun(erlang:element(Index, T1),
erlang:element(Index, T2)))
end,
Acc
).
foldl_index_(Func, Acc, Record, N, N) ->
Func(N, erlang:element(N, Record), Acc);
foldl_index_(Func, Acc, Record, N, M) ->
foldl_index_(Func,
Func(N, erlang:element(N, Record), Acc),
Record, N+1, M).
%% HACK 最好的元转换
%% @doc 存入进程字典 每个filed 都会在前面加上pd_ 的前缀
%% 每个进程字典都只能是单次赋值
put_pd_fields(Record, FieldsName)
when erlang:is_list(FieldsName),
erlang:is_tuple(Record) ->
lists:foldl(fun(FName, Index) ->
case erlang:put(erlang:list_to_atom("pd_" ++ erlang:atom_to_list(FName)),
erlang:element(Index, Record))
of
undefined -> ok;
Ov -> io:format("ERR recrod_put ~p not first ~p\n", [FName, Ov])
end,
Index+1
end,
2,
FieldsName).
%% @doc Record
-spec get_pd_fields(RecordName, [atom()]) -> RecordOut when
RecordName :: atom(),
RecordOut :: tuple().
get_pd_fields(RecordName, FieldsName)
when erlang:is_list(FieldsName) ->
lists:foldl(fun(FName, R) ->
erlang:append_element(R,
erlang:get(erlang:list_to_atom("pd_" ++ erlang:atom_to_list(FName))))
end,
{RecordName},
FieldsName).
%%%%%% TEST unit
%-define(TEST, 1).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-record(tt, {id, name, age}).
pd_fields_test() ->
R= #tt{id=32, name= <<"feof">>, age=[1,2,4]},
put_pd_fields(R, record_info(fields, tt)),
?assertEqual(32, get(pd_id)),
?assertEqual(<<"feof">>, get(pd_name)),
?assertEqual([1,2,4], get(pd_age)),
R2 = get_pd_fields(tt, record_info(fields, tt)),
?assertEqual(R2, R),
ok.
-endif.
j教你如何用erlang-tuple的更多相关文章
- 教你如何用PS制作多款按钮UI设计教程
教你如何用PS制作多款按钮UI设计教程 本文教大家制作按钮的方法 LV. ★ 初入设计,学做按钮.只会套个底色,加个阴影,字体纯白,小聪明的弄个圆角. LV. ★★(描边.字体.内阴影) 看了很多案例 ...
- 说说erlang tuple和record结构
erlang有两种复合结构.tuple和list,两者的区别是tuple子元素的个数是固定不变的.声明后就不能改变了.而list是可变的,能够通过[H|T]来取出或插入新元素. record有点像C/ ...
- 从原理到代码:大牛教你如何用 TensorFlow 亲手搭建一套图像识别模块 | AI 研习社
从原理到代码:大牛教你如何用 TensorFlow 亲手搭建一套图像识别模块 | AI 研习社 PPT链接: https://pan.baidu.com/s/1i5Jrr1N 视频链接: https: ...
- 一篇文章教你如何用R进行数据挖掘
一篇文章教你如何用R进行数据挖掘 引言 R是一种广泛用于数据分析和统计计算的强大语言,于上世纪90年代开始发展起来.得益于全世界众多 爱好者的无尽努力,大家继而开发出了一种基于R但优于R基本文本编辑器 ...
- 零元学Expression Design 4 - Chapter 5 教你如何用自制笔刷在5分钟内做出设计感效果
原文:零元学Expression Design 4 - Chapter 5 教你如何用自制笔刷在5分钟内做出设计感效果 本章将教你如何运用笔刷与简单线条,只要5分钟,就能做出设计感效果 ? 本章将教你 ...
- Android | 教你如何用华为HMS MLKit 图像分割 SDK开发一个证件照DIY小程序
Android | 教你如何用华为HMS MLKit 图像分割 SDK开发一个证件照DIY小程序 引子 上期给大家介绍了如何使用如何用华为HMS MLKit SDK 三十分钟在安卓上开发一个微笑抓 ...
- Android | 教你如何用代码一键实现银行卡绑定
前言 小编前面几期文章分别给大家介绍了用代码实现微笑抓拍.证件照DIY.拍照翻译的功能开发(链接见文章末尾),本次小编给大家带来的是用代码一键实现银行卡识别与绑定功能. 银行卡识别的应用场景 ...
- 手把手教小白如何用css+js实现页面中图片放大展示效果
1.前言 很多童鞋会在项目中遇到一些上传图片,展示图片的操作,但是图片呢有大有小,为了页面的美观,有时候我们需要将图片展示成固定宽高度,但是呢,领导就会说,我想看大图片,怎么办?想看就看呀, ...
- 一篇文章教你如何用 Python 记录日志
前言: 这篇文章是我copy别人的,但是个人认为讲的真的很细致,有原理有实例,不仅仅只教你如何使用日志更会叫你知道日志的原理,真的非常棒,虽然文章很长,也许你不会认认真真读完, 但是当你遇到问题时这篇 ...
随机推荐
- JavaScript 字典
JavaScript 字典 字典以 key value 形式出现 使用: a = {'k1':'v1,''k2':'v2'} 获取值: a['k1'] 获取值:v1
- Python 进程间数据交互
进程间通信:进程之间必须需要中间件. 不同进程间内存是不共享的,要想实现两个进程间的数据交换 Queues:实现传输两个进程的数据 线程queue,访问数据只能在一个进程内进行线程与线程之间的 ...
- linux 英汉词典程序shell+postgresql版
在linux控制台下工作,有时候遇到不懂的单词,想要找个linux下的词典程序,搜寻无果,只好自己动手写个了. 首先获取词典文本文件,在github上找到一个 建立数据库 create databas ...
- BZOJ 2759 一个动态树好题(动态树)
题意 https://www.lydsy.com/JudgeOnline/problem.php?id=2759 思路 每个节点仅有一条有向出边, 这便是一棵基环内向树,我们可以把它在 \(\text ...
- JavaScript(数组、Date、正则)
数组 创建数组 // 一.自变量创建数组 // 1-通过字面量创建一个空数组 var arr1 = []; console.log(arr1) console.log(typeof arr1); // ...
- 【依赖注入】Unity和Autofac
全面理解ASP.NET Core依赖注入:https://www.cnblogs.com/jesse2013/p/di-in-aspnetcore.html MSDN:https://docs.mic ...
- 最长公共前缀(java实现)
题目: 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow& ...
- SpringBoot 配置阿里巴巴Druid连接池
在Spring Boot下默认提供了若干种可用的连接池(dbcp,dbcp2, tomcat, hikari),当然并不支持Druid,Druid来自于阿里系的一个开源连接池,它提供了非常优秀的监控功 ...
- Spring Boot读取配置的几种方式
读取application文件 在application.yml或者properties文件中添加: info.address=USAinfo.company=Springinfo.degree=hi ...
- vue 模仿机票自定义日历组件,区间选择
1.创建组件 components > calander > index.vue <template> <div class="page" v-if ...