概述

Elixir 是一种基于 Erlang 虚拟机的函数式,面向并行的通用语言, 它是一门通用语言,所以不仅可以用在擅长的高可用,高并发场景下,也可以用在 web 开发等场景下。 Erlang 诞生于 1986 年,爱立信。

有了 Erlang,为什么还要 Elixir? Erlang 毕竟诞生的早,虽然有很多优秀的特性,但是语法非常晦涩难懂,甚至没有支持 String Elixir 只是 Erlang 很简单的封装,不仅保留了 Erlang 所有的优秀特性,还提供了类似 Ruby 那样高效的语法。

和 Erlang 相比,Elixir 的语法有 2 个明显的优势

  • macro: 可以简化很多的代码
  • pipeline: |> 可以省却很多临时变量的定义

环境搭建

官方安装文档:https://elixir-lang.org/install.html 建议在 Unix-like 的系统下通过编译源码的方式安装,能够及时体验最新的特性

安装 Elixir 之前要先安装 Erlang

语言基础

在 Elixir 中,任何东西都可以理解为 *表达式+返回值*。 Elixir 中,任何数据不可改变,变量的赋值本质是把变量指向了其他的内存地址,不改变变量原来内存地址中的内容, 所以,等于(=)在 Elixir 中其实是 绑定(binding) 的意思,把右边的值绑定到左边的变量上,并返回右边的值

类型

Elixir 中的类型主要有以下几类:

Number

Elixir 中整数和小数统称为数值类型,整数的除法和求余用 div 和 rem 宏来实现

Atom

原子存在原子表中,不会被 GC 自动回收 true/false 在 Elixir 中是原子 :true/:false nil 在 Elixir 中是原子 :nil

Tuple

元素个数是固定的,适用于小的集合 通过 put_elem 修改 tuple 之后,其实返回的是一个新的 tuple,原来的 tuple 并没有被修改

List

list 可以表示为 [head|tail] 在 list 的末尾追加元素会导致 copy 整个 list,所以一般都在头部添加元素

Map

如果 key 是原子 ex. %{a: "xx", b: "yy"}; 否则 %{1 => "xx", "a string key" => "yy"}

Binary and Bitstring

长度是 8 的倍数的 Bitstring 也是 Binary

String

Elixir 中的 string 本质就是 Binary

Function

function 在 Elixir 中是一等公民,所以它也可以存放在变量中

Reference

BEAM 实例的引用

pid

Erlang process 的唯一标识

Keywork List

一种 list,每个元素都是一个包含 2 个元素的 tuple

IO List

一种深度自包含的结构,可以用来高效的在处理 IO 和网络数据 ex. 下面这个例子,文件写入时会分成 3 次,因为 a,b,c 的内存地址是不连续的 如果把 a,b,c 拼成一个字符串再写入文件的话,新的字符串会再次分配一次 a,b,c 所占用的内存量

{:ok, file} = :file.open("/tmp/tmp.txt", [:write, :raw])
a = "aaa"
b = "bbb"
c = "ccc"
output = [a, b, c]
:file.write(output)

用 io_list 可以避免上面的问题

{:ok, file} = :file.open("/tmp/tmp.txt", [:write, :raw])
a = "aaa"
b = "bbb"
c = "ccc"
output = [a, [b, [c]]]
:file.write(output)

IO.puts 输出时会拍平 io_list

控制流

一般语言中的流程控制就是判断(if, case…),循环(for, while…) Elixir 中虽然也有 if,case(通过 macro 来实现),但是尽量不要使用

Elixir 中通过模式匹配来实现判断,通过递归来实现循环

模式匹配的例子

通过不同的函数,实现变量的类型判断

defmodule ElixirIntro do
def judge(x) when is_integer(x) do
IO.puts("#{x} is integer")
end def judge(x) when is_bitstring(x) do
IO.puts("#{x} is string")
end def judge(x) do
IO.puts("#{x} is not integer and string")
end
end

递归的示例

递归是 Elixir 中常用的技巧,通过递归可以写出简单易懂的代码 下面示例是累加求和的递归写法

defmodule ElixirIntro do
def sum(n) when n <= 1 do
n
end def sum(n) do
n + sum(n - 1)
end
end

上面的递归写法虽然能完成功能,但是运行过程中消耗的内存很比较大,这种写法就是递归被人诟病的地方。

在 Elixir 中,我们应该使用尾递归的方式来完成循环,因为尾递归会被优化,只占用固定数量的内存,上面的示例如下:

defmodule ElixirIntro do
def sum(total, n) when n <= 1 do
total + n
end def sum(total, n) do
sum(total + n, n - 1)
end
end

所谓尾递归,就是函数在最后只调用了自己

代码组织(模块和函数)

Elixir 的代码用 mix 来管理,通过 mix 创建,管理,发布工程。 代码主要是 module 和 function

$ mix new hello
$ cd hello
$ iex -S mix

Elixir 工程的代码都在 lib 文件夹下。

错误处理

错误处理是 Elixir 中的一级概念。

一般的错误处理思路都是尽可能的捕获错误(可预期和不可预期的):

  • 可预期的错误直接处理
  • 不可预期的错误捕获不到可能系统崩溃,捕获后一般也是直接跳过

Elixir 的核心能力之一是应对高并发,所以它的错误处理思路也不一样。 Elixir 错误处理的目的 不是降低错误的数量 ,而是 降低错误带来的影响 并且能够从错误中 自动恢复 。 所以,Elixir 的处理方式:

  • 可预期的错误,和传统方式一样,尽可能处理
  • 不可预期的错误,直接崩溃重启。会导致崩溃的地方尽快崩溃

Elixir 的观点:

  • 有些错误发生后,要想解决很困难,在发生错误后接着处理可能会导致更严重的错误
  • 很多运行时的错误,极难重现,大部分都能通过重启来解决

总结

Elixir 虽然在它的领域有先天的优势,但是肯定也有不足之处:

  • speed: 性能不是 Erlang 平台的优势,毕竟有一层 BEAM 虚拟机, 高并发 != 高性能
  • ecosystem: Erlang/Elixir 的生态远没有其他语言成熟(比如 java, javascript, ruby 等)

Elixir 不是万能的,但是学习 Elixir 可以打开你的视野,特别是对于一直使用面向对象语言的同学, 学习 Elixir 可以让你以另外一种视角看待程序设计。

Elixir 简介的更多相关文章

  1. Ellxir

    API: elixir https://hexdocs.pm/elixir/Module.html#content API: erlang http://www.cnerlang.com/api.ht ...

  2. elixir mix 简介

    概述 mix 是 elixir 工程的构建工具,利用 mix,可以快速方便的创建 elixir 工程,写单元测试,管理 elixir 包的依赖管理等等. 我觉得刚开始学习 elixir 的时候,先简单 ...

  3. elixir 高可用系列(二) GenServer

    概述 如果我们需要管理多个进程,那么,就需要一个专门的 server 来集中监控和控制这些进程的状态,启停等. OTP 平台中的 GenServer 就是对这个 server 通用部分的抽象. 利用 ...

  4. 写给Java开发者的Node.JS简介

    前言 今天上推特看见这篇文章,点进去发现是新货. 正好最近想入Node的坑,又有一些Java基础,所以希望翻译出来给大家,同时也让自己加深理解. 才疏学浅,如有不妥之处请指正. 原文链接:Node f ...

  5. SpaceVim 语言模块 elixir

    原文连接: https://spacevim.org/cn/layers/lang/elixir/ 模块简介 功能特性 启用模块 快捷键 语言专属快捷键 交互式编程 运行当前脚本 模块简介 这一模块为 ...

  6. Browsersync 简介 and 使用

    简介 省时的浏览器同步测试工具,Browsersync能让浏览器实时.快速响应您的文件更改(html.js.css.sass.less等)并自动刷新页面. 曾经我们每改一次的代码,都需要手动去刷新一次 ...

  7. ASP.NET Core 1.1 简介

    ASP.NET Core 1.1 于2016年11月16日发布.这个版本包括许多伟大的新功能以及许多错误修复和一般的增强.这个版本包含了多个新的中间件组件.针对Windows的WebListener服 ...

  8. MVVM模式和在WPF中的实现(一)MVVM模式简介

    MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...

  9. Cassandra简介

    在前面的一篇文章<图形数据库Neo4J简介>中,我们介绍了一种非常流行的图形数据库Neo4J的使用方法.而在本文中,我们将对另外一种类型的NoSQL数据库——Cassandra进行简单地介 ...

随机推荐

  1. Hadoop源码篇--Reduce篇

    一.前述 Reduce文件会从Mapper任务中拉取很多小文件,小文件内部有序,但是整体是没序的,Reduce会合并小文件,然后套个归并算法,变成一个整体有序的文件. 二.代码 ReduceTask源 ...

  2. windows部署MongoDB

    打开MongoDb下载页面,分别下载Community Server和Compass,注意在安装Community Server时可以勾选同时安装Compass,但会比较慢,所以建议两个分开下载安装. ...

  3. 洛谷:P1182:数列分段`Section II`

    题目描述 对于给定的一个长度为N的正整数数列 A-iA−i ,现要将其分成 M(M≤N)M(M≤N) 段,并要求每段连续,且每段和的最大值最小. 关于最大值最小: 例如一数列 4 2 4 5 1424 ...

  4. Java基础17:Java IO流总结

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  5. Chapter 5 Blood Type——5

    "Well…" He paused, and then the rest of the words followed in a rush. "嗯..." 他顿顿 ...

  6. 【Java基础】【24多线程(上)】

    24.01_多线程(多线程的引入)(了解) 1.什么是线程 线程是程序执行的一条路径, 一个进程中可以包含多条线程 多线程并发执行可以提高程序的效率, 可以同时完成多项工作 2.多线程的应用场景 红蜘 ...

  7. Docker系列06—基于容器制作镜像并上传到Docker Registry

    本文收录在容器技术学习系列文章总目录 1.制作镜像 1.1 镜像的生成途径 基于容器制作 dockerfile,docker build 本篇主要详细讲解基于容器制作镜像:基于dockerfile 制 ...

  8. javaWeb项目中的路径格式 请求url地址 客户端路径 服务端路径 url-pattern 路径 获取资源路径 地址 url

    javaweb项目中有很多场景的路径客户端的POST/GET请求,服务器的请求转发,资源获取需要设置路径等这些路径表达的含义都有不同,所以想要更好的书写规范有用的路径代码 需要对路径有一个清晰地认知 ...

  9. 用meterpreter实现跳板机

      meterpreter跳板机 背景:渗透测试者A拿到了B主机的控制权,但没有拿到ssh密码(不能打ssh隧道).现需横向移动渗透内网主机C,为了避免动作过大不便直接在B上对C进行渗透,其中C不能出 ...

  10. Linux常用命令详解(week1_day1_1)--技术流ken

    本节内容 基础命令:lsmanpwdcdmkdirechotouchcpmvrmrmdircatmorelessheadtailclearpoweroffreboot进阶命令(下一章节):aliasu ...