# Associating information to a type

**URL:** <https://discourse.julialang.org/t/associating-information-to-a-type/34937>\
**Category:** General Usage\
**Created:** [February 20, 2020, 10:04pm UTC](https://discourse.julialang.org/t/associating-information-to-a-type/34937 "2020-02-20T22:04:35Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [February 20, 2020, 10:04pm UTC](https://discourse.julialang.org/t/associating-information-to-a-type/34937/1 "2020-02-20T22:04:35Z")

</div>

Consider

```julia
struct Foo
end

@is_friend(Foo, "Bob")
@is_friend(Foo, "Tim")

println(friends_of(Foo))

```

Is there a clean way of implementing `@is_friend` and `friends_of` to return `["Bob", "Tim"]`?

One solution is with a global `Dict`. Then `@is_friend` becomes `push!(that_dict[Foo], "Bob")` and `friends_of` is trivial. But that will Revise very poorly, and it doesn’t work with precompilation (unless I use `Requires.@init`, but ehhh…)

Another solution is for `@is_friend` to become `is_friend(::Type{Foo}, ::Val{"Bob"}) = true`. Then I can read the friend list off of `methods((Type{Foo}, Any,))`. That is Revise- and precompilation-friendly. But it’s a terrible solution… I guess?

Am I missing anything here? (Other than “You should rewrite your program in a different way”)

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [February 21, 2020, 3:14am UTC](https://discourse.julialang.org/t/associating-information-to-a-type/34937/2 "2020-02-21T03:14:01Z")

</div>

> [@cstjean](#):
>
> it doesn’t work with precompilation (unless I use `Requires.@init` , but ehhh…)

How about creating a module-local constant? That is to say, `@is_friend(Foo, "Bob")` is lowered to

```julia
if @isdefined(__friends)
    const __friends = Dict()
end
push!(get!(__friends, Foo, []), "Bob")

```

? This way, `__friends` can be stored in the precompilation cache.

Then we can look it up via `friends_of(Foo) = parentmodule(Foo).__friends[Foo]`. It’s probably a good idea to gensym `__friends`.

I don’t know how to make it Revise-friendly, though.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 21, 2020, 6:35am UTC](https://discourse.julialang.org/t/associating-information-to-a-type/34937/3 "2020-02-21T06:35:58Z")

</div>

I am not sure I understand the spec fully, but I would go with

```julia
is_friend(T, person) = person ∈ friends_of(T)

friends_of(::Type{Foo}) = Set("Bob", "Tim") # maintain list here

```

which is flexible and should be Revise-friendly.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [February 21, 2020, 7:35am UTC](https://discourse.julialang.org/t/associating-information-to-a-type/34937/4 "2020-02-21T07:35:20Z")

</div>

> [@Tamas\_Papp](#):
>
> which is flexible and should be Revise-friendly.

It’s not open. Suppose that instead of friends, I’m registering methods that should be called by `Foo` at some point. I’m stuck doing a big ugly `@register_all_methods Foo begin ... end` that contains all the methods in one big block. I have that solution already. `@big_macro_that_contains_complex_expansion_code_to_register_all_methods_from_dsl_code`. It’s not great. It would be much nicer and modular with a smaller `@declare_fruminating_method` macro that macroexpands into `@register_method Foo ...`

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [February 23, 2020, 6:05am UTC](https://discourse.julialang.org/t/associating-information-to-a-type/34937/5 "2020-02-23T06:05:21Z")

</div>

I found a decent solution using methods, after all: [ConferenceCall.jl](https://github.com/cstjean/ConferenceCall.jl)
