在Erlang中将boolean分配给原子或变量

时间:2017-10-04 11:30:36

标签: erlang boolean variable-assignment

到目前为止,我刚学会编程并对Java感到满意。但是现在我在学校里有一个使用Erlang的作业。哪个我有一些问题。

所以,我有3个简单的(我认为)问题:

  1. 我想像你在Java中那样给变量(或原子?)赋一个布尔值。这可能吗?

  2. 在下面的代码中,checkTheExistance函数返回一个元组{State,boolean}。接下来我将把它分配给另一个元组:{NextState,DoExist}这是正确的吗?我可以将布尔值放在DoExist中吗?

  3. 然后,我想检查case语句中的boolean。并且基于boolean值做一些事情。

  4. 希望您理解我的问题。谢谢。

    handle(State, {join, Pid, Channel}) ->
    
          {NextState, DoExist} = checkTheExistance(Channel, State),
          case {NextState, DoExist} of 
             {_,false} -> startChannel(Channel),
             {_,true} ->  genserver:request(Channel, {join, Pid}) 
          end
         {reply, ok, NextState};
    

2 个答案:

答案 0 :(得分:2)

  • 您可以为变量指定布尔值,但不能“赋值”原子,原子已经是原子类型的值。再见,Erlang没有布尔类型,true和false是用于此目的的2个普通原子。

  • 将{State,Boolean}赋值给{NextState,DoExist}是合法的。这是模式匹配的一个很好的例子。这样做可以验证答案是2个术语元组,并分配变量NexState和DoExist。

  • 案例陈述也是合法的,但是当您在案例中忽略术语NexState时,您可以写:

    case DoExist of 
       false -> startChannel(Channel),
       true ->  genserver:request(Channel, {join, Pid}) 
    end
    

答案 1 :(得分:1)

您的问题和摘要会立即触及几个区域。下面的解释是蜿蜒的,并最终得到答案,到那时你可能已经知道了答案......

第一种:风格

我们不会在Erlang中使用camelCaseNames,因为大写和小写名称之间存在具体的语义区别。因此,命名函数someFunctionName的Java习惯变为some_function_name

第二:州改变

通常我们不会在检查期间改变任何状态。支票是支票,​​状态改变是状态改变。两者不应该混在一起。这就是为什么我们将单一赋值作为语言规则的一部分 - 这样当您在范围内看到变量名时,您查看标签而不是指向存储位置的指针。在一个范围内(一般来说,在一个函数定义,一个lambda或一个列表理解中 - 它不能掩盖外部范围标签)一个标签就意味着你在整个函数中所说的完全没有什么不同。

如果你想检查某些东西,检查一下,并给出检查功能,确切地说它需要做什么工作,并且(通常)不再有:

case check_existence(Channel, State) of
    exists         -> something(State);
    does_not_exist -> something_else(State)
end,

或者,比较差异:

case check_existence(Channel, State) of
    true  -> something(State);
    false -> something_else(State)
end,

这里发生了什么?我们返回了 atoms 。这有点像返回一个字符串,但效率更高,并且在类型规范方面完全明确。实际上,原子是他们自己的类型,他们的意思正是他们所说的,而不是程序中的任何内容。

因此,Erlang中的布尔是truefalse - 它们是原子。他们的确意味着"真实"并且" false",就像has_a_fuzzy_nose正好意味着"有一个模糊的鼻子"如果这在程序中有意义的话。某些函数接受原子" true"当然,布尔运算符接受这些值,但没有任何东西可以使它们与语言中的任何其他原子不同。在Erlang中,您可以创建更多复数逻辑布尔值(有时这非常有用),例如maybehaslacksincompletenext,{ {1}}等等。

第三:end 分配断言

Erlang程序的每一行通常都是值的赋值或断言(匹配)。这里的要点是始终知道您处理好的数据,如果您不是,则会崩溃。一个很好的例子就是包装值,你可以在这里找到它们。典型示例是具有副作用的任何函数,通常返回={ok, Value}

在代码中处理此问题的典型方法是执行以下操作:

{error, Reason}

强制返回元组形状上的断言匹配,然后在原子{ok, Data} = file:read_file(FileName), 上,然后将读取文件的内容分配给变量名称(标签)ok - 假设尚未在当前执行范围内分配Data。在这种情况下,如果Data返回file:read_file/1,则该过程会立即崩溃。

为什么?

因为在标准情况下,我们完全无法控制为什么外部资源(如文件)可能不可用 - 并且需要数千行代码才能正确< / em>处理错误。所以我们只是在那里崩溃并且知道我们没有继续处理坏数据。

关于这些作业......

我们刚看到一项任务,同时也看到了一个断言。完全有可能做一些像这样复杂的事情:

{error, Reason}

这将以更高的复杂成本实现基本相同的效果。将这个(无用的复杂)版本与以下版本进行比较(在语义上相同但更无用的复杂):

Value = file:read_file(FileName),
case Value of
    {ok, Data}      -> do_stuff(Data);
    {error, Reason} -> report_error_and_die(Reason)
end.

现在,记住布尔值{Outcome, Value} = file:read_file(FileName), case Outcome of ok -> do_stuff(Value); error -> report_error_and_die(Value) end. true仅仅是原子,将false的布尔返回值赋给变量名lists:member/2是完全可以接受的。像这样:

Result

但更简洁:

MyList = [1,2,3,4],
Result = lists:member(2, MyList),
case Result of
    true  -> io:format("In the list.~n");
    false -> io:format("Not in the list.~n")
end.

因为我们实际上并不需要在任何地方记住这个名字。 There is, of course, a strong balance between use of labels as implicit documentation (good variable names convey your intent to the next reader of your code) and writing overly verbose code.

结束......

希望这解释的不仅仅是混淆。你现在要做的最重要的事情可能就是在vim和erl shell中徘徊,看看有什么意义,什么没有。 LYSE是一个非常好的介绍性指南和参考 - 我强烈建议您阅读前几章,以便快速掌握语言的顺序部分。不要害怕,Erlang实际上非常容易,小而且可读作为一种语言。 (然而,人们使用Erlang的大量并发问题本质上非常巨大,但这与顺序语言本身无关。)