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

Типы данных

Открыть пример в Engee

Система типов языка 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^15 - 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

Вывод

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