在 Erlang 中重写变量
Rewrite variable in Erlang
我正在玩记录和列表。拜托,我想知道如何使用一个变量两次。当我将任何值分配给变量 _list 然后我尝试重写这个变量然后引发错误:
** exception error: no match of right hand side value
-module(hello).
-author("anx00040").
-record(car, {evc, type, color}).
-record(person, {name, phone, addresa, rc}).
-record(driver, {rc, evc}).
-record(list, {cars = [], persons = [], drivers = []} ).
%% API
-export([helloIF/1, helloCase/1, helloResult/1, helloList/0, map/2, filter/2, helloListCaA/0, createCar/3, createPerson/4, createDriver/2, helloRecords/0, empty_list/0, any_data/0, del_Person/1, get_persons/1, do_it_hard/0, add_person/2]).
createCar(P_evc, P_type, P_color) -> _car = #car{evc = P_evc, type = P_type, color = P_color}, _car
.
createPerson(P_name, P_phone, P_addres, P_rc) -> _person= #person{name = P_name, phone = P_phone, addresa = P_addres, rc = P_rc}, _person
.
createDriver(P_evc, P_rc) -> _driver = #driver{rc = P_rc, evc = P_evc}, _driver
.
empty_list() ->
#list{}.
any_data() ->
_car1 = hello:createCar("BL 4", "Skoda octavia", "White"),
_person1 = hello:createPerson("Eduard B.","+421 917 111 711","Kr, 81107 Bratislava1", "8811235"),
_driver1 = hello:createDriver(_car1#car.evc, _person1#person.rc),
_car2 = hello:createCar("BL 111 HK", "BMW M1", "Red"),
_person2 = hello:createPerson("Lenka M","+421 917 111 111","Krizn0, 81107 Bratislava1", "8811167695"),
_driver2 = hello:createDriver(_car2#car.evc, _person2#person.rc),
_car3 = hello:createCar("BL 123 AB", "Audi A1 S", "Black"),
_person3 = hello:createPerson("Stela Ba.","+421 918 111 711","Azna 20, 81107 Bratislava1", "8811167695"),
_driver3 = hello:createDriver(_car3#car.evc, _person3#person.rc),
_list = #list{
cars = [_car1,_car2,_car3],
persons = [_person1, _person2, _person3],
drivers = [_driver1, _driver2, _driver3]},
_list.
add_person(List, Person) ->
List#list{persons = lists:append([Person], List#list.persons) }.
get_persons(#list{persons = P}) -> P.
do_it_hard()->
empty_list(),
_list = add_person(any_data(), #person{name = "Test",phone = "+421Test", addresa = "Testova 20 81101 Testovo", rc =88113545}),
io:fwrite("\n"),
get_persons(add_person(_list, #person{name = "Test2",phone = "+421Test2", addresa = "Testova 20 81101 Testovo2", rc =991135455}))
.
但是当我两次使用变量 _list 时出现错误:
do_it_hard()->
empty_list(),
_list = add_person(any_data(), #person{name = "Test",phone = "+421Test", addresa = "Testova 20 81101 Testovo", rc =88113545}),
_list =add_person(_list, #person{name = "Test2",phone = "+421Test2", addresa = "Testova 20 81101 Testovo2", rc =991135455}),
get_persons(_list)
.
我用了google...
Erlang 是一种单一任务语言。也就是说,一旦一个变量被赋予了一个值,它就不能再被赋予一个不同的值。从这个意义上说,它更像是代数而不是最传统的编程语言。
http://www.cis.upenn.edu/~matuszek/General/ConciseGuides/concise-erlang.html
在 REPL 中,重用变量名可以方便地进行实验。在那里,你可以做 f(A).
让 Erlang "forget" 当前赋值 A
.
1> Result = connect("goooogle.com").
{error, "server not found"}
2> % oops! I misspelled the server name
2> f(Result).
ok
3> Result = connect("google.com").
{ok, <<"contents of the page">>}
请注意,这只是 REPL 的一项便利功能。你不能在实际代码中这样做。
在实际代码中,变量只能赋值一次。在过程语言(C、Java、Python 等)中,重新分配的典型用例是循环:
for (int i = 0; i < max; i++) {
conn = connect(servers[i]);
reply = send_data(conn);
print(reply);
}
在上面,变量i
、conn
和reply
在循环的每次迭代中被重新赋值。
函数式语言使用递归来执行它们的循环:
send_all(Max, Servers) ->
send_loop(1, Max, Servers).
send_loop(Current, Max, _Servers) when Current =:= Max->
ok;
send_loop(Current, Max, Servers) ->
Conn = connect(lists:nth(Current, Servers)),
Reply = send_data(Conn),
print(Reply).
这不是很地道的 Erlang;我试图让它反映上面的程序代码。
如您所见,我得到了相同的效果,但我在函数中的赋值是固定的。
附带说明一下,您使用了很多以下划线开头的变量名。在 Erlang 中,这是一种暗示您不会使用这些变量的值的方式。 (就像上面的例子一样,当我到达列表的末尾时,我不关心服务器列表。)在你的代码中使用前导下划线会关闭一些有用的编译器警告,并且会让其他开发人员感到困惑谁看你的代码。
在某些情况下使用 use SeqBind:
会很方便
SeqBind is a parse transformation that auto-numbers all occurrences of these bindings following the suffix @ (creating L@0, L@1, Req@0, Req@1) and so on.
简单示例:
...
-compile({parse_transform,seqbind}).
...
List@ = lists:seq(0, 100),
List@ = lists:filter(fun (X) -> X rem 2 == 0 end, List@)
...
我正在玩记录和列表。拜托,我想知道如何使用一个变量两次。当我将任何值分配给变量 _list 然后我尝试重写这个变量然后引发错误:
** exception error: no match of right hand side value
-module(hello).
-author("anx00040").
-record(car, {evc, type, color}).
-record(person, {name, phone, addresa, rc}).
-record(driver, {rc, evc}).
-record(list, {cars = [], persons = [], drivers = []} ).
%% API
-export([helloIF/1, helloCase/1, helloResult/1, helloList/0, map/2, filter/2, helloListCaA/0, createCar/3, createPerson/4, createDriver/2, helloRecords/0, empty_list/0, any_data/0, del_Person/1, get_persons/1, do_it_hard/0, add_person/2]).
createCar(P_evc, P_type, P_color) -> _car = #car{evc = P_evc, type = P_type, color = P_color}, _car
.
createPerson(P_name, P_phone, P_addres, P_rc) -> _person= #person{name = P_name, phone = P_phone, addresa = P_addres, rc = P_rc}, _person
.
createDriver(P_evc, P_rc) -> _driver = #driver{rc = P_rc, evc = P_evc}, _driver
.
empty_list() ->
#list{}.
any_data() ->
_car1 = hello:createCar("BL 4", "Skoda octavia", "White"),
_person1 = hello:createPerson("Eduard B.","+421 917 111 711","Kr, 81107 Bratislava1", "8811235"),
_driver1 = hello:createDriver(_car1#car.evc, _person1#person.rc),
_car2 = hello:createCar("BL 111 HK", "BMW M1", "Red"),
_person2 = hello:createPerson("Lenka M","+421 917 111 111","Krizn0, 81107 Bratislava1", "8811167695"),
_driver2 = hello:createDriver(_car2#car.evc, _person2#person.rc),
_car3 = hello:createCar("BL 123 AB", "Audi A1 S", "Black"),
_person3 = hello:createPerson("Stela Ba.","+421 918 111 711","Azna 20, 81107 Bratislava1", "8811167695"),
_driver3 = hello:createDriver(_car3#car.evc, _person3#person.rc),
_list = #list{
cars = [_car1,_car2,_car3],
persons = [_person1, _person2, _person3],
drivers = [_driver1, _driver2, _driver3]},
_list.
add_person(List, Person) ->
List#list{persons = lists:append([Person], List#list.persons) }.
get_persons(#list{persons = P}) -> P.
do_it_hard()->
empty_list(),
_list = add_person(any_data(), #person{name = "Test",phone = "+421Test", addresa = "Testova 20 81101 Testovo", rc =88113545}),
io:fwrite("\n"),
get_persons(add_person(_list, #person{name = "Test2",phone = "+421Test2", addresa = "Testova 20 81101 Testovo2", rc =991135455}))
.
但是当我两次使用变量 _list 时出现错误:
do_it_hard()->
empty_list(),
_list = add_person(any_data(), #person{name = "Test",phone = "+421Test", addresa = "Testova 20 81101 Testovo", rc =88113545}),
_list =add_person(_list, #person{name = "Test2",phone = "+421Test2", addresa = "Testova 20 81101 Testovo2", rc =991135455}),
get_persons(_list)
.
我用了google...
Erlang 是一种单一任务语言。也就是说,一旦一个变量被赋予了一个值,它就不能再被赋予一个不同的值。从这个意义上说,它更像是代数而不是最传统的编程语言。
http://www.cis.upenn.edu/~matuszek/General/ConciseGuides/concise-erlang.html
在 REPL 中,重用变量名可以方便地进行实验。在那里,你可以做 f(A).
让 Erlang "forget" 当前赋值 A
.
1> Result = connect("goooogle.com").
{error, "server not found"}
2> % oops! I misspelled the server name
2> f(Result).
ok
3> Result = connect("google.com").
{ok, <<"contents of the page">>}
请注意,这只是 REPL 的一项便利功能。你不能在实际代码中这样做。
在实际代码中,变量只能赋值一次。在过程语言(C、Java、Python 等)中,重新分配的典型用例是循环:
for (int i = 0; i < max; i++) {
conn = connect(servers[i]);
reply = send_data(conn);
print(reply);
}
在上面,变量i
、conn
和reply
在循环的每次迭代中被重新赋值。
函数式语言使用递归来执行它们的循环:
send_all(Max, Servers) ->
send_loop(1, Max, Servers).
send_loop(Current, Max, _Servers) when Current =:= Max->
ok;
send_loop(Current, Max, Servers) ->
Conn = connect(lists:nth(Current, Servers)),
Reply = send_data(Conn),
print(Reply).
这不是很地道的 Erlang;我试图让它反映上面的程序代码。
如您所见,我得到了相同的效果,但我在函数中的赋值是固定的。
附带说明一下,您使用了很多以下划线开头的变量名。在 Erlang 中,这是一种暗示您不会使用这些变量的值的方式。 (就像上面的例子一样,当我到达列表的末尾时,我不关心服务器列表。)在你的代码中使用前导下划线会关闭一些有用的编译器警告,并且会让其他开发人员感到困惑谁看你的代码。
在某些情况下使用 use SeqBind:
会很方便SeqBind is a parse transformation that auto-numbers all occurrences of these bindings following the suffix @ (creating L@0, L@1, Req@0, Req@1) and so on.
简单示例:
...
-compile({parse_transform,seqbind}).
...
List@ = lists:seq(0, 100),
List@ = lists:filter(fun (X) -> X rem 2 == 0 end, List@)
...