将布尔值分配给 Erlang 中的原子或变量
Assign boolean to a atom or variable in Erlang
我刚刚学会了编程并且对 Java 感觉很舒服......到目前为止。但现在我在学校有一项作业,我们使用 Erlang。我有一些问题。
所以,我有 3 个简单的(我认为)问题:
我想像您在 Java 中那样将布尔值分配给变量(或原子?)。这可能吗?
在我下面的代码中,checkTheExistance 函数 returns 一个元组 {State, boolean}。接下来我将把它分配给另一个元组:{NextState, DoExist} 这对吗?我可以把布尔值放在 DoExist 中吗?
然后,我想检查 case 语句中的布尔值。并基于布尔值做一些事情。
希望你能理解我的问题。谢谢你。
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};
你可以给一个变量赋一个布尔值,但是你不能"assign"一个原子,一个原子已经是一个原子类型的值。顺便说一下,Erlang 没有布尔类型,true 和 false 是用于此目的的 2 个普通原子。
{State, Boolean} 赋值给 {NextState, DoExist} 是合法的。这是模式匹配的一个很好的例子。这样做你验证答案是一个 2 项元组,并且你分配变量 NexState 和 DoExist。
case语句也是合法的,但是由于你忽略了case中的NexState这个词,你可以这样写:
case DoExist of
false -> startChannel(Channel),
true -> genserver:request(Channel, {join, Pid})
end
您的问题和摘要同时涉及几个方面。下面的解释很曲折,最终在最后得到答案,到时候你可能已经知道答案了......
第一:风格
我们在 Erlang 中不使用驼峰命名法,因为大写和小写名称之间存在具体的语义区别。所以你的 Java 函数命名习惯 someFunctionName
变成了 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,
这里发生了什么?我们 return 编辑了 原子 。这有点像 return 字符串,但 效率更高 并且在类型规范方面完全明确。实际上,原子是它们自己的类型,它们的意思完全是它们所说的,在程序中仅此而已。
所以 Erlang 中的布尔值是 true
和 false
-- 它们是原子。它们的意思恰好是 "true" 和 "false",就像 has_a_fuzzy_nose
恰好意味着 "has a fuzzy nose" 如果这在程序中有意义的话。有某些函数接受原子 "true" 和 "false",布尔运算符当然也接受这些值,但是没有什么使它们与 任何其他原子 在语言中。在 Erlang 中,您可以创建更多的复数逻辑布尔值(有时这非常有用),例如 maybe
、has
、lacks
、incomplete
、next
、end
等等。
第三:=
是赋值和断言
Erlang 程序的每一行通常都是对值的赋值或断言(匹配)。这里的重点是始终知道您正在处理好的数据,如果不是,则崩溃。一个很好的例子是 wrapped values,您会在各处看到它。典型的例子是任何有副作用的函数,通常 return {ok, Value}
或 {error, Reason}
.
在代码中处理此问题的典型方法是执行以下操作:
{ok, Data} = file:read_file(FileName),
这会在元组形状 returned 上强制断言匹配,然后在原子ok
,然后将读取文件的内容赋值给变量名(标签)Data
——假设Data
在当前执行范围内还没有赋值。在这种情况下,如果 file:read_file/1
已 returned {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
的布尔值 return 分配给变量是完全可以接受的像这样命名 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.
但做起来更简洁:
MyList = [1,2,3,4],
case lists:member(2, MyList) of
true -> io:format("In the list.~n");
false -> io:format("Not in the list.~n")
end.
收盘中...
希望这能解释多于混淆。您现在要做的最重要的事情可能是在 vim 和 erl shell 中游手好闲,看看什么有意义,什么没有。 LYSE 是一本非常好的介绍性指南和参考资料——我强烈建议您通读前几章,以便快速掌握该语言的顺序部分。别害怕,作为一种语言,Erlang 实际上 非常简单 、小巧且可读性强。 (不过,人们使用 Erlang 解决的大规模并发问题本质上是非常庞大的,但这与顺序语言本身无关。)
我刚刚学会了编程并且对 Java 感觉很舒服......到目前为止。但现在我在学校有一项作业,我们使用 Erlang。我有一些问题。
所以,我有 3 个简单的(我认为)问题:
我想像您在 Java 中那样将布尔值分配给变量(或原子?)。这可能吗?
在我下面的代码中,checkTheExistance 函数 returns 一个元组 {State, boolean}。接下来我将把它分配给另一个元组:{NextState, DoExist} 这对吗?我可以把布尔值放在 DoExist 中吗?
然后,我想检查 case 语句中的布尔值。并基于布尔值做一些事情。
希望你能理解我的问题。谢谢你。
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};
你可以给一个变量赋一个布尔值,但是你不能"assign"一个原子,一个原子已经是一个原子类型的值。顺便说一下,Erlang 没有布尔类型,true 和 false 是用于此目的的 2 个普通原子。
{State, Boolean} 赋值给 {NextState, DoExist} 是合法的。这是模式匹配的一个很好的例子。这样做你验证答案是一个 2 项元组,并且你分配变量 NexState 和 DoExist。
case语句也是合法的,但是由于你忽略了case中的NexState这个词,你可以这样写:
case DoExist of false -> startChannel(Channel), true -> genserver:request(Channel, {join, Pid}) end
您的问题和摘要同时涉及几个方面。下面的解释很曲折,最终在最后得到答案,到时候你可能已经知道答案了......
第一:风格
我们在 Erlang 中不使用驼峰命名法,因为大写和小写名称之间存在具体的语义区别。所以你的 Java 函数命名习惯 someFunctionName
变成了 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,
这里发生了什么?我们 return 编辑了 原子 。这有点像 return 字符串,但 效率更高 并且在类型规范方面完全明确。实际上,原子是它们自己的类型,它们的意思完全是它们所说的,在程序中仅此而已。
所以 Erlang 中的布尔值是 true
和 false
-- 它们是原子。它们的意思恰好是 "true" 和 "false",就像 has_a_fuzzy_nose
恰好意味着 "has a fuzzy nose" 如果这在程序中有意义的话。有某些函数接受原子 "true" 和 "false",布尔运算符当然也接受这些值,但是没有什么使它们与 任何其他原子 在语言中。在 Erlang 中,您可以创建更多的复数逻辑布尔值(有时这非常有用),例如 maybe
、has
、lacks
、incomplete
、next
、end
等等。
第三:=
是赋值和断言
Erlang 程序的每一行通常都是对值的赋值或断言(匹配)。这里的重点是始终知道您正在处理好的数据,如果不是,则崩溃。一个很好的例子是 wrapped values,您会在各处看到它。典型的例子是任何有副作用的函数,通常 return {ok, Value}
或 {error, Reason}
.
在代码中处理此问题的典型方法是执行以下操作:
{ok, Data} = file:read_file(FileName),
这会在元组形状 returned 上强制断言匹配,然后在原子ok
,然后将读取文件的内容赋值给变量名(标签)Data
——假设Data
在当前执行范围内还没有赋值。在这种情况下,如果 file:read_file/1
已 returned {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
的布尔值 return 分配给变量是完全可以接受的像这样命名 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.
但做起来更简洁:
MyList = [1,2,3,4],
case lists:member(2, MyList) of
true -> io:format("In the list.~n");
false -> io:format("Not in the list.~n")
end.
收盘中...
希望这能解释多于混淆。您现在要做的最重要的事情可能是在 vim 和 erl shell 中游手好闲,看看什么有意义,什么没有。 LYSE 是一本非常好的介绍性指南和参考资料——我强烈建议您通读前几章,以便快速掌握该语言的顺序部分。别害怕,作为一种语言,Erlang 实际上 非常简单 、小巧且可读性强。 (不过,人们使用 Erlang 解决的大规模并发问题本质上是非常庞大的,但这与顺序语言本身无关。)