# How to extend method used in package extension

**URL:** <https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871>\
**Category:** General Usage\
**Tags:** question, packages, method-extension\
**Created:** [December 20, 2023, 5:54pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871 "2023-12-20T17:54:06Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [December 20, 2023, 5:54pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/1 "2023-12-20T17:54:06Z")

</div>

Hello,

I am using a package which has plotting functionality defined in a package extension. It uses a function `package_function` which is defined in the package module as

`function package_function end`

and in the module PlotExt, there are various methods for `package_function`. I would like to create a method `package_function(x::MyNewType)`. I used

`import ThePackage: package_function`

and defined the method for the new type. It is visible in main, but is not visible by PlotExt. Is there a way to extend `package_function` so that it is visible by PlotExt?

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [December 20, 2023, 6:20pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/2 "2023-12-20T18:20:13Z")

</div>

I’m slightly confused where `import ThePackage: package_function` is. If you put it in `PlotExt`, then it should be available to extend there.

```julia
module PlotExt
    # ...
    import ThePackage: package_function
    # ....
end

```

The problem you might run into is if `MyNewType` is available and exported.

If you could be more concrete on how you have arranged your code and where your import statements are, that would be helpful to give you a specific answer.

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [December 20, 2023, 7:08pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/3 "2023-12-20T19:08:21Z")

</div>

@mkitti, thank you for your reply. Let me see if I can clarify. I am using a package developed by someone else. So I do not want to include `MyNewType` and `package_function(x::MyNewType)` in that person’s package. I would like to define those separately in my own project:

my\_script.jl

```julia
using Plots
using ThePackage
import ThePackage: package_function 

struct MyNewType
...
end

function package_function(x::MyNewType)
...
end 

x = MyNewType()

# this function is defined in PlotsExt of ThePackage
# it calls package_function
outer_package_function(x)

```

When I run this code, I receive an error originating from PlotsExt indicating that ` package_function(x::MyNewType)` is not defined. In the past, I have used a similar pattern for code defined within the ThePackage module. However, it does not seem to work for PlotExt.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [December 20, 2023, 8:27pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/4 "2023-12-20T20:27:06Z")

</div>

Can you provide the error’s full stacktrace and check `ThePackage.package_function === Base.get_extension(ThePackage, :PlotExt).package_function`? Or `:PlotsExt`, however it’s really spelled (you wrote both so far).

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [December 20, 2023, 8:27pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/5 "2023-12-20T20:27:45Z")

</div>

What are you describing is not a package extension. A package extension is a glue package that loads when two or more other packages are loaded.

Instead you are actually adding new methods and new types. In this case, this should just be a regular package that depends on the other package.

You should not insert `MyNewType` or `package_function` into `ThePackage`’s namespace. Instead, your package could reexport all of `ThePackage`’s symbols adding the new type and new functions to it. There is a package Reexport.jl that assists with this pattern.

```julia
module ThePackage
    export foo, Bar
    foo() = println("Hello")
    struct Bar
    end
end

module MyPackage
    using Reexport
    @reexport using ThePackage
    export MyNewType, my_function

    struct MyNewType
    end
    function my_function(x::MyNewType)
    end
end

```

Technically it is possible to insert methods and functions into foreign packages via `@eval` but this is highly discouraged and breaks a lot of things such as precompilation caches. For example, the following is how one would insert a type into the `Base` module.

```julia
julia> Base.Foo
ERROR: UndefVarError: `Foo` not defined

julia> struct Base.Foo
           x::Int
       end
ERROR: syntax: invalid type signature around REPL[2]:1

julia> @eval Base begin # Do not do this
           struct Foo
               x::Int
           end
       end

julia> Base.Foo
Base.Foo

julia> Base.Foo(5)
Base.Foo(5)

```

Here’s a fully self contained in-REPL demonstration. The main difference here from a real scenario is that the packages are defined inline as `Main.ThePackage` and `Main.MyPackage`, so we have to refer to them relatively.

```julia
julia> using Pkg

julia> Pkg.activate(; temp = true)
  Activating new project at `/var/folders/5j/phv_vfc97m967ww98fbvtmfr0000gq/T/jl_k1C41J`

julia> Pkg.add("Reexport")
   Resolving package versions...
    Updating `/private/var/folders/5j/phv_vfc97m967ww98fbvtmfr0000gq/T/jl_k1C41J/Project.toml`
  [189a3867] + Reexport v1.2.2
    Updating `/private/var/folders/5j/phv_vfc97m967ww98fbvtmfr0000gq/T/jl_k1C41J/Manifest.toml`
  [189a3867] + Reexport v1.2.2

julia> module ThePackage
           export foo, Bar
           foo() = println("Hello")
           struct Bar
           end
       end
Main.ThePackage

julia> module MyPackage
           using Reexport
           @reexport using ..ThePackage
           export MyNewType, my_function
           
           struct MyNewType
           end
           function my_function(x::MyNewType)
           end
       end
Main.MyPackage

julia> using .MyPackage

julia> foo
foo (generic function with 1 method)

julia> Bar
Bar

julia> MyNewType
MyNewType

julia> my_function
my_function (generic function with 1 method)

julia> foo()
Hello

julia> @which foo
Main.ThePackage

julia> @which Bar
Main.ThePackage

julia> @which MyNewType
Main.MyPackage

julia> @which my_function
Main.MyPackage

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [December 20, 2023, 8:37pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/6 "2023-12-20T20:37:28Z")

</div>

> [@mkitti](#):
>
> What are you describing is not a package extension. A package extension is a glue package that loads when two or more other packages are loaded.
> 
> Instead you are actually adding new methods and new types.

I was assuming that there was an unposted package extension and that `outer_package_function` really originated in `ThePackage` and is only implemented further in `PlotExt`, but this is making me question things too.

How is `PlotExt` structured, and is it in the `/ext` directory of `ThePackage`?

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [December 20, 2023, 8:51pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/7 "2023-12-20T20:51:44Z")

</div>

> [@Benny](#):
>
> I was assuming that there was an unposted package extension and that `outer_package_function` really originated in `ThePackage` and is only implemented further in `PlotExt`, but this is making me question things too.

I apologize for the confusion. I think Benny is correct about what I am trying to do. It turns out that I was mistaken about where `package_function` was defined. It was only defined in the PlotExt module. When I dev’ed the package and added `function package_function end` to the main package, and then imported it into PlotExt, I was able to extend the method for the new type and it worked with PlotExt. Sorry again for the oversight. I am still getting familiar with the package extensions.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [December 20, 2023, 9:03pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/8 "2023-12-20T21:03:54Z")

</div>

The key concept there is that unlike packages, extensions and the names within them are not importable. So, their purpose is mixing names from their package dependencies, though it is allowed to create internal names to implement things. Do not be misled by `Base.get_extension`; while that lets you access an extension’s module, assigning anything from it to a new variable is not equivalent to importing (and optionally renaming) an existing variable. For now, that seems more useful for code reflection, and names should strictly be imported from packages; for example, instead of an extension, make a package with the same dependencies and import that in addition to them.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [December 20, 2023, 9:16pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/9 "2023-12-20T21:16:16Z")

</div>

I’m still not following why we need this to be a package extension. You do not own `ThePackage`, so why are you building an extension? Why not just create `MyPackage`?

An extension to `MyPackage` would only be useful if `ThePackage` is an optional (weak) dependency of `MyPackage` and you needed to add some functionality to integrate `MyPackage` and `ThePackage` together.

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [December 20, 2023, 9:48pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/10 "2023-12-20T21:48:11Z")

</div>

@mkitti sorry. I think I am having trouble communicating the issue. Let me try to clarify again with an extended example:

**code for someone’s package**

```julia
module SomePersonsPackage 

    # the problem was that some_function was not defined in the package 
    function some_function end 
    ...
end

module PlotExtensionForSomePersons 
    
    import SomePersonsPackage: some_function

    function outer_function(x)
        
        # I want to use my own method here
        some_function(x)
        ...
        # I want to use the existing functions here
        # so I can re-use existing code
        cool_function_I_want_to_use(x)
        ...
    end
end

```

**my\_script.jl**

```julia
using Plots
using SomePersonsPackage
import SomePersonsPackage: some_function 

struct MyNewType
...
end

function some_function(x::MyNewType)
...
end 

x = MyNewType()

outer_function(x)

```

The structure of the example above is correct. I want to use all of the functions defined by `SomePersonsPackage`, except `some_function`. The default behavior of `some_function` does not work for my use case; so I defined my own method for `some_function` to work with `MyNewType`.

The problem—which I did not realize initially—was that `some_function` was not defined in `SomePersonsPackage`. I confused it with a different function which was defined in both places. So extending `some_function` will work so long as it is also defined in `SomePersonsPackage` and imported into the plotting extension.

I hope that clarifies the issue and the eventual solution. If not, no worries. I eventually figured out my silly mistake. I want to thank you for your assistance!

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [December 20, 2023, 10:36pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/11 "2023-12-20T22:36:26Z")

</div>

I think you are referring to the term “package extension” without realizing that this refers to very specific concept.

[https://pkgdocs.julialang.org/v1/creating-packages/#Conditional-loading-of-code-in-packages-(Extensions)](https://pkgdocs.julialang.org/v1/creating-packages/#Conditional-loading-of-code-in-packages-(Extensions))

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [December 20, 2023, 11:58pm UTC](https://discourse.julialang.org/t/how-to-extend-method-used-in-package-extension/107871/12 "2023-12-20T23:58:47Z")

</div>

> [@mkitti](#):
>
> I think you are referring to the term “package extension” without realizing that this refers to very specific concept.

I’m not sure this is the case. It reads to me like he added two packages he does not own, `ThePackage` and `Plots`, and `ThePackage` has an extension `PlotExt` dependent on `Plots`. He wanted to add a method to `package_function` in his own script, but it only existed in the extension, not either of the packages, so it couldn’t be imported to begin with; `import ThePackage: package_function` should’ve printed a warning saying so, and the script’s `package_function` definition would’ve made a separate new function. `dev`ing `ThePackage` and moving `package_function`’s origin to the package made it possible.

Seems to me that the owner of `ThePackage` never intended for `outer_function` or `some_function` to be exposed. I have no idea what it’s for because it doesn’t obviously extend `Plots` and `ThePackage`, maybe it’s some internal detail ran at the top level during precompilation or in ` __init__ ()` at loading.
