简体   繁体   English

Erlang初学者:找到外围吗?

[英]Erlang Beginner: Find Perimeter?

I am learning Erlang and was attempting problem mentioned here , as 我正在学习Erlang并尝试此处提到的问题,因为

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}

So, my solution to this is 所以,我的解决方案是

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

and when I run I get 当我跑步时我得到

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

but this is incorrect since I can also do 但这是不正确的,因为我也可以

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

What is a better way to approach this problem, how can I be more specific about type and arguments? 解决此问题的更好方法是什么,如何才能更具体地说明类型和参数?

The reason for the first error is that you are not matching rectangle in your case ... end expression, so it fails to match anything. 第一个错误的原因是您的case ... end表达式不匹配rectangle ,因此它无法匹配任何内容。 Unlike most imperative languages, a case expression in a functional language is generally required to match at least one clause -- otherwise, what value should the expression evaluate to? 与大多数命令式语言不同,通常需要使用功能性语言中的case表达式来匹配至少一个子句-否则,该表达式应求值是什么?

A more idiomatic way of solving this problem involves pattern matching at the function head, like so: 解决此问题的一种更惯用的方法是在函数头处进行模式匹配 ,如下所示:

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]).

Note that the function clauses are separated using ; 注意,功能子句使用;分隔; , with the last clause being terminated with . ,最后一个子句以终止. .

In essence, instead of manually selecting fields from the tuple with element/2 , Erlang allows you to "unpack" the tuple using pattern matching. 从本质上讲,Erlang无需您从带有element/2的元组中手动选择字段,而是可以使用模式匹配来“解压缩”该元组。 This is, in my opinion, one of the greatest benefits of using a functional language with algebraic data types. 我认为,这是使用具有代数数据类型的功能语言的最大好处之一。

Incidentally, the reason that you got a correct result even for an erroneous call like perimeter({triangle, 1, 2, 3, 4}) is that you didn't use pattern matching, but instead manually selected the relevant fields of the tuple. 顺便说一句,即使对于诸如perimeter({triangle, 1, 2, 3, 4})类的错误调用也能获得正确的结果,原因是您没有使用模式匹配,而是手动选择了元组的相关字段。 You never checked that the tuple wasn't too long! 您从未检查过元组不长! Pattern matching performs a kind of input validation as a side-effect, because an expression like: 模式匹配执行一种输入验证作为副作用,因为这样的表达式如下:

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

Is guaranteed to fail with a match error. 确保因匹配错误而失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM