# Proposal for SharedFunctions.jl package for optional dependency management

**URL:** <https://discourse.julialang.org/t/proposal-for-sharedfunctions-jl-package-for-optional-dependency-management/23526>\
**Category:** Internals & Design\
**Created:** [April 25, 2019, 5:18pm UTC](https://discourse.julialang.org/t/proposal-for-sharedfunctions-jl-package-for-optional-dependency-management/23526 "2019-04-25T17:18:42Z")\
**Posts on this page:** 1\
**Showing post:** 66

<div class="post-metadata">

**Author:** ![TsurHerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tsurherman/32/1234_2.png) [@TsurHerman](https://discourse.julialang.org/u/TsurHerman)\
**Post date:** [April 30, 2019, 9:11pm UTC](https://discourse.julialang.org/t/proposal-for-sharedfunctions-jl-package-for-optional-dependency-management/23526/66 "2019-04-30T21:11:56Z")

</div>

> [@StefanKarpinski](#):
>
> This seems to have become another thread on context dispatch

There are ~~three~~ several topics here as I see it and I’ll do my best to be brief and concise, with as little errors as possible

1. The discussion started on having the need to define some abstract base module with names, so different modules can coordinate upon(extend common interface)

2. It evolved to:

> [@cstjean](#):
>
> There should be a way to define a `LightGraphs.cartesian_product` method without importing `LightGraphs` .

1. @tkf made the observation that we can extend a function in a module before it is loaded, in a fashion that is roughly equivalent to the following:  
let  
`Function{UID,NAME} where UID where NAME`  
be the abstract base type of all functions in julia, where UID stands for the module or package UUID  
Then any module can extend a function in another module without having to specifically load it.

Here is an example of extending function plot in module Plots using module name for UID

```julia
(plot::Function{:Plots,:plot}(x::MyVecType) = plot(toBaseVec(x))

```

1. Jeff suggested that there will be a way to tell the system to merge functions in different modules(hope I understood correctly)

2. @chakravala wants to do the same but make the merge visible only locally as not to affect the integrity of other modules

3. Context Dispatch is a generalization of the way multiple-dispatch is handled today as it enables you to do the same things, using the same code, however, an implicit merging of exported function names as in 5 feels very natural in this way and can often replace explicit coordination as in 3

> [@Binary Caching and Pre-compilation .. again](https://discourse.julialang.org/t/binary-caching-and-pre-compilation-again/19589/1):
>
> **The building blocks:**
> 
> - A Context is a set of modules.
> - The Context of module M is the set of all modules that module M depends upon.
> - Extension: The method table for a Context consists only from methods belonging to modules in the Context
> - Propagation: the context is propagated recursively down the AST, and is narrowed if proven that it will resolve the call just as specific as the wider context

> [@StefanKarpinski](#):
>
> - Base defines `sort!` which calls `isless` by default
> - Package `A` defines type `T` and `isless` methods for it
> - Package `B` defined function `f` which calls `sort!` on arguments of unknown type
> - Package `C` uses `A` and `B` : it constructs objects of type `A.T` and passes them to `B.f`

so for your toy example, calling function B.f from the context of module C uses modules Base, A and B for its method table so there is no problem.

Now let’s say module D who uses C, and calls ` C.g()` which in turn calls B.f with the constructed types.  
Since it can be proved that the context of C will suffice, the context can be narrowed.

And as long as you don’t change the state of module C or its dependent modules you can re-use the  
binary resulting from compiling the code for ` call C.g() from the context of C`

Another aspect is that the automatic merging of exported names suddenly looks very appealing.

Your example with Context Dispatch and automatic merging of exported names would look like:

```julia
module Base
    sort!(x,y) = isless(x,y)
    isless(x,y) = ErrorException("unimplemented")
    export isless,sort!
end

module A
    struct T end
    isless(x::T,y::T) = true
    export isless
end

module B
    using Base
    f(x,y) = sort!(x,y)
end

module C
    using Base, A, B
    
    g() = B.f(A.T(),A.T())
end

```

In the context of module C, the functions Base.isless and A.isless got merged.

> [@StefanKarpinski](#):
>
> If there are other references, in PL literature or elsewhere?

I don’t think so, like many others here, I think, I learned about compilers and LLVM and multiple-dispatch through the feat of engineering we call “julia”.

It came up initially to solve what @chakravala was writing about, it was a little bit obscure in the beginning but it starts to feel more and more like the right way to go.

O.k it took me more than 3 hours to write this, and I am losing focus, what I meant by the saying  
“I don’t own the idea” is that it feels like a larger subject than just a small eureka moment.

---

_[View the full topic](https://discourse.julialang.org/t/proposal-for-sharedfunctions-jl-package-for-optional-dependency-management/23526)._
