(译)Études for Elixir Chapter 3: 原子,元组和模式匹配

本文介绍了Elixir语言中模式匹配的基本用法,包括模式匹配在几何形状面积计算中的应用,以及如何通过guards来限制参数的有效性,并展示了如何将元组作为函数参数。

Étude 3-1: 模式匹配

area函数中使用原子模式匹配来计算一个矩形, 三角形椭圆形的面积. 如果你的参数为shape, a, b:

面积公式为:

TYPEFORMULADESCRIPTION
:rectangea * b矩形
:trianglea * b / 2.0三角形
:ellipse:math.pi() * a * b椭圆形

实现代码:

defmodule Geom do
  @moduledoc """ 
  Functions for calculating areas of geometric shapes. 
  from *Études for Elixir*, O'Reilly Media, Inc., 2013.
  Copyright 2013 by J. David Eisenberg.
  """ 
  @vsn 0.1 

  @doc """
  Calculates the area of a shape, given the shape and two of the
  dimensions. Returns the product of its arguments for a rectangle,
  one half the product of the arguments for a triangle, and
  :math.pi times the product of the arguments for an ellipse.
  """
  
  @spec area(atom(), number(), number()) :: number()
  
  def area(:rectangle, length, width) do
    length * width
  end
  
  def area(:triangle, base, height) do
    base * height / 2.0
  end
  
  def area(:ellipse, a, b) do
    :math.pi * a * b
  end
end

Étude 3-2: Guards

在函数匹配的情况下, 再加上一些限制的匹配条件. 多用于限制参数的类型, 值的取值范围

参考了一些资料, 多译为保护式, 多用于限制取值范围避免取到无效的值, 比如数学中除数为0是无意义的. 因此需要限制除数大于0

下面以area/3为例子来说明如何使用保护式

defmodule Geom do
  @spec area(atom(), number(), number()) :: number()
  
  def area(:rectangle, length, width) when length >= 0 and width >= 0 do
    length * width
  end
  
  def area(:triangle, base, height) when base >= 0 and height >= 0 do
    base * height / 2.0
  end
  
  def area(:ellipse, a, b) when a >= 0 and b >= 0 do
    :math.pi * a * b
  end
end

例如area(:rectangle, length, width)矩形面积函数分句, 除了传递三个必须的参数意外, 当length > 0并且width >= 0, 才会匹配到这个分句, 否则匹配不到任何area函数, 这时候Erlang VM会刨除无法匹配的错误, 如下:

iex(60)> Geom.area(:rectangle, -1, 10)
** (FunctionClauseError) no function clause matching in Geom.area/3
    iex:61: Geom.area(:rectangle, -1, 10)

要处理这类无法匹配的错误, 请看Étude 3-3.

Étude 3-3: 下划线

defmodule Geom do
  
  @spec area(atom(), number(), number()) :: number()
  
  def area(:rectangle, length, width) when length >= 0 and width >= 0 do
    length * width
  end
  
  def area(:triangle, base, height) when base >= 0 and height >= 0 do
    base * height / 2.0
  end
  def area(:ellipse, a, b) when a >= 0 and b >= 0 do
    :math.pi * a * b
  end
  
  def area(_, _, _) do
    0
  end
end

这里我们增加了第四个函数用于匹配其他非:rectangle,:triangle,:ellipse形状的默认调用返回0.

Étude 3-4: 把元组作为参数

defmodule Geom do
  
  @spec area({atom(), number(), number()}) :: number()
  
  # 把元组作为参数
  def area({shape, dim1, dim2}) do
    area(shape, dim1, dim2)
  end
  
  # Individual functions to handle each shape

  @spec area(atom(), number(), number()) :: number()
  
  defp area(:rectangle, length, width) when length >= 0 and width >= 0 do
    length * width
  end
  
  defp area(:triangle, base, height) when base >= 0 and height >= 0 do
    base * height / 2.0
  end
  
  defp area(:ellipse, a, b) when a >= 0 and b >= 0 do
    :math.pi * a * b
  end
  
  defp area(_, _, _) do
    0
  end
end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值