# Does julia have a construct analogous to Racket's parameters?

**URL:** https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658
**Category:** General Usage
**Created:** [June 10, 2021, 7:39am UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658 "2021-06-10T07:39:21Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)
#### Post date: [June 10, 2021, 7:39am UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/1 "2021-06-10T07:39:21Z")

</div>

Racket has this cool thing where you can define implicit values called parameters: [4.13&nbsp;Dynamic Binding: parameterize](https://docs.racket-lang.org/guide/parameterize.html). Is there anything analogous in julia?

For example, it would be convenient in the implementation of things random number generators to give the feeling of having ethereal globals, while in reality offering the programmer more control and healthy scoping rules.

Eg,

```julia
# Reach into the either and pull out the `rng` parameter.
foo(x) = randn(@getparam :rng) * 3 + x

# Provide a value for the `rng` parameter but only in the context of this scope.
@provideparam rng = MersenneTwister(...) in begin
  foo(12)
end

```

---

<div class="post-metadata">

### Author: ![xiaodai](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xiaodai/32/15937_2.png) [@xiaodai](https://discourse.julialang.org/u/xiaodai)
#### Post date: [June 10, 2021, 7:41am UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/2 "2021-06-10T07:41:35Z")

</div>

First thought is, what’s the advantage of doing this vs passing in an explicit random seed?

---

<div class="post-metadata">

### Author: ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)
#### Post date: [June 10, 2021, 8:33am UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/3 "2021-06-10T08:33:36Z")

</div>

Well this has the advantage that you can interop with third-party code that doesn’t know anything about random seeds. But my use case is a bit more interesting anyhow. I have a custom numeric type `Foo` and it contains a reference to a “semi-global” `World` object:

```julia
struct Foo
  world # pointer to something interesting and contextual
  value # just a Float64 perhaps
end

```

Now I’d like to use this with a library like IntervalAnalysis.jl where the lower/upper bounds of my `Interval`s are `Foo`s… But IntervalAnalysis.jl calls `zero()` internally. Now the question is how do I implement `zero(::Type{Foo})`?

With something like parameters I could do:

```julia
mkFoo(x) = Foo(@getparam :world, x)
zero(::Type{Foo}) = mkFoo(0.0)

@provideparam world = World(...) in begin
  # My codebase: set up some Foo's, etc
  x = mkFoo(3)
  y = mkFoo(5)

  # Third-party code: use IntervalAnalysis.jl
  interval(x, y)
  ...
end

# And outside the scope, if the paramter isn't provided...
mkFoo(7)
# error: no value provided for parameter `world`

```

---

<div class="post-metadata">

### Author: ![xiaodai](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xiaodai/32/15937_2.png) [@xiaodai](https://discourse.julialang.org/u/xiaodai)
#### Post date: [June 10, 2021, 11:07am UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/4 "2021-06-10T11:07:20Z")

</div>

> [@Samuel\_Ainsworth](#):
>
> `pointer to something interesting and contextual`

interesting. I think using Cassette.jl and overdub you can achieve something like this.

---

<div class="post-metadata">

### Author: ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)
#### Post date: [June 10, 2021, 12:16pm UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/5 "2021-06-10T12:16:17Z")

</div>

This is an interesting idea and probably Casette.jl or IRTools.jl is the best way to solve it.

On the other hand, to some extent it can be solved with usual macros (sorry, I am just thinking aloud, not sure if its doable in reality).

Idea is that your code roughly equivalent to

```julia
struct Foo
  world # pointer to something interesting and contextual
  value # just a Float64 perhaps
end

let world = "hello"
    mkFoo(x) = Foo(world, x)
    println(mkFoo(1))
end

```

i.e. if we create closure inside `let` block, than we are good to go. Of course, your example use function declaration outside of `let` block, in which case you can’t declare closure.

What can be done, is “storing” closure declaration somewhere and applying it afterwards, so for the end user, it looks like

```julia
@with_context world mkFoo(x) = Foo(world, x)

@in_context world = World(...) begin
  x = mkFoo(3)
  y = mkFoo(5)
...
end

```

And macro `@in_context` should generate these lines

```julia
let world = World(...) begin
  mkFoo(x) = mkFoo(world, x) # substitute from @with_context declaration

```

Of course, it’s very quickly became rather complicated: what should we do if we have more than one context? How can we decide which functions to use? And what can we do with nested `@in_context`?

So it looks like that building full scaled implementation in this approach is too complicated, but limited versions could exist.

---

<div class="post-metadata">

### Author: ![ggggggggg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ggggggggg/32/265_2.png) [@ggggggggg](https://discourse.julialang.org/u/ggggggggg)
#### Post date: [June 10, 2021, 3:47pm UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/6 "2021-06-10T15:47:55Z")

</div>

What about

```julia
julia> struct Foo{World} 
       value
       end

julia> Base.zero(x::Foo{W}) where W = Foo{W}(0)

julia> zero(Foo{1}(10))
Foo{1}(0)

```

---

<div class="post-metadata">

### Author: ![PabloZubieta](https://avatars.discourse-cdn.com/v4/letter/p/ee7513/32.png) [@PabloZubieta](https://discourse.julialang.org/u/PabloZubieta)
#### Post date: [June 10, 2021, 6:19pm UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/7 "2021-06-10T18:19:03Z")

</div>

I’m guessing that if he needed to handle a collection of `Foo`s in some cases he might want to keep homogeneity to avoid type instabilities, so a parameterized `Foo` would make him loose that.

---

<div class="post-metadata">

### Author: ![melonedo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/melonedo/32/15503_2.png) [@melonedo](https://discourse.julialang.org/u/melonedo)
#### Post date: [June 12, 2021, 9:54am UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/8 "2021-06-12T09:54:08Z")

</div>

Really interesting!  
This smells like the classical factory pattern in the OOP world:  
Assume `Derived <: Base`, if function that works for `Base` also wants to work for `Derived`, it must create intermediate values of type `Derived`. To achieve this, we explicitly pass a constructor function that creates `Derived` instances. Here, you which to customize what kind of `Foo` is constructed, which could be interpreted as “subtyping” in a more general sense.

If an explicit constructor is not possible, `Foo{world}` does the trick.

However, in julia, `zero(T)` does not need to return exactly `T`. Assume the meaning of zero is independent of context, you can define a `ZeroFoo` type that represent the meaning of zero, regardless of the context.

---

<div class="post-metadata">

### Author: ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)
#### Post date: [June 13, 2021, 6:33am UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/9 "2021-06-13T06:33:51Z")

</div>

> [@melonedo](#):
>
> If an explicit constructor is not possible, `Foo{world}` does the trick.

This would be very nice! I’m not sure how to make it work in Julia, but this may be due to my own ignorance. The `World` type is effectively defined as

```julia
struct World
  xs::Array{Int64} # not actually Int64, but you get the idea
end

```

And thus far Julia has not allowed me to pass such things in as type parameters.

> [@melonedo](#):
>
> However, in julia, `zero(T)` does not need to return exactly `T` . Assume the meaning of zero is independent of context, you can define a `ZeroFoo` type that represent the meaning of zero, regardless of the context.

Ah… this could work. It would require a little refactor, but this may be the way to go…

---

<div class="post-metadata">

### Author: ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)
#### Post date: [June 13, 2021, 8:39am UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/10 "2021-06-13T08:39:14Z")

</div>

Sounds like the `ZeroFoo` thing may be the cleaner solution, but the original question is interesting and maybe worth pointing out that as long as your code is single-task, it can be done pretty cleanly with `Base.task_local_storage`:

```julia
foo(x) = randn(Base.task_local_storage(:rng)) * 3 + x

Base.task_local_storage(:rng, MersenneTwister(1)) do
  foo(12)
end

```

(And for asynchronous code, the question may be kind of ambiguous anyway, e.g. what should happen if the code inside `@provideparam` spawns code which runs after you’ve exited the block)

---

<div class="post-metadata">

### Author: ![melonedo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/melonedo/32/15503_2.png) [@melonedo](https://discourse.julialang.org/u/melonedo)
#### Post date: [June 14, 2021, 7:34am UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/11 "2021-06-14T07:34:46Z")

</div>

> [@Samuel\_Ainsworth](#):
>
> And thus far Julia has not allowed me to pass such things in as type parameters.

But this is julia and you can pass a function as type parameter (which seems to be abusing and may not be recommended in general):

```julia
struct Foo{world_func} # world_func() returns whatever you like
  value
end
value(x::Foo) = x.value
world(x::Foo{f}) where f = f() # instead of x.world

```

Note: this is a generalization of the solution @ggggggggg has provided.

---

<div class="post-metadata">

### Author: ![melonedo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/melonedo/32/15503_2.png) [@melonedo](https://discourse.julialang.org/u/melonedo)
#### Post date: [June 16, 2021, 5:51am UTC](https://discourse.julialang.org/t/does-julia-have-a-construct-analogous-to-rackets-parameters/62658/12 "2021-06-16T05:51:29Z")

</div>

Oh I see, if you do not need thread safety, this can be easily implemented:

```julia
const global_params = Dict{Symbol, Any}()

function parameterize(f; params...)
    old_values = []
    for (k, v) in params
        push!(old_values, get(global_params, k, missing))
        global_params[k] = v
    end
    try
        f()
    finally
        for ((k, _), v) in zip(params, old_values)
            if ismissing(v)
                delete!(global_params, k)
            else
                global_params[k] = v
            end
        end
    end
end

get_parameter(key::Symbol) = global_params[key]

macro get_parameter(key::Symbol)
    :(get_parameter($(Meta.quot(key))))
end

make_parameter(key::Symbol, value) = global_params[key] = value

function make_parameter(; params...)
    for (k, v) in params
        make_parameter(k, v)
    end
end

```

Usage:

```julia
make_parameter(a=1)
println(get_parameter(:a)) # 1

f = parameterize(a=2, b=3) do
    @show get_parameter(:a)
    @show @get_parameter b
    x -> x + @get_parameter a
end
f(1) # 2

```
