Erlang有什麼奇技淫巧?

時間 2021-05-31 18:35:41

1樓:slepher

erlang是不支援自定義運算子的

企圖自定義運算子的語句會死在parser

非法:>

erl_parse

:parse_exprs

(element(2

,erl_scan

:string

("A >> B."

))).

}合法:

>erl_parse

:parse_exprs

(element(2

,erl_scan

:string

("A + B."

))).

,}]}

不過可以通過構建特定格式的運算子來通過parser

Erlang adding userdefined Symbols like ** or <*

If you really, really want this you can use a parse transform but your code has to be syntactically correct before the transform. So for example your parse transform can rewrite A *_* B into exp(A, B) because A *_* B will be parsed as something like (A * _) * B. However you will not be able to transform A ** B.

A *_* B 會解析成 (A * _) * B成功忽悠parser成為合法的運算子

>erl_parse

:parse_exprs

(element(2

,erl_scan

:string

("A /'>>='/ B."

))).

,},}]}

接下來就是parse_transform出場的機會了

overload_op.erl

overload_op_example.erl

另外乙個成功忽悠parser的例子就是erlando

Monad

=state_t

:new

(identity_m

).do

([Monad||A

<-foo(),

foo(),B=

baz(),

C<-bar(A,

B,dog),

return

()]).

通過do + list comprehension達到了模擬haskell中do block的目的

帶<-的語句就是 >>=

不帶<- 的語句就是 >>

帶 = 的語句就是let

return 就是 return

除了要標明需要使用的monad, 其他地方看起來和haskell一毛一樣

2樓:大雄

為什麼知乎上的程式設計師都覺得自已說的話都是真理,看起來好牛B的樣子。但總讓人覺得一直在語言的表面浮著,沒有一些很有哲理的總結呢。看過之後,覺得各位大神說的話都好像不那麼可信。

好像大神們的思唯是一直停自已的那一邊,對自已分析的總好像頭頭是道。覺得從來沒有正真懷疑過自已的能力,難道知乎上的真的都是神一樣的人物麼。思考問題總是單純的表達自已的觀點,從來沒有考慮過不與自已相同的人為什麼會用其他方法,也沒有考慮過與自已思維方式不同的人為什麼會不同。

所以我不喜歡知乎的氛圍。

3樓:某文

有意思的日常小總結:

1.Erlang Shell小技巧:v(

Line

).%%把Line行函式重新執行一次v(

-1).%%把前一行的函式重新執行一次rr(

Module

).%%把Module中的Record載入到Shell中,【超有用】rr(

"*/*"

).%%把在這個子目錄下的所有Module裡面的Record給載入到Shell裡面

2.receive after Time

這個Time最大值是50*24*60*60*1000,當時間大於50天時(這種場景真是少之又少),就會報錯:

所以要把Time拆成小於最大值的列表:

normalize

(Time)–

>Limit=49

*24*60

*60,[

Time

remLimit

|lists

:duplicate

(Time

divLimit

,Limit

)].loop([T

|Next

]})–

>receive

–>Server

!afterT*

1000

–>ifNext=:=

–>Server!;

Next=/=

–>loop

(Next

})end

end.

用於把信箱中特定的訊息清空:

flush_timeouts() ->

receive

when is_reference(TRef) ->

flush_timeouts()

after 0 ->

okend.

3.相比於在列表List尾加資料:

1>List=[

1,2,

3].[1

,2,3

]2>lists

:reverse([4

|lists

:reverse

(List

)]).[1

,2,3

,4]或:

3>List++[4]

Binary可以在頭或尾任意加資料:

4> Bin = <<1,2,3>>.

<<1,2,3>>

5> <>.

<<1,2,3,4>>1=

:1oftrue

when

noterlang

:length(t

)=:=

1orelse

true

->ok;

_->error

end.

Result is: error

保護式中對t (atom) 求length會出錯,本應crash掉,但因為在保護式中,預設出錯後結束此保護式計算並返回false,這也是為什麼保護式不接受複雜的函式,只能用erlang的bif來做的原因之一。

6.如果是把本節點上所有的Erlang節點都殺死(測試時非常有用):

killall beam.smp

7.對於gen_server標準的程序,可以使用sys模組來對程序做你想要做的任何處理:允許自定義trace函式, 記錄所有型別的事件等等。

它非常完善且可以很好地用於開發。 但

它會稍微影響處於生產環境的系統, 因為它沒有把IO重定向到遠端的shell中, 而且他沒有限制trace訊息的速度。

如檢視乙個程序的資料:

sys:

get_status

(whereis

(Server

)).8.rpc:call/4 會把使用io:format的列印字元在本地列印:

(foo@host) rpc:call('bar@host', io, format, ["~p", [test]]).

這會在foo節點上列印test。

這是因為rpc:call時會預設把本節點的group_leader傳過去

所以:如果使上面的操作在遠端節點上直接列印出來:

erl-

snamea(

a@localhost)1

>global

:register_name

(global_io_srv

,group_leader

()).

yeserl

-snameb(

b@localhost)1

>net_kernel

:connect(a

@localhost

).true(b

@localhost)2

>io:

format

(global

:whereis_name

(global_io_srv

),"it should be printed on remote node~n"

,).ok

9.使用receive達到收訊息時不同的優先順序:

receive

->->priority

(Data1

)after

0->receive

->priority

(Data1

)->normal

(Data2

)end

end.

10.如果想生成非常長的list 如:

lists:seq(1,64000000).

非常慢且一次性占用超多的內在(有可能造成程序crash)。

可以轉為動態生成的方式:

-module

(lazy).-

export

([seq/2

]).seq(M

,N)when

M=fun()

->[M

|seq(M

+1,N

)]end

;seq

(_,_)

->fun()

->end.

1>Lists

=lazy

:seq(1

,64000000).#

Fun<

lazy.0

.26378159

>2>hd(

Lists

()).13

>Lists2=tl

(Lists

()).

#Fun

.26378159

>4>hd(

Lists2

()).

211.程序中郵箱裡面的存著的messages會在每個新message來之後重新匹配一次:

start(State) ->

.loop(State) ->

receive

first_msg when State == nil ->

io:format("first_msg when state == nil"loop(first_msg);

second_msg when State == first_msg ->

io:format("second_msg when state == first_msg"loop(second_msg)

end.

1>=msg_test

:start

(nil).2

>Pid!

nil.

nil3

>Pid!

second_msg

.second_msg

4>Pid!

first_msg

.first_msg

when

state

==nilfirst_msg

second_msg

when

state

==first_msg

12.erlang:get_stacktrace()Get the call stack back-trace (stacktrace) of thelast exceptionin the calling process as a list of tuples.

得到的此程序最後一次的exception,如果你在沒有發生exception處檢視堆疊呼叫,就應該:

Trace

=try

throw(42

)catch

42->

erlang

:get_stacktrace

()end

,erlang

:display

(Trace

)erlang call stack

13.tail recursion 與 recursion的區別例子:

求值2的5次冪

使用非尾遞迴實現:

pow(x, 1) -> x;

pow(x, N) -> x * pow(x, N-1).

其呼叫過程:

pow(2,5)

2 * pow(2, 4)

2 * (2 * pow(2, 3))

2 * (2 * (2 * pow(2, 2)))

2 * (2 * (2 * (2 * pow(2, 1))))

2 * (2 * (2 * (2 * 2)))

32注意到真正的計算開始是在最後的pow(2, 1)然後再一步步反推回pow(2,5)才得到的結果。

再看看尾遞迴的實現

tail_pow(x, 1, acc) -> x * acc;

tail_pow(x, N, acc) -> tail_pow(x, N-1, acc * x).

其呼叫過程:

tail_pow(2, 5, 1)

tail_pow(2, 4, 4)

tail_pow(2, 3, 8)

tail_pow(2, 2, 16)

tail_pow(2, 1, 32)

32可以看出他的求值順序就是從5到1的,兩點一對比,可以更加理解Joe所說的:

The important thing to note about tail-recursive functions is that they can run in loops without consuming stack space. Such function are called 「iterative functions.使用以上2個例子求2的1次冪到2的64次冪之和(不要使用等比數列求和公式2的65次冪-1。。

)對比下時間會更加直觀。可以這樣:

timer:tc

(fun

()->

lists

:foldl

(fun(x

,acc

)->pow(2,

x)+acc

end,0,

lists

:seq(1

,64))end

).timer:tc

(fun

()->

lists

:foldl

(fun(x

,acc

)->tail_pow(2

,x,1

)+accend,0

,lists

:seq(1

,64))end

).mylists:concat([begin lists:seq(1,10) end||Small <- lists:seq(1,1000000)]).

看看你會用多久~

14.如果你發現crash時的堆椎呼叫資訊不夠詳細或太過詳細,都可以使用

erlang:system_flag(backtrace_depth,10).

來調整,預設為8。

15.判斷非空列表

case

List

of[_|_]

->do_not_empty_work

(List);_

->do_other_work

(List

)end

16.io_lib:format/2裡面的佔位符自動補全功能。

1010> , } = calendar:local_timelists:flatten(io_lib:

format("~4..0w~2..0w~2..

0w~2..0w~2..0w~2..

0w",[Year, Month, Day, Hour, Min, Sec])).

"20151015184620"

17. 保護式中andalso/orelse與;/,的區別

andalso/orelse如果表示式crash掉,那麼整個表示式會返回false, 後者則只是crash部分返回false.

21>F1=

fun(X)

whenX/

0==0;

true

->X;

21>(X

)->X+

1end.#

Fun<

erl_eval.6

.54118792

>22>F1(

10).

1023

>F2=

fun(X)

whenX/

0==0orelse

true

->X;

23>(X

)->X+

1end.#

Fun<

erl_eval.6

.54118792

>24>F2(

10).

1118. 當我們在shell裡面得到的結果是List,shell會嘗試把結果變成a printable string,

1> [65,66,67,68,69].

"ABCDE"

如果我們只想看到原始的值,可以使用shell:strings(false).來關掉這個這個猜的功能。

19.有一些庫提供原始碼的同時,也提供了beam的ez包,那麼,你可以直接解壓ez包到code:lib_dir().

目錄下,就可以直接當基礎庫使用了,不需要每次都去重編這個庫。比如:rabbitmq-erlang-client。

20. 如果節點是以-heart啟動的,殺掉他最安全的方式就是進入shell,然後init:stop().21.

Pok mon GO 有什麼奇技淫巧?

Lu Jia 最近剛剛發現的。每個寵物進化時除了要注意測算他的IV值之外,就是身材.攻擊 防守和體力,還要注意它的特殊攻擊的型別。同型別的攻擊會有50 傷害加成。下圖同樣兩個暴鯉龍.乙個特殊攻擊是 dragon 乙個是 water 後者要明顯好於前者。同樣的例子,寶石海星居然是rock特殊攻擊。廢物...

Python 有什麼奇技淫巧?

jannchie見齊 Python字串格式化 資料 data 目標 輸出 我是見齊,是個程式設計師。字串拼接 我是 data name 是個 data job 使用格式化方案 我是 是個 format data name data job 較簡單的格式化方案方案 我是 s 是個 s。data nam...

MATLAB 有什麼奇技淫巧?

鮑里斯 運算的加速 bsxfun cellfun 可以將for迴圈速度提高幾個數量級。如果實在懶得寫,可以寫個mex介面呼叫c c 來執行迴圈。只不過在處理影象時,matlab和opencv影象矩陣的index不同。劃重點 從我能熟練運用matlab開始到現在大概四年時間,我發現我用到的幾乎所有的功...