2017-09-08 13 views
0

ここには、組み込み関数と全く同じ名前の別の関数を呼び出す関数で2つのブレークポイントを持つ単純なモジュールがあります。get/1put/2同じ名前のエリクサーデバッガーが私の代わりに組み込み関数を呼び出す理由

私のの代わりに関数の put/2を内蔵実行 get/1にデバッガ結果から get/1呼び出し、

iex(1)> Test.call_get 
Break reached: Test.call_get/0 (lib/test.ex:7) 

    5: end 
    6: def call_get() do 
    7:  require IEx; IEx.pry 
    8:  get("k") 
    9: end 
pry(1)> get("a") 
:undefined 
pry(2)> Test.get("a") 
Doing get 
:ok 

それが見えるように:

defmodule Test do 
    def call_put() do 
    require IEx; IEx.pry 
    put("k", "v") 
    end 
    def call_get() do 
    require IEx; IEx.pry 
    get("k") 
    end 

    def put(_k, _v)do 
    IO.puts("Doing put") 
    end 
    def get(_k) do 
    IO.puts("Doing get") 
    end 
end 

シェルでそれを実行しますモジュール。 正しく機能させるには、関数呼び出しの名前空間を設定する必要があります。誰も私にこの行動を説明できますか?

+1

私は、現在のモジュールの機能が 'IEx.pry'セッションで自動的に"インポート "されるとは思いません。セッションの開始時に 'import test'を実行するだけです。 – Dogbert

答えて

2

ここで起こっていることは、コンテキストが異なることです。見て:get/0機能のASTは、コンテキストが含まれるであろう

iex|1 ▶ defmodule Test do 
...|1 ▶ def get(p), do: p        
...|1 ▶ IO.inspect quote do: (def get(), do: get(42)) 
...|1 ▶ end 
{:def, [context: Test, import: Kernel], 
[{:get, [context: Test], []}, [do: {:get, [], '*'}]]} 

{:get, [context: Test], []} 

これは、コンパイラが修飾されていない機能のために呼び出すことを知っている方法です。基本的に、同じモジュール内で関数を無条件に呼び出すことは、構文的な砂糖です。ブレークポイントでは、モジュールはすでにコンパイルされており、「ローカル」関数がないため、「ローカル」関数へのアクセスはありません。 import Testを使用して、それらの修飾されていない名前で関数にアクセスすることができます。

+1

2つのことの振る舞いが同じではないので、「同じモジュール内の関数を無条件に呼び出すことはできません」とは、「統語的砂糖」とは考えません。 https://stackoverflow.com/questions/32923026/using-fully-qualified-function-calls-in-erlangで説明されているように、完全修飾された関数呼び出しと通常の呼び出しを参照してください。 – Dogbert

+0

私は 'quote do:(def get()、do:get(42))'を 'defmodule Test'の中から実行したときとまったく同じASTを取得しています。私はこれがローカルコールがうまくいかない理由だとは思わない。私は新しい 'iex'セッションでコードを実行すると' context:Elixir'でASTを取得します。 – Dogbert

関連する問題