Functional programming Erlang:以N为单位遍历N个区域
我希望遍历一个NxN区域,给定起始点X,Y和要遍历的正方形的大小。例如,给定X=10,Y=12,Size=2-我想生成10,10;10,11 ; 11,10和11,11 我想到了这个,但它似乎无限地继续下去:Functional programming Erlang:以N为单位遍历N个区域,functional-programming,erlang,Functional Programming,Erlang,我希望遍历一个NxN区域,给定起始点X,Y和要遍历的正方形的大小。例如,给定X=10,Y=12,Size=2-我想生成10,10;10,11 ; 11,10和11,11 我想到了这个,但它似乎无限地继续下去: traverse({X,Y,Xend,Yend}) -> % print X,Y values here.... case (X == Xend-1) andalso (Y == Yend-1) of true ->
traverse({X,Y,Xend,Yend}) ->
% print X,Y values here....
case (X == Xend-1) andalso (Y == Yend-1) of
true ->
ok;
_->
case (Y < Yend-1) of
true ->
traverse({X,Y+1,Xend,Yend});
_->
traverse({X+1,Y,Xend,Yend})
end
end.
我做错了什么?实际上,我对函数范式还不熟悉,我试着在C语言上实现它,用“return”代替上面的“ok”,效果不错,但我猜,我对“函数”的思考还不够多 试试这个:
traverse({X,Y,Xend,Yend}) ->
dotraverse(X, Y, Xend, Yend, _StartX=X).
dotraverse({Xend,Yend,Xend,Yend}, SX) ->
ok;
dotraverse({X,Y,Xend,Yend}, SX) when X<Xend ->
%print
dotraverse({X+1, Y, Xend, Yend}, SX);
dotraverse({Xend,Y,Xend,Yend}) ->
dotraverse(SX,Y+1, Xend, Yend}, SX).
遍历({X,Y,Xend,Yend})->
dotraverse(X,Y,Xend,Yend,_StartX=X)。
dotraverse({Xend,Yend,Xend,Yend},SX)->
好啊
当X时的dotraverse({X,Y,Xend,Yend},SX)
%印刷品
dotraverse({X+1,Y,Xend,Yend},SX);
dotraverse({Xend,Y,Xend,Yend})->
dotraverse(SX,Y+1,Xend,Yend},SX)。
注意:未经测试,但你已经了解了它的要点。这是一个来自函数范式新手的好问题。这里更大的错误是代码的构思方式,而不是它不起作用的事实
traverse(X0, Y0, S) ->
[
io:format("coords: ~p~n", [{X,Y}])
|| X <- lists:seq(X0, X0 + S - 1),
Y <- lists:seq(Y0, Y0 + S - 1)
],
ok
因为您来自C语言,所以很自然您会以命令式风格编写代码,因为这就是您的思维方式
在函数式风格中,您必须告诉编译器“您想做什么”,而不是像在命令式语言(如C)中那样告诉编译器“如何做”。Zed给出的示例使用列表理解是正确的方法
编写代码是最好的学习方式,但要确保你也注重功能性思维。实现这一飞跃需要一段时间,但是继续编写代码,最终你会到达目的地
如果你对Erlang很认真,可以阅读Joe Armstrong的书或Cesarini和Thompson的书,或者阅读Erlang.org上的“OTP设计原则用户指南”。这些将帮助你开始以不同的方式思考,所花费的时间将是非常值得的。
dotraverse({X,Y,Xend,Yend},SX)当X==Xend,Y==Yend
时,更多的模式匹配被写成dotraverse({Xend,Yend,Xend,Yend},SX)
@jldupont:same代表最后一个子句;)谢谢,我在你的方法和Zed的方法中实现的都很有趣,但是最后,我还是选择了Zed的方法,非常感谢。使用map()你可以在适当的地方实现:list:map(fun({X,Y})->io:format(“遍历~p,~p~n,[X,Y])end,[{X,Y}|X@Tim,这种方法的缺点是你需要构建整个{X,Y}的列表坐标。但我看不出比使用列表理解有什么好处……然后问题是:“为什么我的方法不起作用”……从技术上讲,你没有回答问题;-)尽管你可以将我的回答解释为“你的方法不起作用,因为你没有这样做”:-)OP明确表示要遍历一个正方形。即使示例中只有一个大小变量。两个变量显然是多余的。我不明白为什么您的代码应该无限期地继续下去。但有一个错误:在内部case语句中,false case应该将Y的值还原为Ystart…除非您允许X=Xend或Y=Yend。在t中您需要礼盒(X>=Xend-1)和礼盒(Y>=Yend-1)。
traverse(X0, Y0, S) ->
[
io:format("coords: ~p~n", [{X,Y}])
|| X <- lists:seq(X0, X0 + S - 1),
Y <- lists:seq(Y0, Y0 + S - 1)
],
ok
1> traverse(10, 12, 2).
coords: {10,12}
coords: {10,13}
coords: {11,12}
coords: {11,13}
ok