How to use package in Julia without importing it? - julia

If you write it imports all bunch of methods into the current scope.
using Plots
plot(rand(5,5))
I need only one method, is it possible to write the same code but without using or importing anything, I don't want to pollute the current scope with Plots exports and don't mind to prefix it with package name every time I use it.
Plots.plot(rand(5,5))

import will bring a module into scope without any of its exported names. You can still use qualified names to reference names within the imported module:
import Plots
Plots.plot(rand(5,5))
To avoid using the qualified name, you can create a binding to a new name:
const plot_from_plots = Plots.plot

According to the Julia website you should be able to do:
using Plots: plot
Which will only bring plot() in scope
See Module aliasing in Julia for how to create an alias for the method

In addition to the other suggestions; I wrote a package (ImportMacros) which lets you import functions with other names without bringing anything else into scope:
julia> using ImportMacros
julia> #import Plots.plot as plt
julia> plt
plot (generic function with 3 methods)
so Plots.plot is available as plt, yet Plots is undefined:
julia> Plots
ERROR: UndefVarError: Plots not defined

Related

R: how to properly include libraries in my package

I'm writing by first R-Package and was wondering what the right way is to include other libraries, like ggplot2.
So there are two places where an import statement can go in my package. The DESCRIPTION file and the NAMESPACE, where the latter requires to include ggplot in some roxagen statement like #'#import ggplot2.
Actually I thought that is is enough to include ggplot2 inside DESCRIPTION, as I thought that loading my packages will also load or dependencies, however, when ggplot2 is not in the namespace it seems like I cannot use function, e.g. aes, ggplot without writing ggplot2::aes or ggplot2::gpplot. So for what are the import statements in each of the config files, i.e. DESCRIPTION and NAMESPACE?
The one required step is to include ggplot2 under Imports: in your DESCRIPTION file. This ensures that ggplot2 is installed when your package is installed.
Then, to use functions from ggplot2 in your package, you need to tell R where to look for them. You can do this in 3 ways:
Put the name of the package before the function name when you use it: ggplot2::aes(). This is my preferred method, as it doesn’t add anything extra to your NAMESPACE, avoids any name collisions, and avoids breakage if you later rework or remove a function.
Import specific functions as you use them. Do this by putting #’ #importFrom ggplot2 aes in the roxygen block above the function using it. Add however many function names you need to that line. After doing that, you can use aes() directly without having to specify the namespace it’s coming from with ggplot2::aes(). This can be convenient if you’re working with a lot of functions (like with ggplot2), but I recommend using the first option instead in general to keep your NAMESPACE tidier. You technically only need to include the #importFrom line for once in your package for any function, but I recommend including it for each function that is using the imported functions. That way, if you ever rework or remove a function, the other functions don’t break.
You can import a whole package of functions by putting #’ #import ggplot2 in a roxygen block. This imports every function from a package. This can be a lot for big packages like ggplot2 and dplyr, and the can potentially cause issues, so I suggest never doing this and instead importing only the specific functions you need or calling them with ggplot2::aes().
If you depend on a package you should put it in the Imports field of the DESCRIPTION file, after which you can use pkgname::function() in your code.
usethis::use_package() function can help you do this.
If you want your code to be able to use any code of the package without the use of ::, you should put a roxygen comment somewhere like this:
#' #import pkgname
NULL
This then gets ported by roxygen2 to your NAMESPACE file.
If you want to specifically use some functions (but not others), you can use the following that is used by roxygen2:
#' #importFrom pkgname fun1 fun2
NULL
The usethis::use_import_from() function can help you do the above. In the examples above NULL only indicates that you're not documentating a function or data, and you can use it at the end of a documentation comment block.

Modifying a function from a package in Julia

First I'm sorry if this question seems vague, because I'm new to Julia and I'm mostly just wondering in Julia if there's an easy way to modify a native function of a package while simply using all its dependencies in general, or there has to be a package-specific solution.
For example, foo is a function from the package LibraryA, and it can be simply called and used as follows without problem:
using LibraryA
foo(args)
However, if I want a slightly modified version of foo(), say bar(), whose source code (mostly copy of the foo() function) is in a separate file bar.jl and uses a lot of dependencies from LibraryA, the lines
using LibraryA
include("bar.jl")
bar(args)
will not work as lots of loaderrors occur:
LoadError: UndefVarError: vars not defined
where vars are the variables defined in the package LibraryA
As long as the variables are in the global scope in LibraryA, you can import them explicitly to make them available in the current scope:
using LibraryA: vars, bigvar, littlevar, baz
include("bar.jl")
bar(args)
As a matter of convention, however, make sure that these variables are not intended to be "private" i.e. intended for internal use in LibraryA (there's no explicit private marker in Julia, it's generally inferred based on documentation).
If a variable vars itself appears to be private, but has an accessor getvars that's public, you can instead create a new variable vars in the current scope using that accessor.
using LibraryA: bigvar, littlevar, baz, getvars
vars = getvars()
include("bar.jl")
bar(args)
(Make sure to make it a const var if it was const originally, and similarly type annotate it var::WhateverTheTypeOfVarIs if it is annotated in the original module as well.)

How to use a Python module's functions inside a function you're defining WITHOUT importing beyond your function's scope (Ie: R has package::function)

Is there a way to incorporate Python functions from an external module/library in a function you're writing/defining, without importing them globally or beyond of the function scope?
For example, in R you can do package::function:
myfxn <- function(x){ # R example
dplyr::as_tibble(x)
}
I'd like to do something similar in Python, but as far as I can tell, people usually just import the modules/elements of modules at the top of the file (for speed, succinctness, comprehensiveness, etc.) I know you can technically do something like this:
Example of what I know you can do in Python (but isn't what I'm looking for):
def myfxn(x): # Python
from pandas import DataFrame
return(DataFrame(x))
...But what I'd really like is a way to use a function like the pandas DataFrame one without having to globally import it. I wish there was something like...
def myfxn(x): # Python
return(pandas.DataFrame(x))
Where I wouldn't have to actually import anything. Is there any way of doing what I'm referencing? If not, is there an argument (except for a tiny amount of processing speed) about why there shouldn't be?

Extend map from other packages at compile time

I'm trying to extend a map across packages at 'compile time'. Is this possible?
I have package A with a predefined map:
package A
var MyMap = map[string]string{"key1": "value", "key2": "value"}
And I would like to extend the map during 'compile time'. This shall be done in another package. E.g. like so (not working code ofc.):
package B
import "A"
A.MyMap.Slice1["key3"] = "value" // extend the map during compile time
Is this somehow possible?
You can't do this "at compile" time. In fact, the composite literal that package A uses, that also will be constructed and used at runtime. There are no composite literal constants.
Going further, whatever code you write in package B, if it imports package A, code of package B will only run after package A has been initialized, including the map you posted.
If you want A.MyMap to have a different value before it can be seen by any other package, you should modify the source of package A. This could be a generated additional file, which could use a package init() function, assigning a new value to MyMap, or adding new values to it.
If you can, you could also modify package A so that the initialization of MyMap is moved to a different source file, one that can be generated.
It is actually extension at runtime but it should fit your example.
Use init function.
package B
import "A"
func init() {
A.MyMap["key3"] = "value"
}
You pass a string at linking time with command
go build -ldflags '-X somemap={"k":"v"}'
and then parse it to map at run time. You can easily use JSON format.
See more on GcToolchainTricks.

julia counterpart for "from module import some_func" in python

I find using Module in julia is equivalent to from Module import * in python. Is there any way to import a single function or variable from a module.
You can import e.g. a single function with
using Module.func
If you also want to be able to extend the function with new methods, use instead
import Module.func
If you want to import several named functions and variables from the same module, you can e.g. use one of
using Module: func1, func2
import Module: func1, func2
All of these forms allow to import definitions from Module regardless of whether they are exported there, unlike using Module, which only imports exported definitions.
Also keep in mind that it is really values that are imported, not variables, so if you try to assign to an imported variable, you will not see a change in the originating module (and you will get a warning).
If you have a module Foo with a function bar (or something else specific you wan to import) you can do:
import Foo: bar
This brings only bar into scope.

Resources