Erlang map 中的非法匹配问题

来源:互联网 发布:人类为何不优化人种 编辑:程序博客网 时间:2024/06/07 08:10

《Programming Erlang》第 5 章有个例子。
通过 map 计算字符串各个字符出现的频率。

代码如下

-module(countChar).-export([count_characters/1]).count_characters(Str) ->    count_characters(Str, #{}).count_characters([H|T],  #{ H => N } = X) ->    count_characters(T, X#{ H := N+1 });count_characters([H|T], X) ->    count_characters(T, X#{ H => 1 });count_characters([], X) ->     X.

运行后一直报错:

错误

找了好一会也没找到错误,于是网上查说是版本错误。

版本
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V6.2 (abort with ^G)

最新版本是Erlang/opt 18.1,我的是Erlang/opt 17

跑到 官网 下载最新版本,发现官网根本进不去,进去也下载不了,网上有人说 Erlang 的官网在瑞典,速度慢的根本不能下载- -,于是跑到群里求助,有个好心的前辈给我发了Erlang 18.1 最新版本。

我传到了云盘上,需要的小伙伴可以去下载哈~
windows Erlang/opt 18.1
Linux Erlang/opt 18.1

然后卸载 17 安装 18。
编译,运行
又出现了如下错误:

这里写图片描述

应该还是版本问题,但是没有找到相关资料,最后在 StackOverFlow 找到了相同的问题。

查了相关资料,得知:
在 Erlang/opt 17中
- No variable keys (key中不能含变量)
- No single value access (不支持取单个value,即不支持#{Key}操作)
- No map comprehensions (不支持map推导,例如 #{X => foggy || X <- [london,boston]}.)

18 中仅得到部分支持

如果我们要使用上述功能,应该运用 Erlang 提供给我们的 maps 模块。

maps:new()
erlang:is_map(M)
maps:is_key(Key, Map)
maps:get(Key, Map)

最后答主贴了 17 版本和 18 版本下可运行的例子:

Erlang/opt 17 版本

-module(count_chars).-export([count_characters/1]).count_characters(Str) ->        count_characters(Str, #{}).%% maps module functions cannot be used as guards (release 17)%% or you'll get "illegal guard expression" errorcount_characters([H|T], X) ->    case maps:is_key(H,X) of        false -> count_characters(T, maps:put(H,1,X));        true  -> Count = maps:get(H,X),                         count_characters(T, maps:update(H,Count+1,X))    end;count_characters([], X) ->        X.

Erlang/opt 18 版本

-module(count_chars).-export([count_characters/1]).count_characters(Str) ->        count_characters(Str, #{}).count_characters([H|T], X) ->    case maps:is_key(H,X) of        false -> count_characters(T, X#{ H => 1 });        true  -> #{ H := Count } = X,                 count_characters(T, X#{ H := Count+1 })    end;count_characters([], X) ->        X.

可见 17 版本中全部使用了 maps 模块中的 API,18 版本只用了 maps:is_key()。

我自己尝试运行 Erlang/opt 18 版本,成功。

这里写图片描述

书中作者的写法可能会在将来版本中支持。
毕竟看起来简洁多了^_^。

0 0
原创粉丝点击