4

我正在尝试学习 julia,并从重写我的一个 C++ 程序开始。

我在寻找一种在 Julia 中表示以下概念的好方法时遇到了问题。

我有一些结构,它们都是某种集合。假设我有一个地址簿和一个相册。每个系列都有非常不同的元素。现在,在 C++ 中,如果我知道将 PhotoAlbum 传递给函数,那么创建 Photo 类型的变量非常容易。

我想不出朱莉娅的等效方式。理想情况下,编译器应该确切地知道集合由哪种类型组成,以便尽可能优化。

这就是我在 C++ 中的做法

class AddressBook
{
  public:
    typedef PersonalDetail Element;
}


class PhotoAlbum
{
  public:
    typedef Photo Element;
}


template<typename Collection>
void printFirstElement<Collection>(const Collection& c)
{
  const typename Collection::Element firstElement = //c.first();...
  // do something with firstElement
}
4

2 回答 2

3

如果我正确理解您的问题,我会说您不必考虑它,因为编译器会知道所需的类型。例如,在您上面的代码中,当您调用first(c)(这将相当于c.first())时,此变量的类型将在编译时已知(您可以通过@code_warntype在您的函数上运行来确认这一点)。

如果你能提供一个完整的小型工作示例,我可以给你一个工作代码。

一个更高级的主题是将一些元数据附加到您的类型。有几种方法可以做到。让我向您展示其中之一 - 通过参数抽象类型。

abstract type AbstractCollection{T} end
struct PersonalDetail end
struct AddressBook <: AbstractCollection{PersonalDetail} end
struct Photo end
struct PhotoAlbum <: AbstractCollection{Photo} end
getcollectiontype(::AbstractCollection{T}) where T = T

现在你可以写这样的东西来提取元数据

julia> ab = AddressBook()
AddressBook()

julia> pa = PhotoAlbum()
PhotoAlbum()

julia> getcollectiontype(ab)
PersonalDetail

julia> getcollectiontype(pa)
Photo

当然它是一个 MWE,我不确定你的代码中是否需要它(如果你展示一个小的完整工作代码,我们可以讨论最佳实施策略)。

也可能根本不需要这样的东西。例如,您有一个标准函数eltype,该函数应返回集合中的一种元素。对于此功能,您可以为您的特定类型添加方法以获取有关它们持有的元素类型的信息。然后您可以简单地eltype(collection)在您的代码中再次运行 - 在编译时 - 您将获得有关集合元素类型的信息。

另请注意,Julia 中的类型也是值,因此例如以下代码可以正常工作,并且编译器根据需要知道所有类型(该函数f尝试使用类型构造函数将其第二个参数转换为其第y一个参数x的类型):

julia> f(x,y) = typeof(x)(y)
f (generic function with 1 method)

julia> f(10, 2.0)
2

julia> f(10.0, 2)
2.0

julia> @code_warntype f(10.0, 2)
Body::Float64
1 ─ %1 = (Base.sitofp)(Float64, y)::Float64
└──      return %1

上面的定义等价于下面的定义f(x::T,y) = T(y)

于 2019-02-14T20:45:16.813 回答
-1

由于 Julia 中的变量可以保存类型,因此您可以这样做

struct PersonalDetail
end
struct Photo
end

struct AddressBook
    Element
    AddressBook(Element=PersonalDetail) = new(Element)
end

struct PhotoAlbum
    Element
    PhotoAlbum(Element=Photo) = new(Element)
end

PhotoAlbum()

话虽如此,您可以编写函数而不指定它们的类型

function printFirstElement(c)
    @show c[1]
end
printFirstElement([AddressBook()])
printFirstElement([PhotoAlbum()])
printFirstElement([rand([AddressBook() PhotoAlbum()])])
printFirstElement(1:5) # doesn't specify element type with `Element`, but we can still access its first element
于 2019-02-26T13:58:33.463 回答