Julia Language
유형
수색…
통사론
- 변경 불가능한 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
이것은 다형성을 촉진합니다. 예를 들어 Nil
과 Cons
라는 두 가지 불변 유형을 정의하여 링크 된 목록 을 쉽게 만들 수 있습니다. 이 이름은 각각 비어있는 목록과 비어 있지 않은 목록을 설명하는 데 전통적으로 사용됩니다.
abstract LinkedList
immutable Nil <: LinkedList end
immutable Cons <: LinkedList
first
rest::LinkedList
end
우리는 빈리스트를 Nil()
과 Cons(first, rest)
의한 다른리스트로 표현할 것인데, first
는 링크 된리스트의 첫 번째 요소이고 rest
는 rest
모든 요소들로 구성된 링크 된리스트이다. 예를 들어, [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.IsInfinite
및Base.SizeUnknown
은 모두 싱글 톤 유형입니다.
- 버전 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)