13 alias,require와 import - alias, require and import
소프트웨어 재사용을 용이하게하기 위해 Elixir는 3개의 지시어(directives)를 제공합니다. 밑에서 살펴보겠지만 lexical scope를 가지고 있어 지시어(directives)라고 합니다.
In order to facilitate software reuse, Elixir provides three directives. As we are going to see below, they are called directives because they have lexical scope.
13.1 alias - alias
alias
로 어떤 모듈에도 별명을 붙일 수 있습니다. Math
모듈이 수학에 특화된 오퍼레이션을 위해 특별한 리스트의 구현을 사용한다고 가정해봅시다:
alias
allows you to set up aliases for any given module name. Imagine our Math
module uses a special list implementation for doing math specific operations:
defmodule Math do
alias Math.List, as: List
end
이제부터 List
의 모든 참조는 Math.List
로 확장됩니다. 오리지날 List
에 접근하려면 Elixir
모듈을 통해 접근하게 됩니다:
From now on, any reference to List
will automatically expand to Math.List
. In case one wants to access the original List
, it can be done by accessing the module via Elixir
:
List.flatten #=> uses Math.List.flatten
Elixir.List.flatten #=> uses List.flatten
Elixir.Math.List.flatten #=> uses Math.List.flatten
주의: Elixir에 정의된 모든 모듈은 Elixir 네임스페이스에 정의되어 있습니다. 그러나 편의를 위해 참조 할 때 "Elixir"를 생략 할 수 있습니다.
Note: All modules defined in Elixir are defined inside a main Elixir namespace. However, for convenience, you can omit "Elixir." when referencing them.
Alias는 숏컷(shortcuts)을 정의하는데 자주 사용됩니다. 사실 :as
옵션 없이 alias
를 호출하면 모듈 이름의 마지막 부분을 자동으로 별칭(alias)으로 설정합니다. 예를들면:
Aliases are frequently used to define shortcuts. In fact, calling alias
without an :as
option sets the alias automatically to the last part of the module name, for example:
alias Math.List
다음과 같습니다:
Is the same as:
alias Math.List, as: List
alias
는 lexical scope 하기 때문에 특정 함수안에서도 별칭(alias)을 설정 할 수 있습니다:
Note that alias
is lexically scoped, which allows you to set aliases inside specific functions:
defmodule Math do
def plus(a, b) do
alias Math.List
# ...
end
def minus(a, b) do
# ...
end
end
위의 예와 같이 alias
를 함수 plus/2
에서 호출해도, 별칭(alias)은 함수 plus/2
내에서만 유효하며 minus/2
에 전혀 영향을주지 않습니다.
In the example above, since we are invoking alias
inside the function plus/2
, the alias will just be valid inside the function plus/2
. minus/2
won't be affected at all.
13.2 require - require
Elixir는 메타 프로그래밍(코드를 생성하는 코드를 작성)을위한 메커니즘으로 매크로를 제공합니다.
Elixir provides macros as a mechanism for meta-programming (writing code that generates code).
매크로는 실행 및 컴파일시에 확장되는 코드의 덩어리입니다. 이 말은 매크로를 사용하기 위해서는 모듈의 구현이 컴파일 중에 있어야 한다는 의미입니다. require
지시어(directives)를 사용하면 매크로를 컴파일하고 이후에 사용할 수 있습니다:
Macros are chunks of code that are executed and expanded at compilation time. This means, in order to use a macro, we need to guarantee its module and implementation are available during compilation. This is done with the require
directive:
iex> Integer.is_odd(3)
** (CompileError) iex:1: you must require Integer before invoking the macro Integer.is_odd/1
iex> require Integer
nil
iex> Integer.is_odd(3)
true
Elixir에서 Integer.is_odd?/1
는 매크로로 정의되어 있기 때문에 가드(guard)로 사용할 수 있습니다. 즉, Integer.is_odd?/1
을 실행하기 위해서는 먼저 Integer
모듈이 필요합니다.
In Elixir, Integer.is_odd/1
is defined as a macro so it can be used as guards. This means that, in order to invoke Integer.is_odd/1
, we need to first require the Integer
module.
일반적으로 모듈의 매크로를 사용하는 경우를 제외하고는 사용하기 전에 모듈을 require할 필요가 없습니다. 로드되지 않은 매크로를 호출하려고 하면 오류가 발생합니다. alias
지시어(directives)와 마찬가지로 require
도 lexically scoped인 것에 주목하십시오. 매크로에 대해서는 이후의 장에서 다시 자세히 이야기 할것입니다.
In general a module does not need to be required before usage, except if we want to use the macros available in that module. An attempt to call a macro that was not loaded will raise an error. Note that like the alias
directive, require
is also lexically scoped. We will talk more about macros in a later chapter.
13.3 import - import
규정된 이름을 사용하지 않고 다른 모듈의 함수 또는 매크로에 쉽게 접근하고 싶을 때 import
를 사용합니다. 예를들어 List
의 duplicate
함수를 여러 번 사용하려면 그냥 import 하면 됩니다:
We use import
whenever we want to easily access functions or macros from other modules without using the qualified name. For instance, if we want to use the duplicate
function from List
several times, we can simply import it:
iex> import List, only: [duplicate: 2]
nil
iex> duplicate :ok, 3
[:ok, :ok, :ok]
이 경우, List
에서 duplicate
(인자가 2개인것)함수만 가져올 수 있습니다. 비록 :only
는 옵션이지만 사용을 권장하고 있습니다. :except
도 옵션으로 제공됩니다.
In this case, we are importing only the function duplicate
(with arity 2) from List
. Although :only
is optional, its usage is recommended. :except
could also be given as an option.
import
는 :only
옵션으로 :macros
와 :functions
을 전달할 수도 있습니다. 예를들어 모든 매크로를 가져 오려면 이렇게 쓸 수 있습니다:
import
also supports :macros
and :functions
to be given to :only
. For example, to import all macros, one could write:
import Integer, only: :macros
또는 모든 함수를 가져오려면 이렇게 쓸 수 있습니다:
Or to import all functions, you could write:
import Integer, only: :functions
import 또한 lexically scoped인 점에 유의하십시오, 이 말은 특정 함수에서 특정 매크로를 가져올 수 있다는 것을 의미합니다:
Note that import
is also lexically scoped, this means we can import specific macros inside specific functions:
defmodule Math do
def some_function do
import List, only: [duplicate: 2]
# call duplicate
end
end
위의 예에서 List.duplicate/2
는 특정 함수 내에서만 보입니다. duplicate/2
는 모듈의 다른 어떤 함수에서도 (물론 다른 모듈에서도)사용할 수 없습니다.
In the example above, the imported List.duplicate/2
is only visible within that specific function. duplicate/2
won't be available in any other function in that module (or any other module for that matter).
모듈을 import하면 자동으로 require한다는 점에 유의하십시오.
Note that importing a module automatically requires it.
13.4 Alias - Aliases
이 시점즈음에는 도대체 Elixir의 별칭(alias)은 실제로 무엇이며 어떻게 표현되고 있는지 궁금해하고 있을것입니다.
At this point, you may be wondering, what exactly an Elixir alias is and how it is represented?
Elixir의 별칭(alias)은 (String, Keyword등과 같은) 컴파일하는 동안 원자형으로 변환되는 대문자로 시작하는(capitalized) 식별자입니다. 예를들어 String
별칭(alias)은 기본적으로 원자형 :"Elixir.String"
로 변환됩니다:
An alias in Elixir is a capitalized identifier (like String
, Keyword
, etc) which is converted to an atom during compilation. For instance, the String
alias translates by default to the atom :"Elixir.String"
:
iex> is_atom(String)
true
iex> to_string(String)
"Elixir.String"
iex> :"Elixir.String"
String
alias/2
지시어(directive)를 사용하면 단순히 어떤 별칭(alias)으로 바꾸고 있습니다.
By using the alias/2
directive, we are simply changing what an alias translates to.
정확히 말하면 Erlang VM에서 (즉 Elixir도) 모듈이 원자형으로 표현되기 때문에 별칭(alias)이 동작할 수 있는 것입니다. 예를들어 Erlang 모듈을 사용할 때의 메커니즘은 이렇습니다:
Aliases work as described because in the Erlang VM (and consequently Elixir), modules are represented by atoms. For example, that's the mechanism we use to call Erlang modules:
iex> :lists.flatten([1,[2],3])
[1, 2, 3]
모듈의 내부의 함수를 동적으로 호출 할 수있는 메커니즘입니다:
This is also the mechanism that allows us to dynamically call a given function in a module:
iex> mod = :lists
:lists
iex> mod.flatten([1,[2],3])
[1,2,3]
다시 말해서, 원자형 :lists
의 함수 flatten
를 단순히 호출하고 있을뿐입니다.
In other words, we are simply calling the function flatten
on the atom :lists
.
13.5 중첩 - Nesting
지금까지는 별칭(alias)에 대해 얘기했습니다, Elixir에서 중첩이 어떻게 작동하는지에 대해서도 말씀 드리겠습니다. 다음의 예를 살펴 봅시다:
Now that we have talked about aliases, we can talk about nesting and how it works in Elixir. Consider the following example:
defmodule Foo do
defmodule Bar do
end
end
위의 예는 Foo
와 Foo.Bar
두 개의 모듈을 정의하고 있습니다. Foo
안의 Bar
가 같은 lexical scope안에 있는 동안은 Bar
만으로도 접근할 수 있습니다. 만약 개발자가 나중에 Bar
를 다른 파일로 옮기고 이를 참조하기 위해서는 풀네임(Foo.Bar
)을 쓰거나 별칭(alias)이 설정되야 합니다.
The example above will define two modules Foo
and Foo.Bar
. The second can be accessed as Bar
inside Foo
as long as they are in the same lexical scope. If later the developer decides to move Bar
to another file, it will need to be referenced by its full name (Foo.Bar
) or an alias needs to be set using the alias
directive discussed above.
다시 말해서 위의 코드는 다음과 같습니다:
In other words, the code above is exactly the same as:
defmodule Elixir.Foo do
defmodule Elixir.Foo.Bar do
end
alias Elixir.Foo.Bar, as: Bar
end
이후 장에서 보겠지만 별칭(alias)은 매크로에서 매우 중요한 역할을 담당합니다. Elixir 모듈에 대해서는 거의 끝나갑니다. 마지막으로 모듈의 특성에 대해 살펴 보겠습니다.
As we will see in later chapters, aliases also play a crucial role in macros, to guarantee they are hygienic. With this we are almost finishing our tour about Elixir modules, the last topic to cover is module attributes.