पाठ 5 / 25
Modules, Functions and Guards
Define named functions with multiple clauses, guards, defaults and anonymous functions.
Functions are the unit of code
Code lives in modules (defmodule Shop.Pricing do ... end). Public functions use def and private ones defp. A function is identified by its name and arity (number of arguments), written total/1, so total/1 and total/2 are different functions. Functions can have multiple clauses: Elixir tries each clause top to bottom and runs the first whose patterns and guards match, which replaces many if statements. Guards (when is_integer(qty) and qty > 0) allow only a limited set of side-effect-free expressions; defguard defines reusable ones. Default arguments use \\ (def greet(name, greeting \\ "Hello")). Anonymous functions are written fn x -> x * 2 end and called with a dot, double.(4); the capture operator & gives shorthand: &(&1 * 2) or &String.upcase/1. Functions return the last expression; there is no return keyword. Use @doc and @moduledoc for documentation and @spec for type specifications. Module attributes such as @gst_rate 0.18 act as compile-time constants.
Multi-clause functions with guards
Pattern matching in function heads replaces conditionals.
defmodule Shop.Pricing do
@moduledoc "Price calculations in paise."
@gst_rate_percent 18
@doc "Shipping fee for an order total in paise."
@spec shipping_fee(non_neg_integer(), keyword()) :: non_neg_integer()
def shipping_fee(total, opts \\ [])
def shipping_fee(total, _opts) when total >= 100_000, do: 0
def shipping_fee(_total, opts) do
if Keyword.get(opts, :express, false), do: 9_900, else: 4_900
end
def with_gst(paise) when is_integer(paise) and paise >= 0 do
paise + div(paise * @gst_rate_percent + 50, 100)
end
def describe({:ok, total}), do: "Total: #{format(total)}"
def describe({:error, :empty_cart}), do: "Your cart is empty"
def describe({:error, reason}), do: "Could not price order: #{inspect(reason)}"
defp format(paise), do: :erlang.float_to_binary(paise / 100, decimals: 2)
end
IO.puts(Shop.Pricing.shipping_fee(150_000)) # 0
IO.puts(Shop.Pricing.shipping_fee(20_000, express: true)) # 9900
IO.puts(Shop.Pricing.describe({:ok, Shop.Pricing.with_gst(10_000)})) # Total: 118.00
double = fn x -> x * 2 end
IO.inspect(Enum.map([1, 2, 3], double))
IO.inspect(Enum.map(["pune", "delhi"], &String.capitalize/1))Clause order matters
Clauses are tried top to bottom, so put specific clauses first. The compiler warns when a later clause can never match because an earlier one is more general.
त्वरित जाँच: In Elixir, how are total/1 and total/2 related?
- They are the same function
- They are different functions because arity is part of a function's identity
- total/2 overrides total/1
- Defining both is an error
Answer
They are different functions because arity is part of a function's identity — Functions are identified by name and arity.