줄리아의 스플랫 오퍼레이터
개요
줄리아에서 ...
는 스플랫splat 오퍼레이터로 불리며 함수를 사용할 때나 배열을 정의할 때 유용하게 쓰인다1. 이런 오퍼레이터가 줄리아에만 있는 건 아니지만, 다른 언어들에 비해 직관적으로 정의되어 있어 배우고 익히는 게 독보적으로 쉽다. 개인적인 경험으로는 ...
를 사용하게 되면 줄리아 프로그래밍에 대한 어떤 깨달음을 얻게 되는 것 같다.
코드
함수 인풋
기본적으로 ...
는 배열이나 제너레이터 뒤에 붙여서 사용하며, 생긴 그대로 앞에 붙은 컨테이너/이터레이터에 있는 원소를 쭉 풀어서 내놓는다.
julia> min([1,2,3,4,5,6,7,8,9,10])
ERROR: MethodError: no method matching min(::Vector{Int64})
julia> min(1,2,3,4,5,6,7,8,9,10)
1
예를 들어 줄리아의 min()
함수는 리듀스라서 위와 같이 배열 자체를 주면 안되고 여러개의 수를 직접 인자로 전달해야한다. 당연하지만 배열이 커질수록 이걸 직접 손으로 풀어 적기 곤란해지고, 배열의 원소를 풀어헤쳐서 넣을 수 있도록 ...
를 사용할 수 있다.
julia> min(1:10)
ERROR: MethodError: no method matching min(::UnitRange{Int64})
julia> min((1:10)...)
1
물론 실제로는 배열에 대해 사용할 수 있는 minimum()
함수가 있어서 굳이 이렇게 쓸 필요는 없다.
배열 정의
julia> [(1:10)]
1-element Vector{UnitRange{Int64}}:
1:10
위에서 정의된 배열은 유닛레인지의 배열이므로, 직접 원소에 접근하려면 조금 번거로워진다. 시간이 많다면야 그냥 숫자를 1부터 10까지 적어넣어도 되겠지만 스플랫 오퍼레이터를 사용하면 그냥 다음과 같이 쉽게 정의할 수 있다.
julia> [(1:10)...]
10-element Vector{Int64}:
1
2
3
4
5
6
7
8
9
10
물론 이 또한 collect()
함수 같은 대안이 있지만, 알고보면 깔끔하고 센스있는 표현이라는 점이 매력적이다. 다만 속도 측면에서는 그다지 권장되지 않는다고 하니 굳이 ...
를 남발하지 말도록 하자.
julia> [eachrow(rand(3,3))...]
3-element Vector{SubArray{Float64, 1, Matrix{Float64}, Tuple{Int64, Base.Slice{Base.OneTo{Int64}}}, true}}:
[0.6695368164913422, 0.69695509795356, 0.12084083239135612]
[0.6833475867141307, 0.5368141950494666, 0.7877252857572066]
[0.2810163716135018, 0.04317485597011517, 0.44214186775440534]
...
가 재미있어지는 건 위와 같이 제네레이터를 한번 거칠 때다. eachrow()
는 행렬을 행단위로 자른 벡터의 제너레이터를 리턴하는데, 스플랫 오퍼레이터를 통해 그 각각의 벡터를 배열 표기 []
에 집어넣어서 벡터의 벡터를 만든 것이다.
전체코드
min([1,2,3,4,5,6,7,8,9,10])
min(1,2,3,4,5,6,7,8,9,10)
min(1:10)
min((1:10)...)
[(1:10)]
[(1:10)...]
[eachrow(rand(3,3))...]
환경
- OS: Windows
- julia: v1.8.3