# Package extensions - structs inside extensions

**URL:** <https://discourse.julialang.org/t/package-extensions-structs-inside-extensions/101849>\
**Category:** Package Management\
**Created:** [July 20, 2023, 7:15pm UTC](https://discourse.julialang.org/t/package-extensions-structs-inside-extensions/101849 "2023-07-20T19:15:17Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![iabraham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iabraham/32/36532_2.png) [@iabraham](https://discourse.julialang.org/u/iabraham)\
**Post date:** [July 20, 2023, 7:15pm UTC](https://discourse.julialang.org/t/package-extensions-structs-inside-extensions/101849/1 "2023-07-20T19:15:17Z")

</div>

How can one make a struct defined in a package extension available to the user once the extension is loaded?

Suppose we have:

```julia
module MainFoo

using SomeLightDeps 

lightweight_func1 = ... 
lightweight_func2 = ... 

end

```

and its extension that should only be loaded if some heavy dependencies are installed:

```julia
module FooDataExt 

using MainFoo, HeavyDeps 

function extract_prop(x::HeavyType)
.... 
end

struct OneData 
someVar 
end

function OneData(x::HeavyType)
 someTemp1 = extract_prop(x)
 someTemp2 = lightweight_func1(someTemp1)
 someVar = HeavyDeps.heavy_func(someTemp2) 
end

struct TwoData
anotherVar :: AnotherHeavyType
end

function TwoData(yy::HeavyType)
 ....
end

end

```

I am able to make `MainFoo` precompile and usable. Next I load up the heavier dependencies and Julia dutifully loads and precompiles `FooDataExt`. So far so good … now how do I make use of `OneData` and `TwoData` in my program after the extension has been loaded? Both these structs and constructors are only defined in the extension module.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [July 20, 2023, 8:08pm UTC](https://discourse.julialang.org/t/package-extensions-structs-inside-extensions/101849/2 "2023-07-20T20:08:06Z")

</div>

If I’m remembering correctly from what @kristoffer.carlsson said on Slack (now lost), you should be able to writein your extension module

```julia
const MainFoo.OneData = OneData
const MainFoo.TwoData = TwoData

```

I’m not able to test it right now but I thnik that was what would work.

note that it’s not really recommended that you do this. If possible, you should just define `OneData` and `TwoData` in `MainFoo`.

---

<div class="post-metadata">

**Author:** ![iabraham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iabraham/32/36532_2.png) [@iabraham](https://discourse.julialang.org/u/iabraham)\
**Post date:** [July 20, 2023, 8:28pm UTC](https://discourse.julialang.org/t/package-extensions-structs-inside-extensions/101849/3 "2023-07-20T20:28:44Z")

</div>

Wouldn’t we need to say `export OneData` and `export TwoData` somewhere to make them visible to the user after they issue `using MainFoo` ? What I found is that exporting from the extension module doesn’t do anything and to export from `MainFoo` … well the structs need to be defined in `MainFoo`.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [July 20, 2023, 9:27pm UTC](https://discourse.julialang.org/t/package-extensions-structs-inside-extensions/101849/4 "2023-07-20T21:27:39Z")

</div>

Did you try? There’s nothing about `export` that need the exported variable to exist. You can just export a name and then only assign a value to that name when the extension is loaded

But I’ll also just repeat that I think what you’re asking to do is likely a bad idea. Why would you ever want the list of defined exported variables to change depending on where some package anywhere in the environment is loaded?

---

<div class="post-metadata">

**Author:** ![iabraham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iabraham/32/36532_2.png) [@iabraham](https://discourse.julialang.org/u/iabraham)\
**Post date:** [July 20, 2023, 9:49pm UTC](https://discourse.julialang.org/t/package-extensions-structs-inside-extensions/101849/5 "2023-07-20T21:49:59Z")

</div>

I did; and Julia can see the names because of the export in the main module but, it comes back undefined even though the extension is loaded and precompiled (as reported by the Package manager).

```julia
In [8]: using Cyclicity

In [9]: Cyclicity.

CyData ElData Scan areaval
cumul_area cycdiff eval include
make_lead_matrix match_ends mean_center minmax_pairs
quad_norm std_norm totvar_norm
In [9]: Cyclicity.ElData
ERROR: UndefVarError: `ElData` not defined
Stacktrace:
 [1] getproperty(x::Module, f::Symbol)
   @ Base ./Base.jl:31
 [2] top-level scope
   @ REPL[9]:1
 [3] top-level scope
   @ /Applications/Julia-1.9.app/Contents/Resources/julia/share/julia/stdlib/v1.9/REPL/src/REPL.jl:1416

In [10]: Cyclicity.CyData
ERROR: UndefVarError: `CyData` not defined
Stacktrace:
 [1] getproperty(x::Module, f::Symbol)
   @ Base ./Base.jl:31
 [2] top-level scope
   @ REPL[10]:1
 [3] top-level scope
   @ /Applications/Julia-1.9.app/Contents/Resources/julia/share/julia/stdlib/v1.9/REPL/src/REPL.jl:1416

```

In line 9 for example I am doing tab completion and you can see the two data types are there but only vacuously.

My use case is a bit hard to explain but TL;DR is basically the main module has a bunch of functions that have solid day-to-day use. I want that `Cyclicity` package to install in a jiffy and be all-around useful. However, there are some analysis steps that are in some sense natural extensions or deeper next steps on the results of the functions listed above; but for this … I have to make use of some nonlinear constrained optimization (`JuMP` and `Iopt`) packages. So … I only want those helper structs & functions to be loaded up if the user consciously installs these packages.

Maybe I am thinking of it wrong … not quite sure what right way to approach this in Julia might be.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [July 21, 2023, 7:47am UTC](https://discourse.julialang.org/t/package-extensions-structs-inside-extensions/101849/6 "2023-07-21T07:47:48Z")

</div>

I think the most direct way is through `get_extension`:

```julia
Base.get_extension(YourPackage, :AnotherPkgExt).YourType

```

If `YourType` is used a lot, user code can do

```julia
using YourPackage
using AnotherPkg

const YourType = Base.get_extension(YourPackage, :AnotherPkgExt).YourType

```

It’s not too convenient, but this is official documented functionality.  
When possible, it’s best to provide extension interface through methods to existing functions though.

---

<div class="post-metadata">

**Author:** ![Sole](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sole/32/202974_2.png) [@Sole](https://discourse.julialang.org/u/Sole)\
**Post date:** [November 4, 2023, 5:19pm UTC](https://discourse.julialang.org/t/package-extensions-structs-inside-extensions/101849/7 "2023-11-04T17:19:07Z")

</div>

we do need a more straight way to use functions and structures only defined in extension.
