Зачем создавать абстрактный супер тип в Юлии? - PullRequest
3 голосов
/ 14 февраля 2020

Я смотрю на чей-то код, и он использует <: при создании структуры. Я посмотрел в документах и обнаружил, что это означает, что они создают абстрактный супертип. Может кто-нибудь объяснить, что это такое и почему кто-то хотел бы использовать это?

Ответы [ 3 ]

3 голосов
/ 14 февраля 2020

Что такое абстрактные типы?

Абстрактные типы - это узлы в иерархии типов: они группируют типы вместе. Это позволяет вам писать методы, которые применяются ко всей группе типов:

julia> abstract type AbstractFoo end

julia> struct Foo1 <: AbstractFoo end

julia> struct Foo2 <: AbstractFoo end

julia> foo_op(x::AbstractFoo) = "yay!"
foo_op (generic function with 1 method)

julia> foo_op(Foo1())
"yay!"

julia> foo_op(Foo2())
"yay!"

Почему полезны абстрактные типы?

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

Типичным примером является AbstractArray abstract тип. Он представляет возможность доступа к отдельным элементам некоторой многомерной коллекции элементов. Учитывая некоторую проблему, мы обычно можем выбрать подтип абстрактных массивов, которые будут давать эффективные операции: дополнительные ограничения на подтип составляют информацию, которую программист может использовать для повышения эффективности определенных операций .

Например, скажем, мы хотим найти сумму 1..N. Мы могли бы использовать массив целых чисел, но это было бы очень неэффективно по сравнению с UnitRange. Выбор UnitRange кодирует информацию о характеристиках данных; информация, которую мы можем использовать для эффективности. (См. этот ответ для получения дополнительной информации об этом примере.)

julia> using BenchmarkTools

julia> @btime sum($(1:1000_000))
  0.012 ns (0 allocations: 0 bytes)
500000500000

julia> @btime sum($(collect(1:1000_000)))
  229.979 μs (0 allocations: 0 bytes)
500000500000

BitArray обеспечивает эффективное для пространства представление для массива логических значений, SparseArrays обеспечивает эффективные операции для разреженных данных, и так далее. Если у вас есть данные, которые обычно ведут себя как абстрактный массив, но имеют уникальные характеристики, вы можете определить свой собственный подтип.

Этот шаблон обобщает другие абстрактные типы. Используйте их для группировки различных реализаций некоторого общего поведения.

2 голосов
/ 14 февраля 2020

Гораздо более практичным вариантом использования является создание строго типизированных, потенциально взаимно рекурсивных структур. Например, вы не могли бы написать следующее:

struct Node
    edges::Vector{Edge}
end

struct Edge
    from::Node
    to::Node
end

Один из способов написать это довольно искусственный

abstract type AbstractNode end
abstract type AbstractEdge end

struct Node{E<:AbstractEdge}
    edges::Vector{E}
end

struct Edge{N<:AbstractNode}
    from::N
    to::N
end

Часто, при достаточном опыте, эта проблема естественным образом решается уже во время дизайн структуры данных, как показано ниже:

abstract type Program end
abstract type Expression <: Program end
abstract type Statement <: Program

struct Literal <: Expression
    value::Int
end

struct Var <: Expression
    name::Symbol
end

struct Plus <: Expression
    x::Expression
    y::Expression
end

struct Assign <: Statement
    var::Var
    expr::Expression
end

struct Block <: Expression
    side_effects::Vector{<:Program}
    result::Expression
end

Это гарантирует, что Expression s (вещи, которые оцениваются в числах) и Statement s (вещи, которые являются только побочными эффектами) правильно разделены - вы никогда не сможете создавать недопустимые программы, такие как 1 + (x = 2). И это не могло быть написано без абстрактных типов (или взаимно рекурсивных типов, но в настоящее время они не существуют ).

1 голос
/ 14 февраля 2020

Из документации по https://docs.julialang.org/en/v1/manual/types/:

"Одна особенно отличительная особенность системы типов Джулии состоит в том, что конкретные типы не могут заменять друг друга: все конкретные типы являются окончательными и могут только имеют абстрактные типы в качестве своих супертипов. Хотя на первый взгляд это может показаться чрезмерно ограничительным, оно имеет много полезных последствий с удивительно небольшим количеством недостатков. Оказывается, что способность наследовать поведение гораздо важнее, чем способность наследовать структуру и наследовать обе причины значительные трудности в традиционных объектно-ориентированных языках ...

Итак, то, что вы увидели, когда увидели "<: при создании структуры", было примером подкласса структуры из абстрактного типа, обычно для того, чтобы использовать другие функции (методы) этого типа с новой структурой. То есть код не создавал абстрактный супертип. <: означал, что они создавали конкретный тип, но выводили его (с помощью <:) из ранее заявленного абстрактный тип (что ш мог бы быть справа от <: в этом случае). </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...