logo

줄리아의 스플랫 오퍼레이터 📂줄리아

줄리아의 스플랫 오퍼레이터

개요

줄리아에서 ...는 스플랫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