티스토리 뷰

10_Multiple_dispatch(한글)

Multiple dispatch

참고문헌

https://github.com/JuliaComputing/JuliaBoxTutorials/tree/master/introductory-tutorials/intro-to-julia (github : JuliaComputing/JuliaBoxTutorials/introductory-tutorials/intro-to-julia/)

Topics:

  1. 친근한 예제로 시작하기
  2. Input의 type 특정지어주기
  3. 연습문제

함께보기

여기서 우리는 Julia의 주요 특징 중 하나인 multiple dispatch에 대해 살펴볼거다.

Multiple dispatch 는 소프트웨어를 일반적이고 빠르게 만들어준다!

친근한 예제로 시작하기

Multiple dispatch를 이해하기 위해서, 이전에 본 적 있는 예제로 시작할거다.

함수를 선언할 때, 아래와 같이 input의 type에 대한 아무런 정보를 주지 않고 만들 수 있다.

In [1]:
f(x) = x^2
Out[1]:
f (generic function with 1 method)

그러면 Julia는아래와 같이 input이 그럴듯한지 아닌지 스스로 판단하게 된다.

In [2]:
f(10)
Out[2]:
100
In [3]:
f([1, 2, 3])
MethodError: no method matching ^(::Array{Int64,1}, ::Int64)
Closest candidates are:
  ^(!Matched::Float16, ::Integer) at math.jl:782
  ^(!Matched::Missing, ::Integer) at missing.jl:120
  ^(!Matched::Missing, ::Number) at missing.jl:93
  ...

Stacktrace:
 [1] macro expansion at ./none:0 [inlined]
 [2] literal_pow at ./none:0 [inlined]
 [3] f(::Array{Int64,1}) at ./In[1]:1
 [4] top-level scope at In[3]:1

Input의 type 특정지어주기

그러나 Julia에게 어떤 input의 type을 허용하는지 명시적으로 알려줄 수 있다.

예를 들어, String을 input으로 사용하는 foo 함수를 작성해 보자.

In [4]:
foo(x::String, y::String) = println("x랑 y 둘 다 string이다!")
Out[4]:
foo (generic function with 1 method)

보이다시피, input 다음에 콜론을 2개 써서 xy의 type을 String으로 제한시켰다.

이제 fooString에만 작동하고 다른 input에는 작동하지 않는다.

In [5]:
foo("hello", "hi!")
x랑 y 둘 다 string이다!
In [6]:
foo(3, 4)
MethodError: no method matching foo(::Int64, ::Int64)

Stacktrace:
 [1] top-level scope at In[6]:1

foo 함수가 integer(Int)에도 작동하게 하기 위해서, ::Int 를 사용해서 다음과 같이 foo를 정의할 수 있다.

In [7]:
foo(x::Int, y::Int) = println("x랑 y 둘 다 integer다!")
Out[7]:
foo (generic function with 2 methods)
In [8]:
foo(3, 4)
x랑 y 둘 다 integer다!

이제 foo는 integer에도 작동한다. 그러나, 여전히 xyString일 때도 작동함을 아래를 통해 볼 수 있다.

In [9]:
foo("hello", "hi!")
x랑 y 둘 다 string이다!

이게 multiple dispatch의 핵심이다. 아래와 같이 선언했을 때,

foo(x::Int, y::Int) = println("My inputs x and y are both integers!")

아래 코드는 위의 코드를 덮어쓰기 하거나 대체하지 않는다.

foo(y::String, y::String)

대신에, foo라고 불리는 generic functionmethod를 추가로 더했을 뿐이다.

generic function은 특정 연산에 대한 추상적인 개념이다.

예를 들어, generic function + 은 덧셈에 대한 개념이다.

method특정 argument type에 대한 generic function의 구현이다.

예를 들어, +에는 실수, 정수, 행렬 등등을 수용하는 여러 method가 있다.

methods를 이용해서 foo에 얼마나 많은 method가 있는지 볼 수 있다.

In [10]:
methods(foo)
Out[10]:
2 methods for generic function foo:
  • foo(x::Int64, y::Int64) in Main at In[7]:1
  • foo(x::String, y::String) in Main at In[4]:1

참고 : 더하는 데는 얼마나 많은 방법이 있을까?

In [11]:
methods(+)
Out[11]:
163 methods for generic function +:

그래서 이제 foo는 integer와 string에 대해서 사용할 수 있다. 특정 input에 foo를 사용하면, Julia는 어떤 타입의 input인지 추론하고, 적절한 method를 빠르게 전달한다. 이것이 multiple dispatch다.

Multiple dispatch는 우리 코드를 일반적이고 빠르게 만든다. 우리 코드는 일반적이고 유연해질 수 있는데, 왜냐하면 특정 구현(specific implementations)으로 코드를 쓰는 것이 아니라 덧셈과 곱셈 같은 추상 연산(abstract operations)으로 코드를 쓸 수 있기 때문이다. 동시에, 빨리 실행되는데, 그 이유는 관련된 타입에 있어서 효율적인 method를 불러낼 수 있기 때문이다.

generic function을 불러낼 때, 어떤 method가 전달되는지 보기 위해서는, @which macro를 사용한다.

In [12]:
@which foo(3, 4)
Out[12]:
foo(x::Int64, y::Int64) in Main at In[7]:1

더하기에도 @which를 사용해보자.

In [13]:
@which 3.0 + 3.0
Out[13]:
+(x::Float64, y::Float64) in Base at float.jl:395

함수 foo에 다른 method를 더 적용시킬 수 있다. IntFloat64 등등 숫자로 생각되는 모든 object를 포함하는 추상적인 typenumber를 사용하는 method를 추가하자.

In [14]:
foo(x::Number, y::Number) = println("x랑 y 둘 다 number이다!")
Out[14]:
foo (generic function with 3 methods)

This method for foo will work on, for example, floating point numbers:

In [15]:
foo(3.0, 4.0)
x랑 y 둘 다 number이다!

또한 이전에 한 적이 있는, any type을 input으로 받는 duck-typed method를 foo에 추가할 수 있다.

In [16]:
foo(x, y) = println("나는 any type을 input으로 넣어도 실행된다!")
Out[16]:
foo (generic function with 4 methods)

지금까지 foo에 적용한 method를 감안할 때,이 method는 non-numbers를 foo의 input으로 넣을 때 마다 적용될 것이다.

In [17]:
v = rand(3)
foo(v, v)
나는 any type을 input으로 넣어도 실행된다!

연습문제

10.1

함수 foo를 확장하자. Bool type 하나를 input으로 넣을 때, "foo with one boolean!" 이라는 문구가 출력되는 method를 추가하자.

In [18]:
foo(x::Bool) = println("boolean 한 개로 실행됐다!")
Out[18]:
foo (generic function with 5 methods)
In [19]:
methods(foo)
Out[19]:
5 methods for generic function foo:
  • foo(x::Bool) in Main at In[18]:1
  • foo(x::Int64, y::Int64) in Main at In[7]:1
  • foo(x::String, y::String) in Main at In[4]:1
  • foo(x::Number, y::Number) in Main at In[14]:1
  • foo(x, y) in Main at In[16]:1

10.2

아래 코드를 실행할 때, 위에서 적용한 method가 전달되고 있는지 확인하라.

foo(true)
In [20]:
foo(true)
boolean 한 개로 실행됐다!
In [21]:
@which foo(true)
Out[21]:
foo(x::Bool) in Main at In[18]:1
In [22]:
@assert foo(true) == "boolean 한 개로 실행됐다!"
boolean 한 개로 실행됐다!
AssertionError: foo(true) == "boolean 한 개로 실행됐다!"

Stacktrace:
 [1] top-level scope at In[22]:1

'Flux in Julia > Learning Julia (Intro_to_Julia)' 카테고리의 다른 글

11. Basic linear algebra (한글)  (0) 2018.10.04
11. Basic linear algebra  (0) 2018.10.04
10. Multiple dispatch  (0) 2018.10.02
09. Julia is fast (한글)  (0) 2018.10.01
09 Julia is fast  (0) 2018.10.01
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/10   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함