# Given a Julia function \`f\` and its arguments \`agrs\` return typed Julia source code via a macro

**URL:** <https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947>\
**Category:** Internals & Design\
**Tags:** question\
**Created:** [July 12, 2020, 1:54pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947 "2020-07-12T13:54:56Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Impressium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/impressium/32/19575_2.png) [@Impressium](https://discourse.julialang.org/u/Impressium)\
**Post date:** [July 12, 2020, 1:54pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/1 "2020-07-12T13:54:56Z")

</div>

Is there a macro for that? Or is it possible to write one?

It’s always easier to understand via an example:

```julia
function f(x,y)
    a = sqrt(x)
    b = x*y
    return a + b
end

```

Macro call:

```julia
@get_typed_source_code f(1,2)
function f(x::Int64, y::Int64)::Float64
    a::Float64 = sqrt(x::Int64)
    b::Int64 = x::Int64 * y::Int64
    return a::Float64 + b::Int64
end

```

---

<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:** [July 12, 2020, 2:02pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/2 "2020-07-12T14:02:53Z")

</div>

Eg `@code_typed`?

---

<div class="post-metadata">

**Author:** ![Impressium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/impressium/32/19575_2.png) [@Impressium](https://discourse.julialang.org/u/Impressium)\
**Post date:** [July 12, 2020, 2:08pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/3 "2020-07-12T14:08:29Z")

</div>

Kind of, but not that low level. More like in the example above so that one can copy-past the generated julia source code

---

<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:** [July 12, 2020, 2:22pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/4 "2020-07-12T14:22:34Z")

</div>

It may be doable, but quite a few passes are done before the compiler types some code, so it would have to go back somehow to the original form.

I am curious about the use case.

---

<div class="post-metadata">

**Author:** ![Impressium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/impressium/32/19575_2.png) [@Impressium](https://discourse.julialang.org/u/Impressium)\
**Post date:** [July 12, 2020, 2:43pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/5 "2020-07-12T14:43:51Z")

</div>

Just exploring the language 🙂  
For beginners it’s much easier to read and explore Julia source code instead of the lowered Julia code. And sometimes one might want fully typed code.  
(And my boss is used to statically typed languages and what to type everything)

---

<div class="post-metadata">

**Author:** ![Impressium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/impressium/32/19575_2.png) [@Impressium](https://discourse.julialang.org/u/Impressium)\
**Post date:** [July 12, 2020, 2:46pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/6 "2020-07-12T14:46:33Z")

</div>

I think one might start in macros.jl with this piece of code

```julia
function gen_call_with_extracted_types( __module__ , fcn, ex0)
    if isa(ex0, Expr)
        if any(a->(Meta.isexpr(a, :kw) || Meta.isexpr(a, :parameters)), ex0.args)
            return quote
                local arg1 = $(esc(ex0.args[1]))
                local args, kwargs = $separate_kwargs($(map(esc, ex0.args[2:end])...))
                $(fcn)(Core.kwfunc(arg1),
                       Tuple{typeof(kwargs), Core.Typeof(arg1), map(Core.Typeof, args)...})
            end
        elseif ex0.head === :call
            return Expr(:call, fcn, esc(ex0.args[1]),
                        Expr(:call, typesof, map(esc, ex0.args[2:end])...))
        elseif ex0.head === :(=) && length(ex0.args) == 2
            lhs, rhs = ex0.args
            if isa(lhs, Expr)
                if lhs.head === :(.)
                    return Expr(:call, fcn, Base.setproperty!,
                                Expr(:call, typesof, map(esc, lhs.args)..., esc(rhs)))
                elseif lhs.head === :ref
                    return Expr(:call, fcn, Base.setindex!,
                                Expr(:call, typesof, esc(lhs.args[1]), esc(rhs), map(esc, lhs.args[2:end])...))
                end
            end
        elseif ex0.head === :vcat || ex0.head === :typed_vcat
            if ex0.head === :vcat
                f, hf = Base.vcat, Base.hvcat
                args = ex0.args
            else
                f, hf = Base.typed_vcat, Base.typed_hvcat
                args = ex0.args[2:end]
            end
            if any(a->isa(a,Expr) && a.head === :row, args)
                rows = Any[(isa(x,Expr) && x.head === :row ? x.args : Any[x]) for x in args ]
                lens = map(length, rows)
                return Expr(:call, fcn, hf,
                            Expr(:call, typesof,
                                 (ex0.head === :vcat ? [] : Any[esc(ex0.args[1])])...,
                                 Expr(:tuple, lens...),
                                 map(esc, vcat(rows...))...))
            else
                return Expr(:call, fcn, f,
                            Expr(:call, typesof, map(esc, ex0.args)...))
            end
        else
            for (head, f) in (:ref => Base.getindex, :hcat => Base.hcat, :(.) => Base.getproperty, :vect => Base.vect, Symbol("'") => Base.adjoint, :typed_hcat => Base.typed_hcat, :string => string)
                if ex0.head === head
                    return Expr(:call, fcn, f,
                                Expr(:call, typesof, map(esc, ex0.args)...))
                end
            end
        end
    end
    if isa(ex0, Expr) && ex0.head === :macrocall # Make @edit @time 1+2 edit the macro by using the types of the *expressions*
        return Expr(:call, fcn, esc(ex0.args[1]), Tuple{#= __source__ =#LineNumberNode, #= __module__ =#Module, Any[Core.Typeof(a) for a in ex0.args[3:end] ]...})
    end

    ex = Meta.lower( __module__ , ex0)
    if !isa(ex, Expr)
        return Expr(:call, :error, "expression is not a function call or symbol")
    end

    exret = Expr(:none)
    if ex.head === :call
        if any(e->(isa(e, Expr) && e.head === :(...)), ex0.args) &&
            (ex.args[1] === GlobalRef(Core,:_apply) ||
             ex.args[1] === GlobalRef(Base,:_apply))
            # check for splatting
            exret = Expr(:call, ex.args[1], fcn,
                        Expr(:tuple, esc(ex.args[2]),
                            Expr(:call, typesof, map(esc, ex.args[3:end])...)))
        else
            exret = Expr(:call, fcn, esc(ex.args[1]),
                         Expr(:call, typesof, map(esc, ex.args[2:end])...))
        end
    end
    if ex.head === :thunk || exret.head === :none
        exret = Expr(:call, :error, "expression is not a function call, "
                                  * "or is too complex for @$fcn to analyze; "
                                  * "break it down to simpler parts if possible")
    end
    return exret
end

```

Unfortunately I’m not able to understand it yet 😂

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [July 12, 2020, 2:48pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/7 "2020-07-12T14:48:04Z")

</div>

No, this is currently not possible, see:

[https://github.com/JuliaLang/julia/issues/2625](https://github.com/JuliaLang/julia/issues/2625)

Edit: this is only regarding extracting the original source code, without any type information.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [July 12, 2020, 2:49pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/8 "2020-07-12T14:49:54Z")

</div>

you can use `@edit` to have the source code pop up in a text editor.

---

<div class="post-metadata">

**Author:** ![Impressium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/impressium/32/19575_2.png) [@Impressium](https://discourse.julialang.org/u/Impressium)\
**Post date:** [July 12, 2020, 2:57pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/9 "2020-07-12T14:57:58Z")

</div>

Who do I use it?

```julia
julia> using Revise

julia> Revise.@edit
ERROR: LoadError: UndefVarError: @edit not defined
in expression starting at REPL[53]:1

```

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [July 12, 2020, 2:59pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/10 "2020-07-12T14:59:54Z")

</div>

`@edit` is not in `Revise`, it’s in `InteractiveUtils`, so it should already be imported in the `REPL`.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [July 12, 2020, 3:00pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/11 "2020-07-12T15:00:46Z")

</div>

Make sure you know how to do `julia> ?@edit` in the REPL to see the documentation. In this case you write

```julia
julia> @edit println("hey")

```

---

<div class="post-metadata">

**Author:** ![Impressium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/impressium/32/19575_2.png) [@Impressium](https://discourse.julialang.org/u/Impressium)\
**Post date:** [July 12, 2020, 3:02pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/12 "2020-07-12T15:02:53Z")

</div>

But how would I use this to get typed Julia source code?

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [July 12, 2020, 3:16pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/13 "2020-07-12T15:16:10Z")

</div>

Oh, sorry, I might have misunderstood your original question. In Julia, expressions don’t have any types. The way the compiler works, your code is first lowered into an intermediate representation (IR), which turns loops and conditionals into gotos, handles fused broadcasting, etc. This is also where tools like Cassette and IRTools operate at. Type inference is then done only on this IR code and you can see what this results in with `@code_typed`. This means that you can’t really ask Julia for typed Julia code, because that’s not how the compiler works and may not always be well-posed. I would just try to experiment with `@code_typed` a bit, since it can be really useful for getting a feeling for where type instabilities occur.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 12, 2020, 3:16pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/14 "2020-07-12T15:16:59Z")

</div>

It’s unrelated. And the link in [Given a Julia function `f` and its arguments `agrs` return typed Julia source code via a macro - #7 by simeonschaub](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/7) isn’t related either.

> [@Impressium](#):
>
> And sometimes one might want fully typed code.  
> (And my boss is used to statically typed languages and what to type everything)

Just don’t…

---

<div class="post-metadata">

**Author:** ![Impressium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/impressium/32/19575_2.png) [@Impressium](https://discourse.julialang.org/u/Impressium)\
**Post date:** [July 12, 2020, 3:17pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/15 "2020-07-12T15:17:56Z")

</div>

Haha 😂

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [July 12, 2020, 3:20pm UTC](https://discourse.julialang.org/t/given-a-julia-function-f-and-its-arguments-agrs-return-typed-julia-source-code-via-a-macro/42947/16 "2020-07-12T15:20:54Z")

</div>

> [@Impressium](#):
>
> And sometimes one might want fully typed code.  
> (And my boss is used to statically typed languages and what to type everything)

OP I think the real solution here is to accept that Julia has dynamic elements, in that you can write duck-typed code at a high level and it will still be performant. I would suggest do `@code_warntype` a bunch and fixing you see `Any` pop up. It’s not perfect but it’s more in the spirit of writing “julian” code where you don’t nail down all the types all the time.
