您的位置:首页 > 编程语言

Programming Elixir, Functional |> Concurrent |> Pragmatic |> Fun, Pragmatic 读书笔记

2015-11-09 14:02 357 查看


Programming Elixir,  Functional |> Concurrent |> Pragmatic |> Fun, Pragmatic



安装配置
又是‘Don't worry about details’!最烦这种写法

def module Par do

def pmap(coll, f) do

coll |> Enum.map(&(Task.async(fn -> f.(&1) end))) |> Enum.map(&Task.await/1)
调用:result = Par.pmap 1..100, &(&1*&1)
$iex
h(Enum.reverse/1)

$elixir hello.exs

传统编程
模式匹配
=不是赋值,而是match操作
var可重新bind到一个subsequent里:a=1, [1,a,3]=[1,2,3] 子作用域名字隐藏?

所有value不可变
list2 = [ 4 | list1]
如果process因为heap满而中止,所有数据丢弃,无GC

Basics
数据类型:Number, Atom(Symbol?:name), Range(s..e)
正则 ~r{regex}opts(选项:f g i m r s u x)
PID, make-ref
Tuple: {:ok, 42, "abc"}
List: [1,2,3]
语法糖:[name: "Dave", city: "Dallas"] --> [{:name, "Dave"}, ...]

Map: %{ key => value, ...} Perl风格?
colors[:red] --> colors.red

Binaries
bin = <<1, 2>>
bin = << 3 :: size(2), 5 :: size(4), 1 :: size(2)>>
<<213>>

 :io.format("~-8.2b~n", :binary.bin_to_list(bin2))
11010101

true, false, nil

匿名函数
fn arg-list -> body ... end
注意:1)对命名函数不需要f.()语法 2)由于PM机制, fn内可以有多个子句(多重派发?)

字符串模板替换(Ruby?):"#{IO.read(file, :line)}"
函数返回函数(Currying)
函数作为参数(高阶函数)
&记号:&(Float.round(&1,&2) --> &Float.round/2 (C++11完美转发?)

模板与命名函数
do ... end居然不是底层的实际语法??def double(n), do: n*2
Guard子句:def f(x) when p(x) do ... end
默认参数:param \\ defaultValue (编译期的trick?)
defp 宏
|> 管道操作
val |> f(a,b) 基本上相当于f(val, a, b) 插入到第一个参数位置(这有点诡异,对比:F# Java8)

import List, only:[flatten:1]
alias Mix.Tasks.DocTest, as: DocTest (alias指令其实就是内置函数?)
require:引用模块中的宏
属性(attributes):@name value 主要用于声明常量?那干嘛叫‘属性’
*调用Erlang库函数::io.format

Lists与递归
def sum(l), do: _sum(l,0)
defp _sum([], t), do: t ...

字典:Maps, HashDicts, Keywords, Sets与Structs
for p = %{height: height} <- people, height>1.5, do: ...
Maps不能bind value到key
new_map = %{ old_map | key => val, ... } 数据结构都是immutable的(对比:Scala)

@derive Access
defstruct name: "...", over_18: false
* put_in, update_in
Set1 = Enum.into 1..5, HashSet.new

Types
处理集合:Enum与Stream(lazy)
IO.puts File.open("/path/to/file") |> IO.stream(:line) |> Enum.max_by(&String.length/1)
File.stream!

无限列表:Stream.map
def sleep(sec) do

receive do

after sec*1000 -> nil
* Stream.resource
Comprehensions
for x <- [...], x<4, do: x*x
for <<c <- "hello">>, do: >>c>>

Strings 与 Binaries
* Sigils:~-style literals
类似于Perl的heredoc:~w """ ...
utf-8:String.length/codepoints vs byte_size

控制流
if ..., do: .. elese: ...
cond do ... -> ... end
case expr do ... -> ... end
raise RuntimerError, message: "!"

demo:获取json并格式化显示
$mix new issues
习俗:lib/issues/clci.ex OptionParser.parse

defmodules Issues.Mixfile do ...
use Mix.Project
def project do [ ... ] end
defp deps do [ { :httpoison, "~> 0.4"] end

$mix deps.get
$iex -S mix
config.exs
use Mix.Config
import_config "#{Mix.env}.exs"

* Enum.sort l, fn, a, b -> a["t"]<b["t"] end
escript?略

并发编程
多进程
spawn(M, :fun, [args])
receive do {sender, msg} -> send sender, {:ok, "Hi"} 这里尾递归

after 500 -> ... 超时0.5s
* last = Enum.reduce 1..n, self, fn(_, sendto) -> spawn(M, :f, [sendto]) end
$ elixir --erl "+P 1000000" -r chain.exs -e "Chain.run(400_000)"

用时仅3s?
> Process.flag(:trap_exit, true)
spawn_link(子进程结束将导致父终止)
spawn_monitor (atomic)

Agent?

Nodes
$ iex --sname a1 --cookie secret

OTP:Servers
GenServer 6 callbacks:init, handle_call/cast/info, terminate, code_change

OTP:Supervisors
OTP:Apps(代码+描述)
Tasks and Agents

More Advanced Elixir
Macros
IO.inspect
> quote do: :atom
> Code.eval_quoted( quote do: [1, 2, unquote([3,4])])
实现if宏

defmacro myif(cond, clauses) do

do/else_clause = Keyword.get(clauses, :do/else, nil); 注意,这里是2句话,我笔记缩为1句了quote do

case unquote(cond) do

val when val in [false, nil] -> unquote(else_clause)
用Binding注入值
Macros are Hygienic(类似于Scheme)
 ? 操作符重载(略)

Linking Modules
use Behaviour
defcallback ... #声明接口原型?
__using__
Trace method calls

Protocols:defprotocol --> defimpl
More Cool Stuff
TypeSpec and Type Checking
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息