概述

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. requirejs、vue、vuex、vue-route的结合使用,您认为可行吗?

    在五一节之前和一网友讨论前端技术时,对方提到vue.vue-route如果配合requirejs应用.当时的我没有想得很明白,也没能这位网友一个准确的回复,但我许诺于他五一研究后给他一个回复.本是一天 ...

  2. linux-centerOs6.8安装nginx与配置

    一:安装nginx 1.安装gcc(命令:yum install gcc)备注:可以输入gcc -v查询版本信息,查看是否自带安装 2.安装pcre(命令:yum install pcre-devel ...

  3. redis 系列14 有序集合对象

    一. 有序集合概述 Redis 有序集合对象和集合对象一样也是string类型元素的集合,且不允许重复的成员.不同的是每个元素都会关联一个double类型的分数.redis正是通过分数来为集合中的成员 ...

  4. C#版(打败97.89%的提交) - Leetcode 202. 快乐数 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  5. 道路运输车辆卫星定位系统JT/T808服务实现和压测

    在工作上的需要接触道路运输车辆卫星定位系统相关应用,由于自己对网络服务的编写比较感兴趣,所以利用空闲时间实现了JT/T808的一些协议和相关服务(不得不说这种协议的设计在解释的确导致性能上的损耗,特别 ...

  6. Linux 终端下解压文件失败问题

    Linux 终端下解压文件失败: # tar -zxvf *****.tar.bz2 tar 命令出错gzip: stdin: not in gzip format tar: Child return ...

  7. python基础3--函数

    1.函数定义 你可以定义一个由自己想要功能的函数,以下是简单的规则: 函数代码块以def关键词开头,后接函数标识符名称和圆括号(). 任何传入参数和自变量必须放在圆括号中间.圆括号之间可以用于定义参数 ...

  8. 权限管理系统之集成Shiro实现登录、url和页面按钮的访问控制

    用户权限管理一般是对用户页面.按钮的访问权限管理.Shiro框架是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理,对于Shiro的介绍这里就不多说.本篇博客主要是了解Shiro的 ...

  9. MySQL 笔记整理(2) --日志系统,一条SQL查询语句如何执行

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 2) --日志系统,一条SQL查询语句如何执行 MySQL可以恢复到半个月内任意一秒的状态,它的实现和日志系统有关.上一篇中记录了一 ...

  10. 【JVM】问题排查

    jetty的调用场景是:为了支持Servlet规范中的注解方式(使得不再需要在web.xml文件中进行Servlet的部署描述,简化开发流程),jetty在启动时会扫描class.lib包,将使用注解 ...