2016-07-21 17 views
7

W ExProf, nazwy funkcji Elixir są drukowane, jak zakładam są ich nazwy Erlang, po kompilacji. Jednym z przykładów jestJak rozumieć skompilowane nazwy funkcji Erlang Elixir

Enum.reduce/3 

który jest drukowany jako

'Elixir.Enum':'-reduce/3-lists^foldl/2-0-'/3 

Jak analizować ten ciąg? Skąd pochodzi część -lists^foldl/2-0-? Dlaczego istnieje wiele różnych /3? Dlaczego niektóre nazwy mają prefiks -? Co oznacza ^? Dlaczego 2-0-?

+2

Spojrzenie na [źródło] (https://github.com/elixir-lang/elixir/blob/ad3c7c6c600e264c3cb00bba43b20b46c7e0e063/lib/elixir/lib/enum.ex#L1683) staje się jasne, gdzie listy^foldl pochodzi z. Do końca jestem nieświadomy, szczególnie dla/2 części. Byłoby miło wiedzieć, czy nazwa funkcji zmienia się z każdym przypadkiem w źródle. – SpaceMonkey

+0

Kilka szczegółów: Tak właśnie wygląda odniesienie do funkcji erlang. Części są cytowane, ponieważ zawierają znaki, które muszą być cytowane w atomach erlang. Pierwsza część, przed ':' jest nazwą modułu erlang, który jest generowany, druga część jest nazwą funkcji, która jest generowana. Jego nazwa to po prostu podpis zbudowany z oryginalnej nazwy funkcji eliksiru i do której deleguje. I wreszcie jest faktyczna aranżacja całości. dlaczego foldl jest wstawiony do podpisu z arnością 2-0 jest poza mną. – greggreg

+0

Wciąż dobrze byłoby wiedzieć, dlaczego tak się dzieje. Jeśli zajrzysz do README w [ExProf] (https://github.com/parroty/exprof) ten schemat nazewnictwa nie jest wcale oczywisty. Tak czy inaczej, ExProf nie wydaje się być zainteresowany konwencjami nazewnictwa i po prostu bierze nazwy od eprof (co jest Erlang), jak podano. – SpaceMonkey

Odpowiedz

1

Jak przeanalizować ten ciąg?

'Elixir.Enum':'-reduce/3-lists^foldl/2-0-'/3 jest funkcją składni odniesienia Erlang odnosi się do funkcji o nazwie -reduce/3-lists^foldl/2-0- w module Elixir.Enum z Arity 3, podobnie jak w &Enum."-reduce/3-lists^foldl/2-0-"/3 eliksiru.

Skąd pochodzi część -lists^foldl/2-0-?

The -$fn/$arity-$something-$count- to nazwa zwracana przez Erlang w stacktraces (i wyjściu najwyraźniej profilowania) do funkcji anonimowej zdefiniowanej wewnątrz $fn/$arity. Normalnie, można zobaczyć coś takiego -main/0-fun-0-, tj $something == "fun" na przykład w ten sposób:

defmodule Foo do 
    def main do 
    try do 
     (fn -> raise("foo") end).() 
    rescue 
     _ -> IO.inspect System.stacktrace 
    end 
    end 
end 

drukuje:

[{Foo, :"-main/0-fun-0-", 0, [file: 'foo.ex', line: 4]}, 
{Foo, :main, 0, [file: 'foo.ex', line: 4]}, 
{:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 670]}, 
{:elixir, :erl_eval, 3, [file: 'src/elixir.erl', line: 223]}, 
{:elixir, :eval_forms, 4, [file: 'src/elixir.erl', line: 211]}, 
{Code, :eval_string, 3, [file: 'lib/code.ex', line: 168]}, 
{Kernel.CLI, :wrapper, 1, [file: 'lib/kernel/cli.ex', line: 437]}, 
{Enum, :"-map/2-lists^map/1-0-", 2, [file: 'lib/enum.ex', line: 1184]}] 

to po prostu, że jesteś mniej prawdopodobne, aby zobaczyć -fun- te w wiadomościach domyślny błędach eliksir za ponieważ w tym przypadku są one normalized, anonymous fn/0 in Foo.main/0 (dlatego właśnie wydrukowałem powyższy stos, wywołując jawnie podając System.stacktrace/0).

Skąd pochodzi lists^foldl/2? To jest generated by sys_core_fold_lists, moduł called by sys_core_fold dla modułów definiujących atrybut kompilacji inline_list_funcs (moduł Enum w Elixir does do that), który "włącza funkcje listy wysokich rzędów z modułu list". To wstawianie nadaje również nazwę "lists^foldl/2" funkcji anonimowej, a nie tylko "zabawie".

Oto proste demo:

defmodule Fold do 
    @compile :inline_list_funcs 

    def main do 
    sum([1, 2, 3]) 
    end 

    def sum(list) do 
    :lists.foldl(fn a, b -> raise "foo" end, 0, list) 
    end 
end 

Fold.main 

Z @compile :inline_list_funcs, wyjście jest:

** (RuntimeError) foo 
    fold.exs:9: anonymous fn/2 in Fold.sum/1 
    fold.exs:9: Fold."-sum/1-lists^foldl/2-0-"/3 
    (elixir) lib/code.ex:363: Code.require_file/2 

i bez niego, wyjście jest:

** (RuntimeError) foo 
    fold.exs:9: anonymous fn/2 in Fold.sum/1 
    (stdlib) lists.erl:1263: :lists.foldl/3 
    (elixir) lib/code.ex:363: Code.require_file/2 

Z tego atrybutu, my nie ma żadnego wpisu stacktrace dla modułu lists, mimo że mówimy explicite to nazywa się :lists:foldl.

Dlaczego istnieje wiele numerów /3?

To wydaje się być efektem ubocznym Erlanga, w tym aktualności funkcji podczas nadawania nazwy anonimowej funkcji.

Dlaczego niektóre nazwy mają prefiks -?

Wyjaśnienie powyżej.

Co oznacza ^?

To tylko imię wybrane przez sys_core_fold_lists:call/4.

Dlaczego 2-0-?

2 pochodzi z sys_core_fold_lists:call/4. 0 jest referred to as "count" in Exception.format_mfa/3, ale nie jestem pewien, co to oznacza.

0

Jest to wygenerowana nazwa jakiejś funkcji "anonimowej" w implementacji Enum.reduce. Zakładam, że ta funkcja jest zdefiniowana inline i przekazana jako argument do lists:foldl, stąd nazwa. AFAIK takie nazwy są generowane nie przez Elixir, ale przez sam Erlang.