수색…


통사론

  • 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 구문은 리소스 관리상의 이유로 파일 입출력에 특히 유용합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow