Част от общата концепция на Elixir и Erlang е грешките да бъдат фатални и да убиват процеса, в който са възникнали.
Нека някой друг процес (supervisor) се оправя с проблема.
{:error, <проблем>}
{:ok, <резултат>}
raise "Ужаст!" #=> (RuntimeError) Ужаст!
raise RuntimeError #=> (RuntimeError) runtime error
raise ArgumentError, message: "Грешка, брато!" #=> (ArgumentError) Грешка, брато!
try do 1 / 0 rescue [RuntimeError, ArgumentError] -> IO.puts("Няма да стигнем до тук.") error in [ArithmeticError] -> IO.puts("На нула не се дели, #{error.message}") any_other_error -> IO.puts("Лошаво... #{any_other_error.message}") else IO.puts("Няма грешка.") after IO.puts("Finally!") end
defmodule VeryBadError do defexception message: "Лошо!!!" end
try do raise VeryBadError rescue error in VeryBadError -> IO.puts(inspect(error, structs: false)) end #=> %{ #=> __exception__: true, #=> __struct__: VeryBadError, #=> message: "Лошо!!!" #=> }
defmodule EvenWorseError do defexception [:message] @impl true def exception(value) do msg = "An even worst error was raised with value #{inspect(value)}" %EvenWorseError{message: msg} end end
try do raise EvenWorseError, :my_bad rescue error in EvenWorseError -> IO.puts(error.message) end
throw
try do b = 5 throw b IO.puts "this won't print" catch :some_atom -> IO.puts "Caught #{:some_atom}!" x when is_integer(x) -> IO.puts(x) end #=> 5
try do exit("I am exiting") # така можем да излезем от процес catch :exit, _ -> IO.puts "not really" end # и процесът всъщност остава жив
defmodule Quitter do def run do Process.sleep(3000) exit(:i_am_tired) end end Process.flag(:trap_exit, true) spawn_link(Quitter, :run, []) receive do msg -> IO.inspect(msg); end # {:EXIT, #PID<0.95.0>, :i_am_tired}
action = fn -> :nothing end system_process = true # Ако е false този процес ще си чака Process.flag(:trap_exit, system_process) pid = spawn_link(action) receive do msg -> IO.inspect(msg) end # {:EXIT, <pid>, :normal}
action = fn -> exit(:stuff) end system_process = true # Ако е false този процес ще умре с ** (EXIT from <pid>) :stuff Process.flag(:trap_exit, system_process) pid = spawn_link(action) receive do msg -> IO.inspect(msg) end # {:EXIT, <pid>, :stuff}
action = fn -> exit(:normal) end system_process = true # Ако е false този процес ще си чака Process.flag(:trap_exit, system_process) pid = spawn_link(action) receive do msg -> IO.inspect(msg) end # {:EXIT, <pid>, :normal}
action = fn -> raise("Stuff") end system_process = true # Ако е false този процес умира с # [error] Process <pid> raised an exception ** (RuntimeError) Stuff Process.flag(:trap_exit, system_process) pid = spawn_link(action) receive do msg -> IO.inspect(msg) end # {:EXIT, <pid>, # {%RuntimeError{message: "Stuff"}, # [{:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 668]}]}}
action = fn -> throw("Stuff") end system_process = true # Ако е false този процес умира с # [error] Process <pid> raised an exception ** (ErlangError) erlang error: {:nocatch, "Stuff"} Process.flag(:trap_exit, system_process) pid = spawn_link(action) receive do msg -> IO.inspect(msg) end # {:EXIT, <pid>, # {{:nocatch, "Stuff"}, # [{:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 668]}]}}
:kill
IO.puts/2
IO.write/2
IO.puts("По подразбиране пишем на стандартния изход.") IO.puts(:stdio, "Можем да го направим и така.") IO.puts(:stderr, "Или да пишем в стандартния изход за грешки.")
IO.write(:stderr, "Това е грешка!")
puts
write
device
"Далия"
[83, 79, 0x53]
[?S, ?O, ?S]
'SOS'
[83, 79, 83, "mayday!"]
[[83], [79, ["dir", 78]]]
IO.chardata_to_string([1049, [1086, 1091], "!"]) #=> "Йоу!"
chain
defmodule TaskEnum do def map(enumerable, fun) do enumerable |> IO.inspect(label: "Input", structs: false) |> Enum.map(& Task.async(fn -> fun.(&1) end)) |> IO.inspect(label: "Tasks", width: 120, limit: :infinity) |> Enum.map(& Task.await(&1)) end end
IO.read(:line) Хей, Хей<enter> #=> "Хей, Хей\n"
IO.gets("Кажи нещо!\n") Кажи нещо! Нещо!<enter> #=> "Нещо!\n"
read
binwrite
binread
iodata
chardata
IO.iodata_length([1, 2 | <<3, 4>>]) #=> 4
IO.iodata_to_binary([1, << 2 >>, [[3], 4]]) #=> <<1, 2, 3, 4>>
{:ok, file} = File.open("test.txt", [:write]) #=> {:ok, #PID<0.855.0>} IO.binwrite(file, "some text!") #=> :ok File.close(file) #=> :ok
{:ok, file} = File.open("program.txt", [:read]) #=> {:ok, #PID<0.82.0>} IO.stream(file, :line) |> Stream.map(fn line -> line <> "!" end) |> Stream.each(fn line -> IO.puts line end) |> Stream.run()
File.stream!(input_name, read_ahead: <buffer_size>) |> Stream.<transform-or-filter> |> Stream.into(File.stream!(output_name, [:delayed_write])) |> Stream.run
IO.ANSI
IO.puts [IO.ANSI.blue(), "text", IO.ANSI.reset()]
StringIO
{:ok, pid} = StringIO.open("data") #PID<0.136.0>} StringIO.contents(pid) # {"data", ""} IO.write(pid, "doom!") #:ok StringIO.contents(pid) # {"data", "doom!"} IO.read(pid, :line) # "data" StringIO.contents(pid) # {"", "doom!"} StringIO.close(pid) # {:ok, {"", "doom!"}}
{:ok, file} = File.open("data", [:ram]) #=> {:ok, {:file_descriptor, :ram_file, #Port<0.1578>}} IO.binread(file, :all) #=> "data"
IO.binread(file, :all) #=> ""
:file.position(file, :bof) IO.binread(file, :all) #=> "data"
Path
Path.join("some", "path") #=> "some/path" Path.expand("~/development") #=> "/home/meddle/development"