I tried to use multiple-dispatch for functions that are defined in different modules in Julia, e.g.:
module A
export f
f(i::Integer) = println(i)
end
module B
export f
f(i::AbstractFloat) = println(i)
end
using .A, .B
f(.1)
But it returns an error
WARNING: both B and A export "f"; uses of it in module Main must be qualified
ERROR: LoadError: UndefVarError: f not defined
I understand that julia tries to avoid name conflicts in different modules. But in my case these f functions can be distinguished by their arguments but it still returns an error. In the docs, Julia offers three ways to solve the problem:
Simply proceed with qualified names like A.f and B.f. This makes the
context clear to the reader of your code, especially if f just happens
to coincide but has different meaning in various packages. For
example, degree has various uses in mathematics, the natural sciences,
and in everyday life, and these meanings should be kept separate.
Use the as keyword above to rename one or both identifiers, eg
julia> using .A: f as f
julia> using .B: f as g
would make B.f available as g. Here, we are assuming that you did not
use using A before, which would have brought f into the namespace.
When the names in question do share a meaning, it is common for one
module to import it from another, or have a lightweight “base” package
with the sole function of defining an interface like this, which can
be used by other packages. It is conventional to have such package
names end in ...Base (which has nothing to do with Julia's Base
module).
For the first two solutions, they can't solve my problem since I really need to display multiple-dispatch and they have to be defined in different modules, and I don't understand the 3rd solution. Could someone help me please?
function f() end
module A
export f
Main.f(i::Integer) = println(i)
end
module B
export f
Main.f(i::AbstractFloat) = println(i)
end
using .A, .B
f(.1)
Basically, make them the same function by defining a "prototype" function outside both of them and specialize that function twice in each submodule. Here because module A and B lives in global scope so I used Main., you should use whatever is housing your sub modules
I am trying to use shadow variables in optapy but I am not sure I understand how I can update their values correctly. The documentation of OptaPlanner suggests that to update a shadow variable, OptaPlanner uses a VariableListener, but they seem not supported in optapy yet. Am I reading this wrong and I do not need a VariableListener?
If I use the example in the optapy documentation:
from optapy import planning_entity, planning_variable
from optapy.types import PlanningVariableGraphType
#planning_entity
class Customer:
#planning_variable(object, graph_type = PlanningVariableGraphType.CHAINED, ...)
def get_previous_standstill(self):
return self.previous_standstill
def set_previous_standstill(previous_standstill):
...
from optapy import planning_entity, inverse_relation_shadow_variable
#planning_entity
class Standstill:
#inverse_relation_shadow_variable(Customer, source_variable_name ="previous_standstill")
def get_next_customer(self):
return self.next_customer
def set_next_customer(Customer nextCustomer):
...
How is variable next_customer updated?
Custom shadow variables (which use custom VariableListeners) are currently not supported (tracking issue: https://github.com/optapy/optapy/issues/75), but builtin shadow variables (which use predefined VariableListeners) are. The builtin shadow variables are: #inverse_relation_shadow_variable, which updates when the source variable takes the object as a value; and #anchor_shadow_variable which updates when the start of a chain for the source chained variable changes.
In the above example, If I have a Standstill standstill, then whenever OptaPy updates a Customer customer via customer.set_previous_standstill(standstill), standstill.set_next_customer(customer) is called.
i use the Mathematical function "min" in my Kotlin code to declare a variable "toRemove"
val toRemove = min(preferredQuantity - taken, stock.quantity)
error message : Kotlin unresolved reference
1/ may i know how could i solve it?
2/ the function is within kotlin.math, why I cannot use it directly?
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.math/
Thanks!
For completeness' sake: as pointed out by #Tenfour04 in the comments, make sure that kotlin.math.min is imported by checking that one of
import kotlin.math.min
import kotlin.math.*
is on top of the file. The kotlin.math.* variant will import everything from the kotlin.math package. See the Kotlin documentation page on imports.
Suppose I have a module like this:
module Foo
let x = 1
let y = 2
Now I can use this module like this:
module Bar
let z = Foo.x + Foo.y
Is it possible to import a definition from Foo such that it does not need to be qualified?
Something like:
module Bar
import x from Foo // Not real code
let z = x + Foo.y // x need not be qualified
Note that I do not want to import everything from Foo
You cannot, there is no direct F# equivalent to the ES6 import { ... } from 'Module' syntax. F# supports organizing code into both modules and namespaces, but both modules and namespaces are 'imported' in their entirety with the open keyword. As mentioned in the comments, you can use local bindings to simplify qualified access to values (such as let exchangeRange = Conversions.Currency.UsdToCadExchangeRate) or type aliases to simplify qualified access to types (type Converter = Conversions.Currency.CurrencyConverter).
In addition, modules can be marked with the [<AutoOpen>] attribute to make their contents accessible without qualified access, or the [<RequireQualifiedAccess>] attribute to make their contents accessible only when qualified, even if the module is referenced in an open expression.
See this MSDN article for more information.
There are two packages I want to use: CorpusLoaders.jl, and WordNet.jl
CorpusLoaders.SemCor exports sensekey(::SenseTaggedWord)
WordNet exports sensekey(::DB, ::Synset, ::Lemma)
I want to use both sensekey methods.
Eg
for some mixed list of items: mixedlist::Vector{Union{Tuple{SenseTaggedWord},Tuple{DB, Synset,Lemma}}.
Ie the items in the list are a mixture of 1-tuples of SenseTaggedWord, and3 tuples of DB, Synset, and Lemma.
for item in mixedlist
println(sensekey(item...)
end
should work.
This example is a little facetious, since why would I be mixing them like this.
But, hopefully it serves for illustrating the problem in the general case.
Trying to using CorpusLoaders.SemCor, WordNet to bring in both results in WARNING: both WordNet and Semcor export "sensekey"; uses of it in module Main must be qualified.
Manually importing both: import CorpusLoaders.SemCor.sensekey; import WordNet.sensekey results in WARNING: ignoring conflicting import of Semcor.sensekey into Main
What can be done? I want them both, and they don't really conflict, due to multiple-dispatch.
Given that CorpusLoaders.jl is a package I am writing I do have a few more options, since I could make my CorpusLoaders.jl depend on WordNet.jl.
If I did do than then I could say in CorpusLoaders.jl
import WordNet
function WordNet.sensekey(s::SenseTaggedWord)...
and that would make them both work.
But it would mean requiring WordNet as a dependency of CorpusLoaders.
And I want to know how to solve the problem for a consumer of the packages -- not as the creator of the packages.
tl;dr qualify the functions when using them in your script via their module namespace, i.e. CorpusLoader.sensekey() and WordNet.sensekey()
Explanation
My understanding of your question after the edits (thank you for clarifying) is that:
You have written a package called CorpusLoaders.jl, which exports the function sensekey(::SenseTaggedWord)
There is an external package called WordNet.jl, which exports the function sensekey(::DB, ::Synset, ::Lemma)
You have a script that makes use of both modules.
and you are worried that using the modules or "importing" the functions directly could potentially create ambiguity and / or errors in your script, asking
how can I write my CorpusLoaders package to prevent potential clashes with other packages, and
how can I write my script to clearly disambiguate between the two functions while still allowing their use?
I think this stems from a slight confusion how using and import are different from each other, and how modules create a namespace. This is very nicely explained in the docs here.
In essence, the answers are:
You should not worry about exporting things from your module that will clash with other modules. This is what modules are for: you're creating a namespace, which will "qualify" all exported variables, e.g. CorpusLoaders.sensekey(::SenseTaggedWord).
When you type using CorpusLoaders, what you're saying to julia is "import the module itself, and all the exported variables stripped from their namespace qualifier, and bring them into Main". Note that this means you now have access to sensekey as a function directly from Main without a namespace qualifier, and as CorpusLoaders.sensekey(), since you've also imported the module as a variable you can use.
If you then try using the module WordNet as well, julia very reasonably issues a warning, which essentially says:
"You've imported two functions that have the same name. I can't just strip their namespace off because that could create problems in some scenarios (even though in your case it wouldn't because they have different signatures, but I couldn't possibly know this in general). If you want to use either of these functions, please do so using their appropriate namespace qualifier".
So, the solution for 2. is:
you either do
using CorpusLoaders;
using WordNet;
, disregarding the warning, to import all other exported variables as usual in your Main namespace, and access those particular functions directly via their modules as CorpusLoaders.sensekey() and WordNet.sensekey() each time you need to use them in your script, or
you keep both modules clearly disambiguated at all times by doing
import CorpusLoaders;
import WordNet;
and qualify all variables appropriately, or
in this particular case where the function signatures don't clash, if you'd really like to be able to use the function without a namespace qualifier, relying on multiple dispatch instead, you can do something like what FengYang suggested:
import CorpusLoaders;
import WordNet;
sensekey(a::SenseTaggedWord) = CorpusLoader.sensekey(a);
sensekey(a::DB, b::Synset, c::Lemma) = WordNet.sensekey(a, b, c);
which is essentially a new function, defined on module Main, acting as a wrapper for the two namespace-qualified functions.
In the end, it all comes down to using using vs import and namespaces appropriately for your particular code. :)
As an addendum, code can get very unwieldy with long namespace qualifiers like CorpusLoader and WordNet. julia doesn't have something like python's import numpy as np, but at the same time modules become simple variables on your workspace, so it's trivial to create an alias for them. So you can do:
import CorpusLoaders; const cl = CorpusLoaders;
import Wordnet; const wn = WordNet;
# ... code using both cl.sensekey() and wn.sensekey()
In this case, the functions do not conflict, but in general that is impossible to guarantee. It could be the case that a package loaded later will add methods to one of the functions that will conflict. So to be able to use the sensekey for both packages requires some additional guarantees and restrictions.
One way to do this is to ignore both package's sensekey, and instead provide your own, dispatching to the correct package:
sensekey(x) = CorpusLoaders.sensekey(x)
sensekey(x, y, z) = WordNet.sensekey(x,y,z)
I implemented what #Fengyang Wang said,
as a function:
function importfrom(moduleinstance::Module, functionname::Symbol, argtypes::Tuple)
meths = methods(moduleinstance.(functionname), argtypes)
importfrom(moduleinstance, functionname, meths)
end
function importfrom(moduleinstance::Module, functionname::Symbol)
meths = methods(moduleinstance.(functionname))
importfrom(moduleinstance, functionname, meths)
end
function importfrom(moduleinstance::Module, functionname::Symbol, meths::Base.MethodList)
for mt in meths
paramnames = collect(mt.lambda_template.slotnames[2:end])
paramtypes = collect(mt.sig.parameters[2:end])
paramsig = ((n,t)->Expr(:(::),n,t)).(paramnames, paramtypes)
funcdec = Expr(:(=),
Expr(:call, functionname, paramsig...),
Expr(:call, :($moduleinstance.$functionname), paramnames...)
)
current_module().eval(funcdec) #Runs at global scope, from calling module
end
end
Call with:
using WordNet
using CorpusLoaders.Semcor
importfrom(CorpusLoaders.Semcor, :sensekey)
importfrom(WordNet, :sensekey)
methods(sensekey)
2 methods for generic function sensekey:
sensekey(db::WordNet.DB, ss::WordNet.Synset, lem::WordNet.Lemma)
sensekey(saword::CorpusLoaders.Semcor.SenseAnnotatedWord
If you wanted to get really flash you could reexport the DocString too.