100言語Spedrdrun :エピソード81:エリクサー
Erlangはいくつかの強力な分散コンピューティング機能を備えたプラットフォームですが、それが使用する言語Erlangは本当にひどいです.Erlangの言語、その構文、その標準ライブラリ、その文字列処理、そのUnixの統合などのすべては、巨大な痛みです.
ある意味では、JavaとJVMの状況に似ていますが、それに対するすべてのファッショナブルな憎しみのために、Java言語はErlangの言語と同じくらい悪くどこにもありません.
それで、何人かの良い人々は正しいことをして、同じプラットホームのためにより良い言語―エリクソン―をつくりました.これはJavaを置き換える努力よりはるかに成功しました.and according to StackOverflow surveys, Elixir is currently more than twice as popular as Erlang , そして、Erlang VMの主な言語になりました.
一方、Kotlinと他の人はまだJava脅威を克服するために長い道のりを持っています.
Elixirはルビーに触発された構文を持っていますが、それは主に表面レベルの類似性です、そして、言語は非常に異なります.
Luaのエピソードのように、ルアーはブラジルから出てきた唯一の重要な技術だと言った.エリクサーは、かなりかなり成功したブラジルの言語です.
Back in 2006 I wrote an Erlang review , 私が今このシリーズのためにしていることといくぶん似ています.
そして、私が予言的な程度に正しかったことは、わかります.私がそれを書いた6年後にElixirは、^ Dを除いて全体のwishlistを届けました、そして、それはアーランよりずっと人気がありました.歴史の右側にいるのはいいことだ.
普通から始めましょう.こんにちは、世界!エリクシールで
エリキシルはreplを持ちます、しかし、それは驚くべきでありません.Ctrl - Dは全く動作しません.また、Ctrl - Cを使っているなら、この奇妙なダイアログに行きます.
あなたがあまりに近くないならば、ElixirはちょうどUnicodeを正当にサポートするようです.
しかし、表面の下で、Erlang VMのストリング状況は、巨大な混乱です.以下のような文字列型がたくさんあります. 整数のリンクリスト-どちらが「ストリング」であると思われていて、そうではないかを示す方法がない 様々なエンコーディングを持つビット文字列 原子(ルビー文字のように) Erlang言語では、それは総災害です.Erlang REPLで単純な非ASCII文字列を作成する試みは以下の通りです.
エリクサーは、これをよりよくするために、最善を尽くします.それはデフォルトでUTF 8ビット文字列にすべてのストリングを作ります.そして、それが利用可能なオプションの最も合理的であるので、適切な入力と出力を加えます.
場合によっては、根底にあるErlang VMによって混乱した文字列問題に遭遇することがあります.
fizzbuzzをしましょう!
パイプへの関数が正しい位置に正しい引数を持っている場合にのみ動作します.パイプを入れる
Rubyのような高度オブジェクト指向言語には、以下の必要があります
そしてもちろん、人々はより多くのために、両方の言語で、そして他のすべての言語でパイプラインを求め続けます.
詳細は、一歩一歩. すべての関数はモジュール内でなければなりません 関数は、すべての特定の がある ほとんどは変数を変更できません
プロセスで何かをしようとしましょう.我々は緑の人々にプロセスを生成し、それを歓迎するメッセージを私たちが望んでいるの束を送信します.
挨拶のプロセスも挨拶カウンタを保持します.
我々は、そのプロセスにメッセージ(タプル)を送ることができます 状態を維持する主な方法は関数引数です.状態を更新したい場合は、更新された引数を使って自分自身を呼び出すだけです この場合、我々は気にかけるだけです
プロセスを少し複雑にしましょう.
がある And
詳細
ここで楽しい
うまく行けば
しかし、このコードは非常に正しいことではありません.
読者のための楽しい小さな運動として、どのような余分な手順は、レースの条件を削除するために撮影する必要がありますか?とno ,プロセスを後方へ(
あなたはエリキシル対Erlangを疑問に思っている場合は、それも本当のコンテストではない.決してErlangを使用して、エリクサーは厳密にすべての考えられる方法でより良いです.
あなたがErlang VMを使用していなければならないかどうかの質問に関しては、それは間違いなく非常にユニークな同時実行モデルを提供して、本当に他のどのプラットホームででもそうすることができない方法で組織化されるソフトウェアにつながります.私は、すべての多くの問題がこの同時実行モデルを必要とすると思いません、しかし、あなたがそうするならば、Elixirはあなたにかなりきちんとした言語ですべてのこれらの能力への接近をします.
All code examples for the series will be in this repository .
Code for the Elixir episode is available here .
ある意味では、JavaとJVMの状況に似ていますが、それに対するすべてのファッショナブルな憎しみのために、Java言語はErlangの言語と同じくらい悪くどこにもありません.
それで、何人かの良い人々は正しいことをして、同じプラットホームのためにより良い言語―エリクソン―をつくりました.これはJavaを置き換える努力よりはるかに成功しました.and according to StackOverflow surveys, Elixir is currently more than twice as popular as Erlang , そして、Erlang VMの主な言語になりました.
一方、Kotlinと他の人はまだJava脅威を克服するために長い道のりを持っています.
Elixirはルビーに触発された構文を持っていますが、それは主に表面レベルの類似性です、そして、言語は非常に異なります.
Luaのエピソードのように、ルアーはブラジルから出てきた唯一の重要な技術だと言った.エリクサーは、かなりかなり成功したブラジルの言語です.
予言通り
Back in 2006 I wrote an Erlang review , 私が今このシリーズのためにしていることといくぶん似ています.
Here's my proposal:
- Conform to the basic Unix conventions like ^D, man pages, and --help.
- Throw away the old syntax and add something Python/Ruby-like. This isn't Lisp - weird syntax doesn't give you anything. Writing a decent parser in ANTLR is just one evening, and you don't have to throw away the old syntax, just provide an alternative. When you're at changing syntax, make it possible to access full language from the interpreter and limit the repeating yourself part a bit.
- Write a decent standard library - real strings with Unicode (not this lists of integers hackery), regular expressions, arrays, hash tables and so on.
- There is absolutely nothing that forces compilation by hand. Make it automatic by default.
Such changes won't interfere with the fault-safe distributed computing part even the tiniest bit. And if Erlang stays the way it is now, I think it is extremely unlikely to get out of its telecom niche.
そして、私が予言的な程度に正しかったことは、わかります.私がそれを書いた6年後にElixirは、^ Dを除いて全体のwishlistを届けました、そして、それはアーランよりずっと人気がありました.歴史の右側にいるのはいいことだ.
こんにちは、世界!
普通から始めましょう.こんにちは、世界!エリクシールで
#!/usr/bin/env elixir
IO.puts("Hello, World!")
$ ./hello.ex
Hello, World!
京大理
エリキシルはreplを持ちます、しかし、それは驚くべきでありません.Ctrl - Dは全く動作しません.また、Ctrl - Cを使っているなら、この奇妙なダイアログに行きます.
$ iex
Erlang/OTP 24 [erts-12.2] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit] [dtrace]
Interactive Elixir (1.13.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 2+2
4
iex(2)> ^C
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
(l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
a
ユニコード
あなたがあまりに近くないならば、ElixirはちょうどUnicodeを正当にサポートするようです.
#!/usr/bin/env elixir
IO.puts(String.length("Hello"))
IO.puts(String.length("Żółw"))
IO.puts(String.length("🍰"))
IO.puts(String.upcase("Żółw"))
IO.puts(String.downcase("Żółw"))
$ ./unicode.ex
5
4
1
ŻÓŁW
żółw
文字列とアーランVM
しかし、表面の下で、Erlang VMのストリング状況は、巨大な混乱です.以下のような文字列型がたくさんあります.
1> <<"Żółw">>.
<<"{óBw">>
2> <<"Żółw"/utf8>>.
<<197,187,195,179,197,130,119>>
3> "Żółw".
[379,243,322,119]
4> 'Żółw'.
'Żółw'
作業に最も近いと思われる最後のものは、実際には原子(シンボル)であり、文字列ではない.エリクサーは、これをよりよくするために、最善を尽くします.それはデフォルトでUTF 8ビット文字列にすべてのストリングを作ります.そして、それが利用可能なオプションの最も合理的であるので、適切な入力と出力を加えます.
場合によっては、根底にあるErlang VMによって混乱した文字列問題に遭遇することがあります.
iex(1)> [10,20]
[10, 20]
iex(2)> [10]
'\n'
iex(3)> [60,70,80]
'<FP'
iex(4)> 'Żółw'
[379, 243, 322, 119]
数字のいくつかのリストは、それらの内容に基づいて「文字列」として数のリストとして印刷されます.そしてそれはRPLとのための同じ規則ではないIO.puts
. 全体的なエリクサーは非常に100 %修正することができない場合でも、Erlang VM文字列混乱を修正するために本当に行く.フィズバズ
fizzbuzzをしましょう!
#!/usr/bin/env elixir
defmodule FizzBuzz do
def fizzbuzz(n) do
cond do
rem(n, 15) == 0 -> "FizzBuzz"
rem(n, 3) == 0 -> "Fizz"
rem(n, 5) == 0 -> "Buzz"
true -> n
end
end
def loop(range) do
range |> Enum.map(&fizzbuzz/1) |> Enum.each(&IO.puts/1)
end
end
1..100 |> FizzBuzz.loop
構文は漠然としたルビーのように見えます、しかし、詳細のどれも全く同じです.エリクサーの人々が一番好きなようなものは|>
演算子は、すでにジュリアのようないくつかの他の言語にその方法を行った.a |> b
ジャストジャストb(a)
, しかし、データが物事の束を流れている場合.a |> b |> c |> d
は通常、d(c(b(a)))
, または中間変数の使用.パイプへの関数が正しい位置に正しい引数を持っている場合にのみ動作します.パイプを入れる
foo(a, _)
, でもそんなにfoo(_, a)
. 他に何かのために、あなたは匿名の機能または若干の他のより複雑な構文を使用する必要があります.Rubyのような高度オブジェクト指向言語には、以下の必要があります
|>
AS.
既に正しい位置にある引数に対してのみ同じことを行いますself
引き数).エリクサーのrange |> Enum.map(&fizzbuzz/1) |> Enum.each(&IO.puts/1)
ルビーに翻訳するrange.map{|x| fizzbuzz x}.each{|x| puts x}
. 間の試合|>
連鎖と.
連鎖は正確ではありません、しかし、彼らは同様の状況の多くをカバーします.そしてもちろん、人々はより多くのために、両方の言語で、そして他のすべての言語でパイプラインを求め続けます.
詳細は、一歩一歩.
defmodule FizzBuzz do ... end
- これはちょうど迷惑です、そして、Elixirは本当にトップレベルとREPLレベルを許可しなければなりませんdef
s. do ... end
Rubyの慣習と全く一致しないので、もっとたくさんのことがありますdo
ルビーより.また、使用することができますdo: ...
for do ... end
. &fizzbuzz/1
言及するfizzbuzz(n)
, 我々は言うことができない&fizzbuzz
(それが意味するようにfizzbuzz()
). if
and if/else
, でもelsif
, どれが非常に異常かcond
これだけでなくプロセス
プロセスで何かをしようとしましょう.我々は緑の人々にプロセスを生成し、それを歓迎するメッセージを私たちが望んでいるの束を送信します.
挨拶のプロセスも挨拶カウンタを保持します.
#!/usr/bin/env elixir
defmodule Greeter do
def loop(counter) do
receive do
{:hello, msg} -> IO.puts("#{counter}: Hello, #{msg}!")
end
loop(counter + 1)
end
end
greeter_pid = spawn(fn -> Greeter.loop(1) end)
send(greeter_pid, {:hello, "World"})
send(greeter_pid, {:hello, "Alice"})
send(greeter_pid, {:hello, "Bob"})
send(greeter_pid, {:hello, "Eve"})
$ ./processes.ex
1: Hello, World!
2: Hello, Alice!
3: Hello, Bob!
4: Hello, Eve!
ここで何が起こっているのかspawn
新しいプロセスを作成し、pid (プロセスID )を返すsend
- PIDや他の識別子を使用できますloop(counter + 1)
does receive do ... end
プロセスのメールボックスから一つのメッセージを受け取り、{:hello, msg}
メッセージ、そして私たちが何をするかは、ハローと、カウンタを印刷するアカウント
プロセスを少し複雑にしましょう.
がある
Account
これらの操作により、アカウントを維持するプロセスAccount.create(name, initial_balance)
{:deposit, value}
{:withdraw, value}
Bank
プロセスBank.create
{:create_account, name, initial_balance}
メッセージ{:transfer, from_name, to_name, amount}
メッセージ#!/usr/bin/env elixir
defmodule Account do
def loop(name, balance) do
new_balance = receive do
{:deposit, value} -> balance + value
{:withdraw, value} -> balance - value
end
IO.puts("Balance for #{name} changed from #{balance} to #{new_balance}")
loop(name, new_balance)
end
def create(name, initial_balance) do
IO.puts("Account created for #{name} with initial balance #{initial_balance}")
loop(name, initial_balance)
end
end
defmodule Bank do
def transfer(map, from_name, to_name, amount) do
send(Map.get(map, from_name), {:withdraw, amount})
send(Map.get(map, to_name), {:deposit, amount})
loop(map)
end
def create_account(map, name, initial_balance) do
pid = spawn(Account, :create, [name, initial_balance])
map = Map.put(map, name, pid)
loop(map)
end
def loop(map) do
receive do
{:create_account, name, initial_balance}
-> create_account(map, name, initial_balance)
{:transfer, from_name, to_name, amount}
-> transfer(map, from_name, to_name, amount)
end
end
def create do
loop(%{})
end
end
bank = spawn(Bank, :create, [])
send(bank, {:create_account, "Alice", 1000})
send(bank, {:create_account, "Bob", 2000})
send(bank, {:create_account, "Eve", 200})
send(bank, {:transfer, "Alice", "Bob", 500})
send(bank, {:transfer, "Bob", "Eve", 220})
それはすべての主流言語よりもはるかに非同期です.どのように意味があるのかに注意してください.$ ./accounts.ex
Account created for Alice with initial balance 1000
Account created for Eve with initial balance 200
Account created for Bob with initial balance 2000
Balance for Eve changed from 200 to 420
Balance for Bob changed from 2000 to 2500
Balance for Alice changed from 1000 to 500
Balance for Bob changed from 2500 to 2280
$ ./accounts.ex
Account created for Bob with initial balance 2000
Account created for Eve with initial balance 200
Account created for Alice with initial balance 1000
Balance for Alice changed from 1000 to 500
Balance for Bob changed from 2000 to 2500
Balance for Eve changed from 200 to 420
Balance for Bob changed from 2500 to 2280
プロセスが生成され、メッセージが送信されますが、彼らが処理されると謎であり、そのために準備する必要があります.詳細
Account
- 全ての状態name
) と変数balance
) 引数として存在するloop
- バランスを更新するには、新しい引数を使って呼び出しますBank
- 唯一の状態は、アカウントからアカウントプロセスIDへのマップですアカウント残高はアカウントプロセスにのみ存在する.If Bank
それらを知りたかった.Account
のような操作を実装する必要があります(get_balance
) そして、それはアカウントをpingする必要があります.もちろん、すべてがasyncであるなら、それは必ずしも最終的な状態ではないでしょう.spawn(Account, :create, [name, initial_balance])
別の構文spawn(fn -> Account.create(name, initial_balance) end)
, 余分な匿名関数なしでフィボナッチ
ここで楽しい
Fibonacci
すべての方法でプロセスを実装する.うまく行けば
fib(20)
プロセスはメッセージを受け取る{:fib, 18, 2584}
and {:fib, 19, 4181}
, そして、それが計算されたものを印刷し、その結果をメッセージとして送る{:fib, 20, 6765}
処理するfib21
and fib22
それで、チェーンはすべて継続することができます.しかし、このコードは非常に正しいことではありません.
Process.register
シンボル名をプロセスに関連付ける方法であり、プロセスIDに送ることができるように、そのような名前にメッセージを送ることができます.読者のための楽しい小さな運動として、どのような余分な手順は、レースの条件を削除するために撮影する必要がありますか?とno ,プロセスを後方へ(
40..1
) 答えではない.#!/usr/bin/env elixir
defmodule Fib do
def done(n, value) do
IO.puts("fib(#{n}) = #{value}")
send(:"fib#{n+1}", {:fib, n, value})
send(:"fib#{n+2}", {:fib, n, value})
end
def waitforprevious(n, a, b) do
{a, b} = receive do
{:fib, m, value} -> cond do
m == n - 1 -> {value, b}
m == n - 2 -> {a, value}
true -> {a, b}
end
end
if (a == 0 or b == 0) do
waitforprevious(n, a, b)
else
done(n, a + b)
end
end
def calculate(n) do
if n <= 2 do
done(n, 1)
else
waitforprevious(n, 0, 0)
end
end
end
(1..40) |> Enum.each(fn n ->
Process.register(spawn(Fib, :calculate, [n]), :"fib#{n}")
end)
いずれかのことが起こる-レースの条件によって打たれたか、しなかったいずれか$ ./fib.ex
fib(1) = 1
fib(2) = 1
$ ./fib.ex
fib(1) = 1
fib(2) = 1
fib(3) = 2
fib(4) = 3
fib(5) = 5
fib(6) = 8
fib(7) = 13
fib(8) = 21
fib(9) = 34
fib(10) = 55
fib(11) = 89
fib(12) = 144
fib(13) = 233
fib(14) = 377
fib(15) = 610
fib(16) = 987
fib(17) = 1597
fib(18) = 2584
fib(19) = 4181
fib(20) = 6765
fib(21) = 10946
fib(22) = 17711
fib(23) = 28657
fib(24) = 46368
fib(25) = 75025
fib(26) = 121393
fib(27) = 196418
fib(28) = 317811
fib(29) = 514229
fib(30) = 832040
fib(31) = 1346269
fib(32) = 2178309
fib(33) = 3524578
fib(34) = 5702887
fib(35) = 9227465
fib(36) = 14930352
fib(37) = 24157817
fib(38) = 39088169
fib(39) = 63245986
fib(40) = 102334155
ああ、実際の世界では、おそらくほとんどのレベルではなく、より高いレベルの機能を使用するspawn
and send
閉じるこの動画はお気に入りから削除されています.あなたはエリクサーを使用する必要がありますか?
あなたはエリキシル対Erlangを疑問に思っている場合は、それも本当のコンテストではない.決してErlangを使用して、エリクサーは厳密にすべての考えられる方法でより良いです.
あなたがErlang VMを使用していなければならないかどうかの質問に関しては、それは間違いなく非常にユニークな同時実行モデルを提供して、本当に他のどのプラットホームででもそうすることができない方法で組織化されるソフトウェアにつながります.私は、すべての多くの問題がこの同時実行モデルを必要とすると思いません、しかし、あなたがそうするならば、Elixirはあなたにかなりきちんとした言語ですべてのこれらの能力への接近をします.
コード
All code examples for the series will be in this repository .
Code for the Elixir episode is available here .
Reference
この問題について(100言語Spedrdrun :エピソード81:エリクサー), 我々は、より多くの情報をここで見つけました https://dev.to/taw/100-languages-speedrun-episode-81-elixir-1241テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol