elixir 函数式编程

函数式编程 · kaelzhang · 于 发布 · 最后由 hkliya回复 · 697 次阅读
5


如果你了解elixir的话,那么你应该知道elixir是基于erlang的vm的,而erlang语言是一个纯函数式编程(functional programming,FP)的语言,那么elixir是不是纯FP语言呢?答案是肯定的,elixir具备erlang FP的绝大多数特性,在少数细节上面有差异。下面将从四个FP基本特性来讲解:

  1. 函数是一等类型(First-Class Functions)

  2. 高阶函数(Higher-Order Functions)

  3. 闭包(Closures)

  4. 不变性(Immutable State)

函数是一等类型(First-Class Functions)

函数独立存在,不依附于任何对象或者命名空间,函数就是数据,就如同数据结构、数字以及字符串一样。匿名函数是该特性的最好体现。

elixir示例:

  iex(1)> add = &(&1 + &2)
  &:erlang.+/2
  iex(2)> sub = &(&1 - &2)
  &:erlang.-/2
  iex(3)> calc = &(&3.(&1, &2))
  #Function<18.54118792/3 in :erl_eval.expr/5>
  iex(4)> IO.inspect add.(1,2)
  3
  3
  iex(5)> IO.inspect sub.(2,4)
  -2
  -2
  iex(6)> IO.inspect calc.(1, 2, add)
  3
  3
  iex(7)> IO.inspect calc.(2, 4, sub)
  -2
  -2
  iex(8)> IO.inspect calc.(2, 4, &(&1 * &2))
  8
  8
  iex(9)>

高阶函数(Higher-Order Functions)

在上面的示例中已经对高阶函数的特点进行了展示。所谓高阶函数,是指接受函数作为参数,或者把函数作为返回值的函数。再多举个elixir的例子:

elixir示例:

  iex(9)> square = fn x -> x * x end
  #Function<6.54118792/1 in :erl_eval.expr/5>
  iex(10)> Enum.map(1..10, square)
  [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
  iex(11)>

闭包(Closures)

闭包包含两个特性:
1. 能够被传递
2. 当函数被创建的时候,所有变量的值都在该函数的作用域内,这些变量的值总是能够被访问的,并且和创建时一致

elixir示例:

  iex(1)> var = 5
  5
  iex(2)> print = fn -> IO.puts(var) end
  #Function<20.54118792/0 in :erl_eval.expr/5>
  iex(3)> var = 6
  6
  iex(4)> print.()
  5
  :ok
  iex(5)>

不变性(Immutable State)

首先,elixir是具有不变性的。不变性的强大体现在竞争和强占上,也就是说不会出现两个流程同时去改变同一个值的情况。

elixir示例:

  iex(5)> tuple={:ok, "hello"}
  {:ok, "hello"}
  iex(6)> put_elem(tuple,1,"world")
  {:ok, "world"}
  iex(7)> tuple
  {:ok, "hello"}
  iex(8)>

然而elixir较之erlang有些差异,那就是elixir可以对变量进行重新绑定。如果仅仅对变量进行模式匹配的话可在变量前加上^。

elixir示例:

  iex(8)> num = 1
  1
  iex(9)> ^num = 2
  ** (MatchError) no match of right hand side value: 2

  iex(9)> num = 2
  2
  iex(10)> ^num = 2
  2

在举个不变性的例子,我先定义一个名为Assignment的模块:

elixir示例:

  defmodule Assignment do
    def change_me(string) do
      string = 2
    end
  end

下面编译该模块,并调用change_me改变传入的变量string为数值2。

elixir示例:

  iex(1)> greeting = "Hello"
  "Hello"
  iex(2)> Assignment.change_me(greeting)
  2
  iex(3)> greeting
  "Hello"

结果greeting未发生变化,依旧为“hello”

原文地址:http://kaelzhang81.github.io/elixir%E7%9A%84%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B/


「软件匠艺社区」旨在传播匠艺精神,通过分享好的「工作方式」和「习惯」以帮助程序员更加快乐高效地编程。
共收到 2 条回复
13

学习

1
hkliya · #2 ·

一会儿我来实践一下。

需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。