Julia Language
기능들
수색…
통사론
- f (n) = ...
- 함수 f (n) ... 끝
- n :: 유형
- x -> ...
- f (n) do ... end
비고
가장 일반적인 일반 기능 외에도 내장 기능이 있습니다. 이러한 함수에는 is
, isa
, typeof
, throw
및 유사한 함수가 포함됩니다. 내장 함수는 일반적으로 Julia 대신 C로 구현되므로 디스패치를위한 인수 유형을 전문으로 지정할 수 없습니다.
숫자 스퀘어
이것은 함수를 정의하는 가장 쉬운 구문입니다 :
square(n) = n * n
함수를 호출하려면 대괄호 (사이에 공백없이)를 사용하십시오.
julia> square(10)
100
함수는 Julia의 객체이며 다른 객체와 마찬가지로 REPL에 표시 할 수 있습니다.
julia> square
square (generic function with 1 method)
모든 줄리아 함수는 기본적으로 일반 ( 다형성 이라고도 함)입니다. 우리의 square
함수는 부동 소수점 값과 마찬가지로 작동합니다.
julia> square(2.5)
6.25
... 또는 심지어 매트릭스 :
julia> square([2 4
2 1])
2×2 Array{Int64,2}:
12 12
6 9
재귀 함수
단순 재귀
재귀와 삼항 조건 연산자 를 사용하여 내장 factorial
함수의 대체 구현을 만들 수 있습니다.
myfactorial(n) = n == 0 ? 1 : n * myfactorial(n - 1)
용법:
julia> myfactorial(10)
3628800
나무 작업
재귀 함수는 종종 데이터 구조, 특히 트리 데이터 구조에서 가장 유용합니다. 줄리아의 표현 은 나무 구조이기 때문에, 재귀는 메타 프로그래밍에 매우 유용 할 수 있습니다. 예를 들어, 아래 함수는 표현식에 사용 된 모든 머리 집합을 수집합니다.
heads(ex::Expr) = reduce(∪, Set((ex.head,)), (heads(a) for a in ex.args))
heads(::Any) = Set{Symbol}()
우리는 우리의 기능이 의도 한대로 작동하는지 점검 할 수 있습니다.
julia> heads(:(7 + 4x > 1 > A[0]))
Set(Symbol[:comparison,:ref,:call])
이 기능은 소형이며 고차원 기능 reduce
, 데이터 유형 Set
및 생성기 표현과 같은 다양한 고급 기술을 사용합니다.
파견 소개
::
구문을 사용하여 인수 유형 을 전달할 수 있습니다.
describe(n::Integer) = "integer $n"
describe(n::AbstractFloat) = "floating point $n"
용법:
julia> describe(10)
"integer 10"
julia> describe(1.0)
"floating point 1.0"
일반적으로 정적 다중 디스패치 또는 동적 단일 디스패치를 제공하는 많은 언어와 달리 Julia는 완전한 동적 다중 디스패치 기능을 제공합니다. 즉, 함수는 둘 이상의 인수에 대해 특수화 될 수 있습니다. 이것은 특정 유형의 조작을위한 특수 메소드를 정의 할 때 유용하며 다른 유형의 대체 메소드를 정의 할 때 유용합니다.
describe(n::Integer, m::Integer) = "integers n=$n and m=$m"
describe(n, m::Integer) = "only m=$m is an integer"
describe(n::Integer, m) = "only n=$n is an integer"
용법:
julia> describe(10, 'x')
"only n=10 is an integer"
julia> describe('x', 10)
"only m=10 is an integer"
julia> describe(10, 10)
"integers n=10 and m=10"
선택적 인수
Julia는 함수가 선택적 인수를 취하도록 허용합니다. 뒤에서 다중 디스패치의 또 다른 특수한 경우로 구현됩니다. 예를 들어 인기있는 Fizz 버즈 문제를 해결해 보겠습니다. 기본적으로 우리는 1:10
범위의 숫자에 대해이를 수행하지만 필요한 경우 다른 값을 허용합니다. 또한 Fizz
또는 Buzz
다른 구를 사용할 수 있습니다.
function fizzbuzz(xs=1:10, fizz="Fizz", buzz="Buzz")
for i in xs
if i % 15 == 0
println(fizz, buzz)
elseif i % 3 == 0
println(fizz)
elseif i % 5 == 0
println(buzz)
else
println(i)
end
end
end
REPL에서 fizzbuzz
를 검사하면 네 가지 방법이 있다고합니다. 허용되는 인수 조합마다 하나의 메소드가 작성되었습니다.
julia> fizzbuzz
fizzbuzz (generic function with 4 methods)
julia> methods(fizzbuzz)
# 4 methods for generic function "fizzbuzz":
fizzbuzz() at REPL[96]:2
fizzbuzz(xs) at REPL[96]:2
fizzbuzz(xs, fizz) at REPL[96]:2
fizzbuzz(xs, fizz, buzz) at REPL[96]:2
매개 변수가 제공되지 않을 때 기본값이 사용되는지 확인할 수 있습니다.
julia> fizzbuzz()
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
옵션 매개 변수는 우리가 제공 할 경우 받아 들여지고 존중됩니다 :
julia> fizzbuzz(5:8, "fuzz", "bizz")
bizz
fuzz
7
8
파라 메 트릭 디스패치
Vector{T}
또는 Dict{K,V}
와 같은 매개 변수 유형에 함수를 전달해야하는 경우가 종종 있지만 유형 매개 변수는 고정되어 있지 않습니다. 이 경우는 파라 메트릭 디스패치를 사용하여 처리 할 수 있습니다.
julia> foo{T<:Number}(xs::Vector{T}) = @show xs .+ 1
foo (generic function with 1 method)
julia> foo(xs::Vector) = @show xs
foo (generic function with 2 methods)
julia> foo([1, 2, 3])
xs .+ 1 = [2,3,4]
3-element Array{Int64,1}:
2
3
4
julia> foo([1.0, 2.0, 3.0])
xs .+ 1 = [2.0,3.0,4.0]
3-element Array{Float64,1}:
2.0
3.0
4.0
julia> foo(["x", "y", "z"])
xs = String["x","y","z"]
3-element Array{String,1}:
"x"
"y"
"z"
xs::Vector{Number}
를 쓰기 만하면됩니다. 그러나이 형식은 명시 적으로 Vector{Number}
인 개체에만 적용됩니다.
julia> isa(Number[1, 2], Vector{Number})
true
julia> isa(Int[1, 2], Vector{Number})
false
이 때문입니다 파라 메트릭 불변 : 오브젝트의 Int[1, 2]
아닌 Vector{Number}
에만 포함 할 수 있으므로, Int
반면들 Vector{Number}
숫자의 종류를 포함 할 수있을 것으로 예상된다.
일반 코드 작성
Dispatch는 매우 강력한 기능이지만 각 유형별 코드를 전문화하는 대신 모든 유형에 대해 작동하는 일반 코드를 작성하는 것이 더 나은 경우가 종종 있습니다. 일반 코드 작성은 코드 중복을 방지합니다.
예를 들어, 다음은 정수 벡터의 제곱의 합을 계산하는 코드입니다.
function sumsq(v::Vector{Int})
s = 0
for x in v
s += x ^ 2
end
s
end
그러나이 코드는 Int
의 벡터 에서만 작동합니다. UnitRange
에서는 작동하지 않습니다.
julia> sumsq(1:10)
ERROR: MethodError: no method matching sumsq(::UnitRange{Int64})
Closest candidates are:
sumsq(::Array{Int64,1}) at REPL[8]:2
Vector{Float64}
에서는 작동하지 않습니다.
julia> sumsq([1.0, 2.0])
ERROR: MethodError: no method matching sumsq(::Array{Float64,1})
Closest candidates are:
sumsq(::Array{Int64,1}) at REPL[8]:2
이 sumsq
함수를 작성하는 더 좋은 방법은 다음과 sumsq
합니다.
function sumsq(v::AbstractVector)
s = zero(eltype(v))
for x in v
s += x ^ 2
end
s
end
위의 두 가지 경우에 적용됩니다. 그러나 어떤 의미에서 벡터가 아닌 제곱을 합산하고자하는 컬렉션이 있습니다. 예를 들어,
julia> sumsq(take(countfrom(1), 100))
ERROR: MethodError: no method matching sumsq(::Base.Take{Base.Count{Int64}})
Closest candidates are:
sumsq(::Array{Int64,1}) at REPL[8]:2
sumsq(::AbstractArray{T,1}) at REPL[11]:2
우리는 게으른 반복 가능한 사각형을 합칠 수 없다는 것을 보여줍니다.
더욱 일반적인 구현은 간단합니다.
function sumsq(v)
s = zero(eltype(v))
for x in v
s += x ^ 2
end
s
end
어떤 경우에도 작동합니다.
julia> sumsq(take(countfrom(1), 100))
338350
이것은 가장 관용적 인 줄리아 코드이며 모든 상황을 처리 할 수 있습니다. 다른 언어에서는 형식 주석을 제거하면 성능에 영향을 줄 수 있지만 Julia에서는 그렇지 않습니다. 형식 안정성 만 성능을 위해 중요합니다.
명령형 계승
다중 행 함수를 정의 할 때 긴 형식의 구.을 사용할 수 있습니다. 이것은 루프와 같은 명령형 구조를 사용할 때 유용 할 수 있습니다. 꼬리 위치의 표현식이 반환됩니다. 예를 들어, 아래 함수는 for
루프 를 사용하여 정수 n
의 팩토리얼 을 계산합니다.
function myfactorial(n)
fact = one(n)
for m in 1:n
fact *= m
end
fact
end
용법:
julia> myfactorial(10)
3628800
더 긴 함수에서는 사용 된 return
문을 보는 것이 일반적입니다. return
문은 꼬리 위치에 필요하지 않지만 때때로 명확성을 위해 사용되기도합니다. 예를 들어 위의 함수를 작성하는 다른 방법은
function myfactorial(n)
fact = one(n)
for m in 1:n
fact *= m
end
return fact
end
이는 위의 기능과 동일한 동작입니다.
익명 함수
화살표 구문
익명 함수는 ->
구문을 사용하여 만들 수 있습니다. 이것은 map
함수와 같은 고차 함수에 함수를 전달할 때 유용합니다. 아래 함수는 배열 A
의 각 숫자의 제곱을 계산합니다.
squareall(A) = map(x -> x ^ 2, A)
이 함수를 사용하는 예는 다음과 같습니다.
julia> squareall(1:10)
10-element Array{Int64,1}:
1
4
9
16
25
36
49
64
81
100
다중 행 구문
function
구문을 사용하여 여러 익명의 함수를 만들 수 있습니다. 예를 들어 다음 예제에서는 첫 번째 n
계승 을 계산하지만 기본 factorial
대신 익명의 함수를 사용합니다.
julia> map(function (n)
product = one(n)
for i in 1:n
product *= i
end
product
end, 1:10)
10-element Array{Int64,1}:
1
2
6
24
120
720
5040
40320
362880
3628800
블록 구문 수행
익명 함수를 함수의 첫 번째 인수로 전달하는 것이 일반적이므로 do
블록 구문이 있습니다. 문법
map(A) do x
x ^ 2
end
~에 해당합니다.
map(x -> x ^ 2, A)
전자는 많은 상황에서 더 명확해질 수 있습니다. 특히 익명의 함수에서 많은 계산이 수행되는 경우 특히 그렇습니다. do
구문은 리소스 관리상의 이유로 파일 입출력에 특히 유용합니다.