Сообщество Engee

Составной тип данных

Автор
avatar-maximsidorovmaximsidorov
Notebook

Составной тип данных в Julia

В этом примере рассматривается реализация составного типа данных (compound data type) в языке программирования Julia для представления точки на плоскости.

Введение

Составной тип данных (или структура) в программировании используется для создания пользовательских типов данных, которые могут содержать несколько связанных значений. Это основной способ создания сложных структур данных из простых компонентов. В данном случае мы создаем структуру Point для представления точки на двумерной плоскости с координатами x и y.

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

  • Группировать связанные данные (координаты x и y);

  • Обеспечивать строгую типизацию для координат;

  • Создавать безопасные и читаемые структуры данных;

  • Поддерживать обобщенное программирование через параметрический полиморфизм.

Основная часть

Определение параметрической структуры Point

Определяем параметрическую структуру Point с типовым параметром T

T <: Real означает, что T должен быть подтипом Real (Int, Float64, Rational и т.д.)

struct Point{T<:Real}
    # Поля структуры: x и y координаты типа T
    x::T
    y::T
end

Создание экземпляров структуры Point

Создадим точки с разными числовыми типами:

  1. Точка с целочисленными координатами
point1 = Point(3, 4);
println("Тип point1: ", typeof(point1))  # Point{Int64}
Тип point1: Point{Int64}
  1. Точка с вещественными координатами
point2 = Point(3.14, 2.71);
println("Тип point2: ", typeof(point2))  # Point{Float64}
Тип point2: Point{Float64}
  1. Точка с рациональными координатами
point3 = Point(1//2, 3//4);
println("Тип point3: ", typeof(point3))  # Point{Rational{Int64}}
Тип point3: Point{Rational{Int64}}

Доступ к полям структуры

Получаем доступ к координатам точек

println("Координаты point1: x = $(rpad(point1.x,4)), y = $(point1.y)")
println("Координаты point2: x = $(point2.x), y = $(point2.y)")
Координаты point1: x = 3   , y = 4
Координаты point2: x = 3.14, y = 2.71

Пытаемся изменить значения (это приведет к ошибке, так как struct иммутабельна)

try
    point1.x = 5  # ERROR: setfield!: immutable struct of type Point cannot be changed
catch err
    err
end
ErrorException("setfield!: immutable struct of type Point cannot be changed")

Создание изменяемой версии структуры

Если нужна изменяемая структура, используем ключевое слово mutable

mutable struct MutablePoint{T<:Real}
    x::T
    y::T
end
# Создаем изменяемую точку
mutable_point = MutablePoint(1.0, 2.0)
println("Исходные координаты: x = $(mutable_point.x), y = $(mutable_point.y)")

# Теперь можно изменять значения
mutable_point.x = 5.0
mutable_point.y = 10.0
println("Новые координаты:    x = $(mutable_point.x), y = $(mutable_point.y)")
Исходные координаты: x = 1.0, y = 2.0
Новые координаты:    x = 5.0, y = 10.0

Добавление методов для работы со структурой

Определяем функцию для вычисления расстояния от точки до начала координат

function distance_from_origin(p::Point{T}) where T<:Real
    return sqrt(p.x^2 + p.y^2)
end
distance_from_origin (generic function with 1 method)

Определяем функцию для вычисления расстояния между двумя точками

function distance(p1::Point{T}, p2::Point{T}) where T<:Real
    return sqrt((p1.x - p2.x)^2 + (p1.y - p2.y)^2)
end
distance (generic function with 1 method)

Создаем точки для тестирования

point_a = Point(0, 0);
point_b = Point(3, 4);

Вычисляем расстояния

println("Расстояние от точки b до начала координат: ", distance_from_origin(point_b))
println("Расстояние между точками a и b: ", distance(point_a, point_b))
Расстояние от точки b до начала координат: 5.0
Расстояние между точками a и b: 5.0

Заключение

В этом примере мы рассмотрели реализацию составного типа данных Point в языке Julia.

Мы создали параметрическую структуру, которая может работать с различными числовыми типами (целыми, вещественными, рациональными и другими подтипами Real). Нам удалось создать безопасный и гибкий тип данных для представления точек на плоскости, обеспечив строгую типизацию и возможность обобщенного программирования. Такой подход важен для создания надежного кода, который может работать с различными числовыми типами без потери производительности и при этом обеспечивает проверку типов на этапе компиляции.

Пример разработан с использованием материалов Rosetta Code