수색…


통사론

  • 변경 불가능한 MyType; 들; 들; 종료
  • MyType을 입력하십시오. 들; 들; 종료

비고

유형이 Julia의 성능에 중요합니다. 성능에 대한 중요한 아이디어는 형식 안정성 입니다. 형식 안정성 은 형식의 함수가 반환하는 경우에만 해당 인수의 값이 아니라 형식에 따라 달라집니다.

유형에 대한 파견

Julia에서 각 기능에 대해 하나 이상의 방법을 정의 할 수 있습니다. 같은 함수의 세 가지 메소드를 정의한다고 가정 해 보겠습니다.

foo(x) = 1
foo(x::Number) = 2
foo(x::Int) = 3

사용할 메소드 ( 발송 이라고 함)를 결정할 때 Julia는 인수의 유형과 일치하는보다 구체적인 메소드를 선택합니다.

julia> foo('one')
1

julia> foo(1.0)
2

julia> foo(1)
3

이것은 다형성을 촉진합니다. 예를 들어 NilCons 라는 두 가지 불변 유형을 정의하여 링크 된 목록 을 쉽게 만들 수 있습니다. 이 이름은 각각 비어있는 목록과 비어 있지 않은 목록을 설명하는 데 전통적으로 사용됩니다.

abstract LinkedList
immutable Nil <: LinkedList end
immutable Cons <: LinkedList
    first
    rest::LinkedList
end

우리는 빈리스트를 Nil()Cons(first, rest) 의한 다른리스트로 표현할 것인데, first 는 링크 된리스트의 첫 번째 요소이고 restrest 모든 요소들로 구성된 링크 된리스트이다. 예를 들어, [1, 2, 3] 목록은

julia> Cons(1, Cons(2, Cons(3, Nil())))
Cons(1,Cons(2,Cons(3,Nil())))

목록이 비어 있습니까?

다양한 컬렉션에서 작동하는 표준 라이브러리의 isempty 함수를 확장한다고 가정 해보십시오.

julia> methods(isempty)
# 29 methods for generic function "isempty":
isempty(v::SimpleVector) at essentials.jl:180
isempty(m::Base.MethodList) at reflection.jl:394
...

우리는 단순히 함수 디스패치 구문을 사용할 수 있으며 두 개의 추가 isempty 메서드를 정의 할 수 있습니다. 이 함수는 Base 모듈에서 Base.isempty 로 확장해야 확장 할 수 있습니다.

Base.isempty(::Nil) = true
Base.isempty(::Cons) = false

여기에서는 목록이 비어 있는지 여부를 결정하기 위해 인수 값이 필요하지 않습니다. 이 정보를 계산하는 데 유형만으로는 충분합니다. Julia는 우리가 값을 사용할 필요가 없다면 형식 주석 만 유지하면서 인수의 이름을 생략 할 수 있습니다.

우리는 isempty 방법이 작동 하는지 테스트 할 수 있습니다.

julia> using Base.Test

julia> @test isempty(Nil())
Test Passed
  Expression: isempty(Nil())

julia> @test !isempty(Cons(1, Cons(2, Cons(3, Nil()))))
Test Passed
  Expression: !(isempty(Cons(1,Cons(2,Cons(3,Nil())))))

참으로 isempty 대한 방법의 수가 2 증가했습니다.

julia> methods(isempty)
# 31 methods for generic function "isempty":
isempty(v::SimpleVector) at essentials.jl:180
isempty(m::Base.MethodList) at reflection.jl:394

분명히 연결된 목록이 비어 있는지 여부를 결정하는 것은 간단한 예입니다. 그러나 그것은 더 흥미로운 것에 이르게합니다 :

목록은 얼마 동안입니까?

표준 라이브러리의 length 함수는 콜렉션 또는 특정 iterables 의 길이를 제공합니다. 연결된 목록의 length 를 구현하는 방법은 여러 가지가 있습니다. 특히 while 루프를 사용하는 것이 Julia에서 가장 빠르고 메모리 효율이 높습니다. 그러나 조숙 한 최적화 는 피해야하기 때문에 링크 된 목록이 효율적 일 필요는 없다고 잠시 생각해 봅시다. length 함수를 작성하는 가장 간단한 방법은 무엇입니까?

Base.length(::Nil) = 0
Base.length(xs::Cons) = 1 + length(xs.rest)

첫 번째 정의는 간단합니다. 빈 목록의 길이는 0 입니다. 두 번째 정의는 읽기 쉽습니다. 목록의 길이를 계산하기 위해 첫 번째 요소를 계산 한 다음 나머지 목록의 길이를 계산합니다. 이 메소드를 우리가 isempty 를 테스트 한 것과 비슷하게 테스트 할 수있다.

julia> @test length(Nil()) == 0
Test Passed
  Expression: length(Nil()) == 0
   Evaluated: 0 == 0

julia> @test length(Cons(1, Cons(2, Cons(3, Nil())))) == 3
Test Passed
  Expression: length(Cons(1,Cons(2,Cons(3,Nil())))) == 3
   Evaluated: 3 == 3

다음 단계

이 장난감 예제는 링크 된 목록에서 원하는 모든 기능을 구현하는 것과는 거리가 멀다. 예를 들어 iteration 인터페이스가 빠져있다. 그러나 디스패치를 ​​사용하여 짧고 명확한 코드를 작성하는 방법을 보여줍니다.

변경할 수없는 유형

가장 간단한 복합 유형은 변경 불가능한 유형입니다. 튜플 과 같은 불변 유형의 인스턴스는 값입니다. 필드를 만든 후에는 해당 필드를 변경할 수 없습니다. 여러면에서 불변의 타입은 타입 자체와 각 필드의 이름을 가진 Tuple 과 같습니다.

싱글 톤 유형

정의에 따라 복합 유형에는 여러 가지 간단한 유형이 포함됩니다. Julia에서이 숫자는 0이 될 수 있습니다. 즉, 변경할 수없는 유형은 필드를 포함 할 수 없습니다 . 이것은 빈 튜플 () 과 유사합니다.

왜 이것이 유용할까요? 이러한 불변의 타입은 오직 하나의 인스턴스 만 존재할 수 있기 때문에 "싱글 톤 타입"으로 알려져있다. 이러한 유형의 값을 "단일 값"이라고합니다. 표준 라이브러리 Base 에는 이러한 싱글 톤 유형이 많이 포함되어 있습니다. 다음은 간단한 목록입니다.

  • Void , nothing 타입. 우리는 Void.instance (싱글 톤 유형의 싱글 톤 값을 검색하기위한 특수 구문)가 실제로 nothing Void.instance 확인할 수 있습니다.
  • MIME"text/plain" 과 같은 모든 미디어 유형은 단일 인스턴스 인 MIME("text/plain") 이있는 단일 유형입니다.
  • Irrational{:π} , Irrational{:e} , Irrational{:φ} 등의 유형은 싱글 톤 유형이며, 싱글 톤 인스턴스는 비합리적인 값인 π = 3.1415926535897... 등입니다.
  • 이터레이터 크기 특성 Base.HasLength , Base.HasShape , Base.IsInfiniteBase.SizeUnknown 은 모두 싱글 톤 유형입니다.
0.5.0
  • 버전 0.5 이상에서는 각 함수 가 싱글 톤 유형의 싱글 톤 인스턴스입니다! 다른 어떤 싱글 톤 값처럼, 우리는 typeof(sin).instance 로부터 함수 sin 복구 할 수있다.

그것들은 아무 것도 포함하고 있지 않기 때문에, 싱글 톤 타입은 믿을 수 없을만큼 가벼우 며 컴파일러가 런타임 오버 헤드를 갖지 않도록 자주 최적화 할 수 있습니다. 따라서 특성, 특수 태그 값 및 특수화하려는 기능과 같은 항목에 완벽합니다.

싱글 톤 유형을 정의하려면,

julia> immutable MySingleton end

싱글 톤 유형에 대한 사용자 정의 인쇄를 정의하려면,

julia> Base.show(io::IO, ::MySingleton) = print(io, "sing")

싱글 톤 인스턴스에 액세스하려면,

julia> MySingleton.instance
MySingleton()

종종 이것을 상수에 할당합니다.

julia> const sing = MySingleton.instance
MySingleton()

래퍼 유형

제로 필드 불변 타입이 흥미롭고 유용하다면 아마도 아마도 한 필드 불변 타입이 더 유용 할 것이다. 이러한 유형은 기본 데이터를 래핑하고 해당 데이터에 대한 대체 인터페이스를 제공하므로 일반적으로 "래퍼 유형"이라고합니다. Base 의 래퍼 유형의 예는 String 입니다. MyString 과 비슷한 String 타입을 정의 할 것입니다. 이 유형은 바이트 ( UInt8 )의 벡터 (1 차원 배열 )에 의해 백업됩니다.

첫째, 유형 정의 자체 및 사용자 정의 된 표시 :

immutable MyString <: AbstractString
    data::Vector{UInt8}
end

function Base.show(io::IO, s::MyString)
    print(io, "MyString: ")
    write(io, s.data)
    return
end

이제 MyString 형식을 사용할 준비가되었습니다! 일부 원시 UTF-8 데이터를 피드로 제공 할 수 있으며 다음과 같이 표시됩니다.

julia> MyString([0x48,0x65,0x6c,0x6c,0x6f,0x2c,0x20,0x57,0x6f,0x72,0x6c,0x64,0x21])
MyString: Hello, World!

분명히이 문자열 유형은 Base.String 유형만큼 사용하기 전에 많은 작업이 필요합니다.

실제 복합 유형

아마도 가장 일반적으로 많은 불변 유형은 하나 이상의 필드를 포함합니다. 표준 라이브러리 Rational{T} 유형은 분자의 num 필드와 분모의 den 필드라는 두 가지 fied를 포함합니다. 이 유형의 디자인을 에뮬레이션하는 것은 매우 간단합니다.

immutable MyRational{T}
    num::T
    den::T
    MyRational(n, d) = (g = gcd(n, d); new(n÷g, d÷g))
end
MyRational{T}(n::T, d::T) = MyRational{T}(n, d)

우리는 합리적인 수를 단순화하는 생성자를 성공적으로 구현했습니다.

julia> MyRational(10, 6)
MyRational{Int64}(5,3)


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