# Metaprogramming

**URL:** <https://discourse.julialang.org/t/metaprogramming/26225>\
**Category:** New to Julia\
**Created:** [July 10, 2019, 3:27pm UTC](https://discourse.julialang.org/t/metaprogramming/26225 "2019-07-10T15:27:53Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![stu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stu/32/8772_2.png) [@stu](https://discourse.julialang.org/u/stu)\
**Post date:** [July 10, 2019, 3:27pm UTC](https://discourse.julialang.org/t/metaprogramming/26225/1 "2019-07-10T15:27:54Z")

</div>

Hello,  
(Apologies for the long post, issue is not that complex, I was just trying to be descriptive to make understanding it easier)  
As I understand it, metaprogramming is the tool that will help me achieve my objective.  
Specifically, what I am trying to accomplish is to write a macro that returns a string or some other sequence of characters that are not actually a string but rather are code and I can directly plop that code as the input to another function, not in the sense that I am defining a variable and passing in that variable to the function but rather that the programming is returning what I would be writing myself into the function.

I will provide an example

```julia
@macro foo()
  #some code
end

vcat(@macro foo())

```

so say for example I wanted vcat to concatenate an arbitrary but specific number of arguments that all have different names.

Thus, I could not just return them as an array because vcat will not operate on an array of inputs. I could provide the input as a tuple of arrays but that fails for my purposes because what I am trying to vertically concatenate are functions and not arrays and thus I need to pass them in within the context of an anonymous function. Thus, I have to pass in the function names with (x) appended onto the end of them.  
For example, it would need to look like that:

```julia
fooy = x -> vcat(foo1(x), foo2(x))

```

Now it would be easy to use a for loop and construct a string that exactly replicates the input that I would want in vcat(here) but obviously such a function would return a string and not code that I can just pass into the function in the same way as if I were to manually type that code into the parameter of vcat. This is why I suspect I need to use metaprogramming. As understand it, it would allow me to do things like this where I can have results that are julia code and not types like Strings, etc.

Is there anyone that knows how to do this?

so far I have used the following code (note this is a bit simplified so that it is easier to follow):

```julia
#the function I am trying to vertically concatenate
circ(x) = x./sqrt(sum(x .* x))
for i in 1:n_circs1
      @eval $(Symbol("encoderbottle_$i")) = circ
end

```

and this code creates a variables encoderbottle\_1 to encoderbottle\_n\_circs1 (where n\_circs1 is an integer and not actually n\_circs1).

What this code means is that I dont have to worry about createing the variables, I just need to write a macro that creates the following Julia code:

```julia
encoderbottle_1(x), encoderbottle_2(x), ... encoderbottle_n_circs1(x)

```

(obviously without the … and the appropriate remainder of the pattern in place)  
and then I can just plop that julia code (not plop is my word and not a technical term i dont think) into the args for the vcat function.

Any help with how to do this would be much appreciated since I still do not fully understand macros in Julia.

Thank you.

---

<div class="post-metadata">

**Author:** ![ElOceanografo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eloceanografo/32/624_2.png) [@ElOceanografo](https://discourse.julialang.org/u/ElOceanografo)\
**Post date:** [July 10, 2019, 6:59pm UTC](https://discourse.julialang.org/t/metaprogramming/26225/2 "2019-07-10T18:59:53Z")

</div>

I’m not totally clear on what your end goal is here, but a couple of points which may be helpful…I suspect you don’t actually need a macro to accomplish what you want. First, you can pass an array to `vcat`, you just need to use the `...` operator to “splat” them into individual arguments:

```julia
foo = 1
bar = [2, 3, 4]
baz = [5, 6]
vcat([foo, bar, baz]...)

```

This also works with functions:

```julia
funclist = [[sin, cos], [+, -], [exp, sqrt]]
vcat(funclist...)

```

Second point: as you’re defining them, your `encoderbottle_n` variables all refer to the same function (`circ`), so they all do the exact same thing…is your actual, non-simplified loop defining each one to do something different?

---

<div class="post-metadata">

**Author:** ![stu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stu/32/8772_2.png) [@stu](https://discourse.julialang.org/u/stu)\
**Post date:** [July 10, 2019, 7:06pm UTC](https://discourse.julialang.org/t/metaprogramming/26225/3 "2019-07-10T19:06:46Z")

</div>

> [@ElOceanografo](#):
>
> Second point: as you’re defining them, your `encoderbottle_n` variables all refer to the same function ( `circ` ), so they all do the exact same thing…is your actual, non-simplified loop defining each one to do something different?

Correct, the non-simplified loop defines each one too be something different.

---

<div class="post-metadata">

**Author:** ![stu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stu/32/8772_2.png) [@stu](https://discourse.julialang.org/u/stu)\
**Post date:** [July 10, 2019, 7:09pm UTC](https://discourse.julialang.org/t/metaprogramming/26225/4 "2019-07-10T19:09:10Z")

</div>

> [@ElOceanografo](#):
>
> funclist = [[sin, cos], [+, -], [exp, sqrt]] vcat(funclist…)

The problem with this is that the result is an array and not a new function

---

<div class="post-metadata">

**Author:** ![stu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stu/32/8772_2.png) [@stu](https://discourse.julialang.org/u/stu)\
**Post date:** [July 10, 2019, 7:11pm UTC](https://discourse.julialang.org/t/metaprogramming/26225/5 "2019-07-10T19:11:07Z")

</div>

For example, take a look at the following code:

```julia
funclist = [[+, +], [+, -], [-, -]]
3-element Array{Array{Function,1},1}:
 [+, +]
 [+, -]
 [-, -]

julia> m = vcat(funclist...)
6-element Array{Function,1}:
 +
 +
 +
 -
 -
 -

julia> m(rand(6))
ERROR: MethodError: objects of type Array{Function,1} are not callable
Use square brackets [] for indexing an Array.
Stacktrace:
 [1] top-level scope at none:0

```

I need to be able to pass in an array that executes on the respective function at varying inputs as is the case when you use the m(x) = vcat(circ(x), circ(x)) format

Thus, if you define it in the way m(x) = vcat(circ(x), circ(x))

you can call m(rand(2)) and it will return an array with 4 ints that are the result of applying the input to the vertically concatenated functions.

---

<div class="post-metadata">

**Author:** ![stu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stu/32/8772_2.png) [@stu](https://discourse.julialang.org/u/stu)\
**Post date:** [July 10, 2019, 7:13pm UTC](https://discourse.julialang.org/t/metaprogramming/26225/6 "2019-07-10T19:13:31Z")

</div>

Thus, if you define it in the way m(x) = vcat(circ(x), circ(x))

you can call m(rand(2)) and it will return an array with 4 ints that are the result of applying the input to the vertically concatenated functions.

---

<div class="post-metadata">

**Author:** ![ElOceanografo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eloceanografo/32/624_2.png) [@ElOceanografo](https://discourse.julialang.org/u/ElOceanografo)\
**Post date:** [July 10, 2019, 7:31pm UTC](https://discourse.julialang.org/t/metaprogramming/26225/7 "2019-07-10T19:31:29Z")

</div>

So backing up a second, IIUC you have _N_ functions and _N_ inputs, and you want to apply the _nth_ function to the _nth_ input? If so, you could use a comprehension:

```julia
funclist = [[+, +], [+, -], [-, -]]
m = vcat(funclist...)
args = rand(6)
[f(a) for (f, a) in zip(m, args)]

```

Or, equivalently,

```julia
map.(m, args)

```

If you want a single function that calls everything, you can just define it yourself:

```julia
calleverything(args) = map.(m, args)
calleverything(randn(6))

```
