Erlang初学者:寻找周界?

时间:2014-12-16 21:26:48

标签: erlang

我正在学习Erlang并尝试将问题提到here,作为

3. Write a function mathStuff:perimeter(Form) which computes the perimeter of different forms. Form can be one of:

    {square,Side}
    {circle,Radius}
    {triangle,A,B,C}

所以,我对此的解决方案是

-module(mathStuff).
-export([perimeter/1]).

perimeter(Form) ->
        case element(1, Form) of
                square          -> io:format("perimeter for square is ~p~n", [4*element(2, Form)]);
                circle          -> io:format("perimeter for circle is ~p~n", [2*math:pi()*element(2, Form)]);
                triangle        -> io:format("perimeter for triangle ~p~n", [element(2, Form) + element(3, Form) + element(4, Form)])
        end.
~             

当我跑步时,我得到了

38> c("mathStuff.erl").              
{ok,mathStuff}
39> mathStuff:perimeter({circle, 2}).
perimeter for circle is 12.566370614359172
ok
40> mathStuff:perimeter({rectangle, 2}).
** exception error: no case clause matching rectangle
     in function  mathStuff:perimeter/1 (mathStuff.erl, line 5)
41> mathStuff:perimeter({square, 2}).   
perimeter for square is 8
ok
42> mathStuff:perimeter({traingle, 1, 2, 3}).
** exception error: no case clause matching traingle
     in function  mathStuff:perimeter/1 (mathStuff.erl, line 5)
43> mathStuff:perimeter({triangle, 1, 2, 3}).
perimeter for triangle 6
ok

但这是不正确的,因为我也可以

44> mathStuff:perimeter({triangle, 1, 2, 3, 4}).
perimeter for triangle 6
ok
45> 

什么是解决此问题的更好方法,我如何更具体地了解类型和参数?

1 个答案:

答案 0 :(得分:2)

第一个错误的原因是您在rectangle表达式中未匹配case ... end,因此无法匹配任何内容。与大多数命令式语言不同,函数式语言中的case表达式通常需要匹配至少一个子句 - 否则,表达式应该评估什么值?

解决此问题的更惯用的方法是在函数头处使用pattern matching,如下所示:

perimeter({square, Side}) ->
    io:format("perimeter for square is ~p~n", [4*Side]);
...
perimeter({triangle, A, B, C}) ->
    io:format("perimeter for triangle ~p~n", [A + B + C]).

请注意,函数子句使用;分隔,最后一个子句以.终止。

本质上,Erlang不是手动选择带有element/2的元组中的字段,而是允许您使用模式匹配来“解包”元组。在我看来,这是使用具有代数数据类型的函数式语言的最大好处之一。

顺便提一下,即使是perimeter({triangle, 1, 2, 3, 4})这样的错误调用,您获得正确结果的原因是您没有使用模式匹配,而是手动选择了相关字段。元组。你从来没有检查过元组是不是太长了!模式匹配执行一种输入验证作为副作用,因为表达式如下:

{A, B, C} = {1, 2, 3, 4}

保证因匹配错误而失败。