1defmodule Function do 2 @moduledoc """ 3 A set of functions for working with functions. 4 5 Anonymous functions are typically created by using `fn`: 6 7 iex> add = fn a, b -> a + b end 8 iex> add.(1, 2) 9 3 10 11 Anonymous functions can also have multiple clauses. All clauses 12 should expect the same number of arguments: 13 14 iex> negate = fn 15 ...> true -> false 16 ...> false -> true 17 ...> end 18 iex> negate.(false) 19 true 20 21 ## The capture operator 22 23 It is also possible to capture public module functions and pass them 24 around as if they were anonymous functions by using the capture 25 operator `Kernel.SpecialForms.&/1`: 26 27 iex> add = &Kernel.+/2 28 iex> add.(1, 2) 29 3 30 31 iex> length = &String.length/1 32 iex> length.("hello") 33 5 34 35 To capture a definition within the current module, you can skip the 36 module prefix, such as `&my_fun/2`. In those cases, the captured 37 function can be public (`def`) or private (`defp`). 38 39 The capture operator can also be used to create anonymous functions 40 that expect at least one argument: 41 42 iex> add = &(&1 + &2) 43 iex> add.(1, 2) 44 3 45 46 In such cases, using the capture operator is no different than using `fn`. 47 48 ## Internal and external functions 49 50 We say that functions that point to definitions residing in modules, such 51 as `&String.length/1`, are **external** functions. All other functions are 52 **local** and they are always bound to the file or module that defined them. 53 54 Besides the functions in this module to work with functions, `Kernel` also 55 has an `apply/2` function that invokes a function with a dynamic number of 56 arguments, as well as `is_function/1` and `is_function/2`, to check 57 respectively if a given value is a function or a function of a given arity. 58 """ 59 60 @type information :: 61 :arity 62 | :env 63 | :index 64 | :module 65 | :name 66 | :new_index 67 | :new_uniq 68 | :pid 69 | :type 70 | :uniq 71 72 @doc """ 73 Captures the given function. 74 75 Inlined by the compiler. 76 77 ## Examples 78 79 iex> Function.capture(String, :length, 1) 80 &String.length/1 81 82 """ 83 @doc since: "1.7.0" 84 @spec capture(module, atom, arity) :: fun 85 def capture(module, function_name, arity) do 86 :erlang.make_fun(module, function_name, arity) 87 end 88 89 @doc """ 90 Returns a keyword list with information about a function. 91 92 The returned keys (with the corresponding possible values) for 93 all types of functions (local and external) are the following: 94 95 * `:type` - `:local` (for anonymous functions) or `:external` (for 96 named functions). 97 98 * `:module` - an atom which is the module where the function is defined when 99 anonymous or the module which the function refers to when it's a named function. 100 101 * `:arity` - (integer) the number of arguments the function is to be called with. 102 103 * `:name` - (atom) the name of the function. 104 105 * `:env` - a list of the environment or free variables. For named 106 functions, the returned list is always empty. 107 108 When `fun` is an anonymous function (that is, the type is `:local`), the following 109 additional keys are returned: 110 111 * `:pid` - PID of the process that originally created the function. 112 113 * `:index` - (integer) an index into the module function table. 114 115 * `:new_index` - (integer) an index into the module function table. 116 117 * `:new_uniq` - (binary) a unique value for this function. It's 118 calculated from the compiled code for the entire module. 119 120 * `:uniq` - (integer) a unique value for this function. This integer is 121 calculated from the compiled code for the entire module. 122 123 **Note**: this function must be used only for debugging purposes. 124 125 Inlined by the compiler. 126 127 ## Examples 128 129 iex> fun = fn x -> x end 130 iex> info = Function.info(fun) 131 iex> Keyword.get(info, :arity) 132 1 133 iex> Keyword.get(info, :type) 134 :local 135 136 iex> fun = &String.length/1 137 iex> info = Function.info(fun) 138 iex> Keyword.get(info, :type) 139 :external 140 iex> Keyword.get(info, :name) 141 :length 142 143 """ 144 @doc since: "1.7.0" 145 @spec info(fun) :: [{information, term}] 146 def info(fun), do: :erlang.fun_info(fun) 147 148 @doc """ 149 Returns a specific information about the function. 150 151 The returned information is a two-element tuple in the shape of 152 `{info, value}`. 153 154 For any function, the information asked for can be any of the atoms 155 `:module`, `:name`, `:arity`, `:env`, or `:type`. 156 157 For anonymous functions, there is also information about any of the 158 atoms `:index`, `:new_index`, `:new_uniq`, `:uniq`, and `:pid`. 159 For a named function, the value of any of these items is always the 160 atom `:undefined`. 161 162 For more information on each of the possible returned values, see 163 `info/1`. 164 165 Inlined by the compiler. 166 167 ## Examples 168 169 iex> f = fn x -> x end 170 iex> Function.info(f, :arity) 171 {:arity, 1} 172 iex> Function.info(f, :type) 173 {:type, :local} 174 175 iex> fun = &String.length/1 176 iex> Function.info(fun, :name) 177 {:name, :length} 178 iex> Function.info(fun, :pid) 179 {:pid, :undefined} 180 181 """ 182 @doc since: "1.7.0" 183 @spec info(fun, item) :: {item, term} when item: information 184 def info(fun, item), do: :erlang.fun_info(fun, item) 185 186 @doc """ 187 Returns its input `value`. This function can be passed as an anonymous function 188 to transformation functions. 189 190 ## Examples 191 192 iex> Function.identity("Hello world!") 193 "Hello world!" 194 195 iex> 'abcdaabccc' |> Enum.sort() |> Enum.chunk_by(&Function.identity/1) 196 ['aaa', 'bb', 'cccc', 'd'] 197 198 iex> Enum.group_by('abracadabra', &Function.identity/1) 199 %{97 => 'aaaaa', 98 => 'bb', 99 => 'c', 100 => 'd', 114 => 'rr'} 200 201 iex> Enum.map([1, 2, 3, 4], &Function.identity/1) 202 [1, 2, 3, 4] 203 204 """ 205 @doc since: "1.10.0" 206 @spec identity(value) :: value when value: var 207 def identity(value), do: value 208end 209