Reputation: 615
##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
I'm trying to write a dataloader in Julia with some additional methods later defined on it.
The data can be loaded in two ways by the user - "remote" and "local".
If the user choses local
, I need another field base_dir
- the directory where the data is stored. If the user choses remote
, I don't need base_dir
as I know which URL to make the request to.
After that, when the loader has been defined, I'll call some functions on the loader to do other stuff (example function below):
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
My question is how do I define this co-dependency in the struct? That is, how do I tell the user and implement in my code the logic that if the getter is local
I need base_dir
and if it's remote, I can dynamically remove the field base_dir
from my struct.
I'm new to Julia so any other tips on improving the code would also be more than welcome.
Upvotes: 3
Views: 410
Reputation: 1727
I think there are several ways to do this; in my view, the simplest one is to rely on the dispatcher. This revolves around using two structs, one for "local", one for "remote". If really needed, you can create an "AbstractLoader" they both belong to, more on that at the end.
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)
I see several advantages to this logic:
The main drawback is code duplication. If there is some code duplication it can be countered, to do that you would need to make the two structs belong to an abstract type.
That would change the code in the following way:
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)
Upvotes: 4