Functional programming Erlang:以N为单位遍历N个区域

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 ->

我希望遍历一个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 -> 
           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