【问题标题】:Is there a way to pass dependent fields to a Julia struct?有没有办法将依赖字段传递给 Julia 结构?
【发布时间】:2021-06-08 05:36:24
【问题描述】:
##define the struct
struct DataLoader
    getter::String
    DataLoader(getter="remote") = new(getter)
end
##testing the struct
ld = DataLoader("local")
ld.getter 

##local

ld = DataLoader()
ld.getter 

##remote

我正在尝试在 Julia 中编写一个数据加载器,并在上面定义一些其他方法。

用户可以通过两种方式加载数据 - “remote”和“local”。

如果用户选择local,我需要另一个字段base_dir - 存储数据的目录。如果用户选择remote,我不需要base_dir,因为我知道向哪个 URL 发出请求。

之后,当加载器被定义后,我会调用加载器上的一些函数来做其他事情(下面的示例函数):

function bar(x::DataLoader)
    if x.getter == "local"
        #do_somethings
        println("local found")

    elseif x.getter == "remote"
        println("remote found")

    else
        println("wrong mode passed")
        
    end  
end

我的问题是如何在结构中定义这种相互依赖关系?也就是说,我如何告诉用户并在我的代码中实现如果getter 是local 我需要base_dir,如果它是远程的,我可以从我的结构中动态删除字段base_dir

我是 Julia 的新手,所以任何其他关于改进代码的提示也非常受欢迎。

【问题讨论】:

  • 你应该有一个抽象类型DataLoader和两个具体结构DataLoaderLocalDataLoaderRemote。这正是应该使用类型系统而不是一些“特殊”字段的情况。您还可以始终拥有一个工厂,例如 get_data_loader,它返回任一版本的 DataLoader

标签: julia


【解决方案1】:

我认为有几种方法可以做到这一点;在我看来,最简单的一种是依赖调度程序。这围绕使用两个结构,一个用于“本地”,一个用于“远程”。如果真的需要,您可以创建一个它们都属于的“AbstractLoader”,最后会详细介绍。

struct LocalLoader 
    basedir::String
end

struct RemoteLoader 
end

ll = LocalLoader("test_directory")
rl = RemoteLoader()

function bar(ll::LocalLoader)
    println("Base directory is $(ll.basedir)")
end

function bar(rl::RemoteLoader)
    println("This is the remote loader")
end

bar(ll)
bar(rl)

我看到了这种逻辑的几个优点:

  • 对于开发者:这两种方法可以独立开发
  • 对于开发人员:您不必在代码中放置一些“if”逻辑,这样会更简单。 (并且不可能通过无效模式)。换一种说法:您不必依赖 Julia 的调度程序来实现调度程序。
  • 它向用户阐明了 API:当用户想要一个本地对象时,必须传递一个字符串。当用户想要一个遥控器时,他/她不能传递额外的参数。

主要缺点是代码重复。如果存在某些代码重复,则可以对其进行反击,为此,您需要使两个结构属于一个抽象类型。

这将通过以下方式更改代码:

abstract type  AbstractLoader end

struct LocalLoader <: AbstractLoader
    basedir::String
end

struct RemoteLoader <: AbstractLoader
end

ll = LocalLoader("test_directory")
rl = RemoteLoader()

function bar(ll::LocalLoader)
    println("Base directory is $(ll.basedir)")
end

function bar(rl::RemoteLoader)
    println("This is the remote loader")
end

bar(ll)
bar(rl)

function foo(al::AbstractLoader)
    println("Do common tasks")
end

foo(ll)
foo(rl)

【讨论】:

  • 感谢您的回答,肯定有帮助。由于我的 Python 背景,我更多地考虑拥有一个加载器,但根据用户选择的模式会有所不同,但我想这是更“朱利安”的设计模式。
  • 我很高兴它有帮助。祝您有美好的一天。
猜你喜欢
  • 1970-01-01
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多