Документация Engee
Notebook

Типы данных

Система типов языка Julia является динамической, но в то же время она содержит некоторые преимущества систем статических типов, позволяя указывать, что определенные значения относятся к определенным типам.

Разделения на объектные и необъектные значения нет: все значения в Julia являются истинными объектами, имеющими тип, принадлежащий одному полностью связному графу типов, все узлы которого одинаково первоклассны как типы.

Ниже приведена сводная таблица сравнения типов данных Engee и MATLAB.

Тип (Engee/MATLAB) Количество бит Наименьшее значение Наибольшее значение
Int8 / int8 8 $$-2^7$$ $$2^7 - 1$$
UInt8 / uint8 8 $$0$$ $$2^8 - 1$$
Int16 / int16 16 $$-2^{15}$$ $$2^{1} - 1$$
UInt16 / uint16 16 $$0$$ $$2^{16} - 1$$
Int32 / int32 32 $$-2^{31}$$ $$2^{31} - 1$$
UInt32 / uint32 32 $$0$$ $$2^{32} - 1$$
Int64 / int64 64 $$-2^{63}$$ $$2^{63} - 1$$
UInt64 / uint64 64 $$0$$ $$2^{64} - 1$$
Int128 / нет 128 $$-2^{127}$$ $$2^{127}- 1$$
UInt128 / нет 128 $$0$$ $$2^{128} - 1$$
Bool / logical 8/1 false(0) true(1)
Bool / logical 8/1 false(0) true(1)
Float16 / нет 16 Половинная точность
Float32 / single 32/32 Одинарная точность
Float64 / double 64/64 Двойная точность
(Nifj или Qifj) / fi(i,x,n,m) (min 8, max 64) / (min 1, max 1024) Число с фиксированной запятой

Объявления типа

Оператор :: можно использовать для присоединения аннотаций типов к выражениям и переменным в программах. Есть две основные причины сделать это.

  1. В качестве установки, помогающей подтвердить, что ваша программа работает так, как вы ожидаете.
  2. Чтобы предоставить компилятору дополнительную информацию о типе, и в некоторых случаях это может повысить производительность.

При добавлении к выражению, вычисляющему значение, :: оператор читается как «является экземпляром».

In [ ]:
(1+2)::Int
Out[0]:
3

При добавлении к переменной в левой части присваивания :: объявляет, что переменная всегда имеет указанный тип, подобно объявлению типа в статически типизированном языке, таком, как C.

In [ ]:
function foo()
    x::Int8 = 100
end
Out[0]:
foo (generic function with 2 methods)
In [ ]:
x = foo()
Out[0]:
100
In [ ]:
typeof(x)
Out[0]:
Int64

Эта функция полезна для предотвращения проблем с производительностью, которые могут возникнуть, если одно из присвоений переменной неожиданно изменило ее тип.

Такое поведение «объявления» происходит только в определенных контекстах и применяется ко всей текущей области действия, даже до объявления.

In [ ]:
local x::Int8  # in a local declaration

Также объявления типов можно применить к глобальным переменным.

In [ ]:
a::Int = 10
Out[0]:
10
In [ ]:
typeof(a)
Out[0]:
Int64
In [ ]:
function foo(y)
        global a = 15   # throws an error when foo is called
        return a + y
end
Out[0]:
foo (generic function with 2 methods)
In [ ]:
foo(10)
Out[0]:
25

Объявления могут быть прикреплены и к определениям функций:

In [ ]:
function sinc(x)::Float64
    if x == 0
        return 1
    end
    return sin(pi*x)/(pi*x)
end

sinc(1.1)
Out[0]:
-0.08942105846213334

Абстрактные типы

Абстрактные типы не могут быть созданы и служат только узлами в графе типов, описывая тем самым наборы связанных конкретных типов, которые являются их потомками.

In [ ]:
abstract type Pointy{T} end
In [ ]:
Pointy{Int64} <: Pointy
Out[0]:
true
In [ ]:
Pointy{1} <: Pointy
Out[0]:
true
In [ ]:
Pointy{Float64} <: Pointy{Real}
Out[0]:
false

Типы кортежей

Кортежи — это абстракция аргументов функции без самой функции. Важнейшими аспектами аргументов функции являются их порядок и типы. Поэтому тип кортежа аналогичен параметризованному неизменяемому типу, где каждый параметр является типом одного поля. Например, тип кортежа из двух элементов похож на следующий неизменяемый тип:

In [ ]:
struct Tuple2{A,B}
    a::A
    b::B
end

Однако есть три ключевых отличия:

  1. Типы кортежей могут иметь любое количество параметров.
  2. Типы кортежей ковариантны по своим параметрам: Tuple{Int} является подтипом Tuple{Any}. Поэтому Tuple{Any} считается абстрактным типом, а типы кортежей являются конкретными только в том случае, если их параметры являются конкретными.
  3. Кортежи не имеют имен полей; доступ к полям осуществляется только по индексу.

Значения кортежа записываются в круглых скобках и запятых. При построении кортежа соответствующий тип кортежа генерируется по требованию:

In [ ]:
typeof((1,"foo",2.5))
Tuple{Int64, String, Float64}
Out[0]:
Tuple{Int64, String, Float64}
In [ ]:
Tuple{Int,AbstractString} <: Tuple{Real,Any}
Out[0]:
true
In [ ]:
Tuple{Int,AbstractString} <: Tuple{Real,Real}
Out[0]:
false

Типы кортежей Vararg

Последним параметром типа кортежа может быть специальное значение Vararg, обозначающее любое количество конечных элементов:

In [ ]:
mytupletype = Tuple{AbstractString,Vararg{Int}}
Tuple{AbstractString, Vararg{Int64}}
Out[0]:
Tuple{AbstractString, Vararg{Int64}}
In [ ]:
isa(("1",1,2), mytupletype)
Out[0]:
true
In [ ]:
isa(("1",1,2,3.0), mytupletype)
Out[0]:
false

Именованные кортежи

Именованные кортежи — это экземпляры типа NamedTuple, который имеет два параметра: кортеж символов, задающий имена полей, и тип кортежа, задающий типы полей. Для удобства NamedTuple типы выводятся с помощью @NamedTuple макроса.

In [ ]:
typeof((a=1,b="hello")) # prints in macro form
@NamedTuple{a::Int64, b::String}
Out[0]:
NamedTuple{(:a, :b), Tuple{Int64, String}}

Параметрические примитивные типы

Примитивные типы тоже можно объявлять параметрически. Например, указатели представлены как примитивные типы, которые будут объявлены в Julia следующим образом:

In [ ]:
# 64-bit system:
primitive type P{T} 64 end
In [ ]:
P{Int64} <: P
Out[0]:
true
In [ ]:
P{Float64} <: P
Out[0]:
true

Вывод

В данной демонстрации показаны основные типы данных, а также возможности их объявления и применения. Дополнительную информацию можно посмотреть в статьях про целые числа и числа с плавающей запятой, а также в статье про типы данных, на основе которых была реализована данная демонстрация.