I have different set of math expressions that must be evaluated at run-time. Currently the task is done by replacing symbols with equivalent values and eval the result. (could be done by any existing symbolic packages)
Now, refer to the definition of modules in Julia-lang:
Modules in Julia are separate variable workspaces, i.e. they introduce
a new global scope .... Modules allow you to create top-level definitions (aka
global variables) without worrying about name conflicts when your code
is used together with somebody else’s.
And with the power of Julia to do meta-things,
I'm wondering if it is possible to create anonymous modules at run-time m=Module(), and use them as a scope to evaluate expressions eval(m, :(a+b)).
But I simply can't find a way to load variable into the run-time modules.
Although I could get result with:
julia> ex=:(module mo; a=1; b=4; end)
julia> eval(ex)
julia> eval(mo,:(a+b))
I prefer more functional way, using anonymous modules.
Any Help.
This works:
julia> m=Module()
anonymous
julia> eval(m, :(a=5))
5
julia> m.a
5
julia> eval(m, :(a))
5
julia> eval(m, :(2a))
10
Related
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
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.
I've been reading a lot of Julia documentation (version 0.4) and am still having problems with loading Julia files. This seems like it should be really easy. So, plainly and simply, how are we supposed to use Julia code from other files directly in our current code? And, as a related, helpful bonus, is there any history or language design decisions that, understood, would illuminate the situation?
P.S. I'm using 0.4.
If you want problem specifics, here are some things I'm dealing with:
First
Using the REPL, I want to use some functions I have written in a different file. Supposedly, I should be able to load said file like this:
julia> using Foobar
That just gives me ArgumentErrors no matter what I do. I've tried including it before trying to use it:
julia> include("Foobar.jl")
julia> using Foobar
I've also tried updating the load path before trying to use it:
julia> push!(LOAD_PATH, "/Users/me/julia")
julia> using Foobar
Second
When I try to fix the first problem by including the file before using it, I get an error for any line that has: using .... The message is that a module cannot be found in path. Or in other words, I'm trying to load a module in the current working directory that depends on another module in the current working directory. When I include the file I'm trying to load, it tries to find the dependency and cannot.
Third
I've tried relative paths. I.e. I'm in the same directory as the .jl file and do:
julia> using .Foobar
if you use include("/path/to/myscript.jl") then you should then have access to any functions, objects, etc. defined in the file you called with include(). No additional calls to using should be needed.
Here is an answer that gives more info on details for creating whole packages (rather than just individual scripts like in the example above), how to do them, and how the using terminology factors in with them: julia: create and use a local package without Internet . For instance, packages must be installed in a particular path relative to your other julia files, not just in the arbitrary working directory that your script is in.
See also here for a longer tutorial on packages.
It seems to work well enough here:
julia> push!(LOAD_PATH, "/Users/me/julia")
2-element Array{ByteString,1}:
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/local/share/julia/site/v0.4"
"/Users/me/julia"
julia> readdir(LOAD_PATH[end])
1-element Array{ByteString,1}:
"MyModule.jl"
julia> using MyModule
julia> x
"Hi there"
where MyModule.jl contains:
module MyModule
export x
x = "Hi there"
end
Suppose I have a module which defines some basic constants such as
integer, parameter :: i8 = selected_int_kind(8)
If I include this in my main program and I also include a module which does some other things (call this module functions) but functions also uses constants, then am I essentially including constants twice in my main program?
If so, is this bad? Can it be dangerous at all to include a module too many times in a program?
No, it is fine to do this. All you are doing with the use statement is providing access to the variables and functions defined in your module via use association. It is not like declaring variables each time they are use'd (they are in fact redeclared however).
The only thing to be wary of are circular dependencies, where module A uses module B and module B uses module A. This is not allowed.
Edit: From Metcalf et al. Fortran 95/2003 explained, pg. 72:
A module may contain use statements that access other modules. It must not access itself directly or indirectly through a chain of use statements, for example a accessing b and b accessing a.
Whilst this quote doesn't directly answer your question, it reiterates that really the only thing you can't do is have a circular dependency. So the following is perfectly valid:
module one_def
implicit none
integer, parameter :: one=1
end module one_def
module two_def
use one_def, only : one
implicit none
integer, parameter :: two=one+one
end module two_def
program test
use one_def, only : one
use two_def, only : two
implicit none
print*, two == one+one ! This prints .True.
end program
I would like to design 2 modules A and B which both have their own functions, for instance: A.compare: A.t -> A.t -> bool, B.compare: B.t -> B.t -> bool. The elements of A and B are convertible. So I would also need functions a_of_b : B.t -> A.t and b_of_a : A.t -> B.t. My question is where I should define these functions? inside the structure of A or the one of B or somewhere else?
Could anyone help?
Edit1: just amended some errors based on the first comment
This is a classic design problem. In OOP languages, it is hard to resolve this elegantly because a class encapsulates both a type definition and methods related to that type. Thus, as soon as you have a function such as a_of_b, which regards two types to an equal extent, there is no clear place for it.
OCaml correctly provides distinct language mechanisms for these distinct needs: type definitions are introduced with the keyword type, and related methods are collected together in a module. This gives you greater flexibility in designing your API, but does not solve the problem automatically.
One possibility is to define modules A and B, both with their respective types and compare functions. Then, the question remaining is where to put a_of_b and b_of_a. You could arbitrarily give preference to module A, and define the functions A.to_b and A.of_b. This is what the Standard Library did when it put to_list and of_list in Array. This lacks symmetry; there is no reason not to have put these functions in B instead.
Instead you could standardize on using of_ functions vs to_ functions. Let's say you prefer to_. Then you would define the functions A.to_b and B.to_a. The problem now is modules A and B are mutually dependent, which is only possible if you define them in the same file.
If you will have lots of functions that deal with values of type A.t and B.t, then it may be worth defining a module AB, and putting all these functions in there. If you will only need two, then an extra module is perhaps overkill.
On the other hand, if the total number of functions regarding A's and B's is small, you could create only the module AB, with type a, type b, and all related methods. However, this does not follow the OCaml community's convention of naming a type t within its own module, and it will be harder to apply the Set and Map functors to these types.
You probably mean A.compare: A.t -> A.t -> bool because types are in lower cases.
You can have a single module AB which contains both the type for A and the type for B.
You can have a single module AB containing both A & B as sub-modules.
You might also use recursive modules & functors.