重载函数头中的原子模式匹配

问题描述 投票:0回答:1

简要说明

我正在制作一个空气污染监测系统,您可以在其中添加各种站点、读数,然后读取保存的数据。

问题

我在尝试匹配单个函数中的各种原子时遇到问题。我的代码是:

handleRequest(add_station, {Name, Coordinates}, Monitor) ->
  {add_station(Name, Coordinates, Monitor), ok}.

handleRequest(get_station, {Station}, Monitor) ->
  {StationData, _} = get_station(Station, Monitor),
  {Monitor, StationData}.

但是在这个错误下编译失败:

function handleRequest/3 already defined

使用方法

我想这样调用这个函数:

serverLoop(Monitor) ->
  receive
    {request, Pid, {Action, Payload}} ->
      UpdatedMonitorOrError = handleRequest(Action, Payload, Monitor),
      if
        is_tuple(UpdatedMonitorOrError) ->
          % is a tuple like {error, Message} only in case of error occured, is a list otherwise
          Pid ! {reply, UpdatedMonitorOrError},
          serverLoop(Monitor);
        true ->
          % UpdatedMonitorOrError is a valid Monitor which could be treated as the next state
          Pid ! {reply, Response},
          serverLoop(UpdatedMonitorOrError)
      end
    end.

其中

Action
是某个原子。我想避免创建多个接收模式匹配子句,因为大多数代码都会重复。

请注意,Payload 可以是由基于 Action 原子的各种元素组成的元组,并且该原子应确定 handleRequest 函数的行为。此外,响应可以是单个原子或从函数返回的数据。

其他尝试

我也尝试过,但无济于事:

handleRequest(add_station, Payload, Monitor) ->
  {Name, Coordinates} = Payload,
  {add_station(Name, Coordinates, Monitor), ok}.

handleRequest(get_station, Payload, Monitor) ->
  {Station} = Payload,
  {StationData, _} = get_station(Station, Monitor),
  {Monitor, StationData}.

最终成功了

handleRequest(Action, Payload, Monitor) ->
  case Action of
    add_station ->
      {Name, Coordinates} = Payload,
      {add_station(Name, Coordinates, Monitor), ok};
    get_station ->
      {Station} = Payload,
      {StationData, _} = get_station(Station, Monitor),
      {Monitor, StationData}
  end.

两个问题

  1. 为什么这个原子模式匹配没有按预期工作?
  2. 这是解决这个问题的 Erlang 方式吗?有更好的方法吗?请注意,某个操作可能具有无效的有效负载,然后它应该返回错误并且不要修改存储的数据。
functional-programming erlang pattern-matching
1个回答
0
投票

在 Erlang 中,相同函数的子句必须用分号而不是点分隔:

handleRequest(add_station, {Name, Coordinates}, Monitor) ->
  {add_station(Name, Coordinates, Monitor), ok};
                                           %%  ↑ note ";" instead of "."
handleRequest(get_station, {Station}, Monitor) ->
  {StationData, _} = get_station(Station, Monitor),
  {Monitor, StationData}.
© www.soinside.com 2019 - 2024. All rights reserved.