Контейнерные типы и система типов

Подробнее тема раскрыта в главе Типы. Эта глава дает возможность начать работать, отложив теорию на потом.

Функции и Array

Система типов в Julia работает строже с элементами контейнерных типов в качестве параметров функций, чем с элементами простых типов. (У типа Tuple эти правила отличаются). Это свойство всех языков, где типовые параметры функций инвариантны. Это значит, например, тип "массив Int" не является подтипом "массива Any":

julia> typeof([1,2,3])<:Array{Any}
false

хотя Int - подтип Any:

typeof(2)<:Any
true

из этого следует, что если вы определите функцию, ожидающую Array{Any}, и думаете, что разрешаете любые массивы для нее, то вы ошибаетесь:

julia> f(a::Array{Any}) = a[1] # кажется, что Array{Any} -это "любой" массив

julia> f([1,2])
ERROR: MethodError: no method matching f(::Array{Int64,1})
Closest candidates are:
  f(::Array{Any,N}) at REPL[33]:1

Julia сообщает, что самое похожее, что она нашла на тему функции f, принимающей массив, так это - f(::Array{Any,N} , а не f(::Array{Int64,1}).

В данном случае можно определить тип так:

julia> f(a::Array) = a[1]
julia> f([2,3]) # проверим
2 # работает

Функции и Dict

Как и в случае с массивами и другими контернейными типами данных, функция, ожидающая Dict{Symbol,AbstractString} не примет Dict{Symbol,String}:

f(d::Dict{Symbol,AbstractString}) = d
d1 = Dict{Symbol,String}()
julia> f(d1)
ERROR: MethodError: `f` has no method matching f(::Dict{Symbol,String})

Конструкторы контейнерных типов

Сами контейнерные типы (и их конструкторы) ведут себя мягче.

Dict{Any,Any} позволит хранить непостоянные типы значений:

d["asdf"]=12
d
Dict{Any,Any} with 2 entries:
  :a     => "asd"
  "asdf" => 12

Задать типы значений пустого словаря можно, например, параметризовав его конструктор типами:

d1 = Dict{Symbol,AbstractString}()

При создании словаря через конструктор с начальными значениями, произойдет автоматический вывод типов. Можно инициализировать словарь, например, парой ключ=>значение:

d1 = Dict(:a=>"abc") 
julia> Dict{Symbol,String} with 1 entry:
  :a => "abc"

В отличие от Dict{Any,Any} этот словарь не даст записать в него другие типы ключей или значений, так: d1[123]="asd" выдаст ошибку.

Однако словарь Dict{Symbol,AbstractString} позволит записать значение конкретного типа String:

d1 = Dict{Symbol,AbstractString}()
Dict{Symbol,AbstractString} with 0 entries

julia> d1[:a]=String("asd")
"asd"

julia> d1
Dict{Symbol,AbstractString} with 1 entry:
  :a => "asd"

Это был беглый обзор часто встречающихся подводных камней для нетерпеливых.

results matching ""

    No results matching ""