06. Functions (한글)
Functions¶
출처¶
https://github.com/JuliaComputing/JuliaBoxTutorials/tree/master/introductory-tutorials/intro-to-julia (github : JuliaComputing/JuliaBoxTutorials/introductory-tutorials/intro-to-julia/)
Topics:
함께보기¶
- http://deepstat.tistory.com/45 (01. Getting started)(in English)
- http://deepstat.tistory.com/46 (01. Getting started(한글))
- http://deepstat.tistory.com/47 (02. Strings)(in English)
- http://deepstat.tistory.com/48 (02. Strings(한글))
- http://deepstat.tistory.com/49 (03. Data structures)(in English)
- http://deepstat.tistory.com/50 (03. Data structures(한글))
- http://deepstat.tistory.com/51 (04. Loops)(in English)
- http://deepstat.tistory.com/52 (04. Loops(한글))
- http://deepstat.tistory.com/53 (05. Conditionals)(in English)
- http://deepstat.tistory.com/54 (05. Conditionals(한글))
- http://deepstat.tistory.com/55 (06. Functions)(in English)
줄리아에는 함수를 선언하는 몇 가지 방법이 있다.
첫번째는 function, end 문을 이용하는 방법이다.
function 안녕(이름)
println("안녕 $이름, 만나서 반가워!")
end
function f(ㅁ)
ㅁ^2
end
이 함수를 사용할 때는 아래와 같이 한다.
안녕("C-3PO")
f(42)
이 함수들을 한 줄로 쓰는 방법도 있다.
안녕2(이름) = println("안녕 $이름, 만나서 반가워!")
f2(ㅁ) = ㅁ^2
안녕2("R2D2")
f2(42)
마지막으로 "anonymous" 함수로 쓰는 방법이 있다.
안녕3 = 이름 -> println("안녕 $이름, 만나서 반가워!")
f3 = ㅁ -> ㅁ^2
안녕3("츄바카")
f3(42)
"오리처럼 꽥꽥대면, 오리다."
줄리아 함수는 input으로 동작할법한 형태로 넣어주기만 하면 작동한다.
예를 들어서 안녕 함수에 input으로 character 대신에 integer 타입을 넣는다면,
안녕(55595472)
함수 f도 input으로 matrix를 넣을 수 있다.
A = rand(3, 3)
f(A)
f 는 string 을 input으로 넣어도 작동한다. 이유는 * operator가 문자를 합치는 역할을 하기 때문이다. 예를 들어, "안녕"을 넣으면,
f("안녕")
반면에, f는 벡터에는 오류나는데, 정방행렬과는 다르게 벡터의 제곱은 정의되지 않았기 때문이다.
v = rand(3)
f(v)
규칙에 의해서, (무조건 적용되는 문법은 아님) 함수에 ! 가 붙으면 input object를 변경하고, ! 가 안 붙으면 input object를 변경하지 않는다.
아래에서 sort 와 sort! 의 차이를 보자.
v = [3, 5, 2]
sort(v)
v
sort(v) 는 v 를 정렬했지만, v 자체를 바꾸지는 않는다.
반면, sort!(v) 를 실행하면 v 또한 바뀐다.
sort!(v)
v
수 = 4
println(f(수))
수
수 = 4
println(f!(수))
수
Higher-order-function 이란, 아래 두 가지 중 하나 이상을 만족하는 함수다.
- 함수를 파라미터로 전달받는 함수
- 함수를 리턴하는 함수
map¶
map 은 input 중 하나를 함수로 받는 "higher-order" 함수다. map 은 함수를 받아서 data structure에 있는 모든 element에 적용시킨다. 예를 들어서,
map(f, [1, 2, 3])
는 모든 elements [1, 2, 3]에 함수 f 를 적용시킨 array를 출력한다.
[f(1), f(2), f(3)]
map(f, [1, 2, 3])
vector [1, 2, 3]을 제곱한게 아니고, [1, 2, 3] elements 들을 제곱한 결과가 나온다.
아래는 named 함수 대신에 anonymous 함수를 써서 하는 코드다.
ㅁ -> ㅁ^3
via
map(ㅁ -> ㅁ^3, [1, 2, 3])
[1, 2, 3] 의 모든 element를 세제곱했다!
broadcast¶
broadcast는 다른 higher-order 함수다. broadcast는 map의 일반화된 함수라서 map이 할 수 있는 것은 다 할 수 있고, 거기에 더해서 다른 것도 더 할 수 있다. broadcast를 사용하는 구문은 map을 사용하는 것과 같다.
broadcast(f, [1, 2, 3])
broadcasting을 이용해서 [1, 2, 3]의 모든 원소에 함수 f를 적용했다.
broadcasting을 사용하는 다른 방법은, 함수명 옆에 . 을 찍고 input 을 적는 것이다. 예를 들어,
broadcast(f, [1, 2, 3])
는 아래와 같다.
f.([1, 2, 3])
f.([1, 2, 3])
이게
f([1, 2, 3])
랑 어떻게 다른지 다시 한 번 설명하자면, 우리는 vector를 제곱할 수는 없지만, vector의 element들을 제곱할 수는 있다.
f(A) 와 f.(A) 의 연산이 어떻게 다른지 보기 위해서 아래와 같은 matrix A를 뒀다.
A = [i + 3*j for j in 0:2, i in 1:3]
f(A)
f(A) = A^2 = A * A
이다. 반면에,
B = f.(A)
는 A의 element들을 제곱했다.
broadcasting을 위한 점 구문은 비교적 복잡한 elementwise 구문을 더 수학적 표현방법에 더 가깝거나 자연스러워 보이도록 한다. 예를 들어,
broadcast(ㅁ -> ㅁ + 2 * f(ㅁ) / ㅁ, A)
대신에
A .+ 2 .* f.(A) ./ A
를 쓸 수 있다. 그리고 두 개가 정확하게 같은 결과를 낸다.
6.1¶
input 값에 1을 더하는 함수로 더하기_일이라는 함수를 만들어보자.
function 더하기_일1(수)
수+1
end
더하기_일1(1)
더하기_일2(수) = 수+1
더하기_일2(1)
더하기_일3 = 수 -> 수+1
더하기_일3(1)
6.2¶
map 또는 broadcast 함수를 사용하여 행렬 A의 모든 요소를 1 씩 증가시키고 변수 A1에 할당해보자.
A1 = map(더하기_일1, A)
A1 = broadcast(더하기_일2, A)
6.3¶
broadcast dot 구문을 사용하여 행렬 A1의 모든 요소를 1 씩 증가시키고 변수 A2에 저장해보자.
A2 = 더하기_일3.(A1)
A2 = A1 .+ 1