# Function as argument

**URL:** <https://discourse.julialang.org/t/function-as-argument/106385>\
**Category:** General Usage\
**Tags:** question\
**Created:** [November 17, 2023, 7:31pm UTC](https://discourse.julialang.org/t/function-as-argument/106385 "2023-11-17T19:31:45Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Domenico\_Lahaye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/domenico_lahaye/32/203728_2.png) [@Domenico\_Lahaye](https://discourse.julialang.org/u/Domenico_Lahaye)\
**Post date:** [November 17, 2023, 7:31pm UTC](https://discourse.julialang.org/t/function-as-argument/106385/1 "2023-11-17T19:31:45Z")

</div>

Please direct me to documentation on how to pass a function as argument to another function in type stable manner. Thx!

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [November 17, 2023, 8:01pm UTC](https://discourse.julialang.org/t/function-as-argument/106385/2 "2023-11-17T20:01:46Z")

</div>

There’s nothing special to do, just pass it.

---

<div class="post-metadata">

**Author:** ![Domenico\_Lahaye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/domenico_lahaye/32/203728_2.png) [@Domenico\_Lahaye](https://discourse.julialang.org/u/Domenico_Lahaye)\
**Post date:** [November 17, 2023, 8:38pm UTC](https://discourse.julialang.org/t/function-as-argument/106385/3 "2023-11-17T20:38:12Z")

</div>

Ah? When I pass as the function as argument, the code below does a lot of allocations.

Taking the function as global variable from main scope instead, makes allocations disappear.

Using @code\_warntype does not reveal any concerns.

I am missing something.

```julia
mySourceFct(x,y) = x+y 

function generateLocalVector(element::Element, sourceFct::Function)
    p1 = element.p1; p2 = element.p2; p3 = element.p3;  
    e1 = element.e1; e2 = element.e2; e3 = element.e3;  
    area = element.area 
    Iloc = SVector(e1, e2, e3) 
    # use broadcast for the lines below instead 
    f1 = area/3*sourceFct(p1.x,p1.y)
    f2 = area/3*sourceFct(p2.x,p2.y)
    f3 = area/3*sourceFct(p3.x,p3.y)
    floc = SVector(f1, f2, f3) 
    return Iloc, floc
end

function generateVector(mesh, sourceFct::Function)
 
    #..recover number of elements  
    N::Int64 = length(mesh.Elements)
    nnodes = mesh.nnodes 
     
    #..preallocate the memory for local matrix contributions 
    f = zeros(Float64,nnodes)

    for i = 1:N #..loop over number of elements..
        element::Element = mesh.Elements[i]
        Iloc, floc = generateLocalVector(element,sourceFct)
        f[Iloc] += floc 
    end
       
    return f; 
end

```

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [November 17, 2023, 8:45pm UTC](https://discourse.julialang.org/t/function-as-argument/106385/4 "2023-11-17T20:45:22Z")

</div>

[Check out this part of the performance tips](https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing).

This should be fixed by changing

```julia
function generateVector(mesh, sourceFct::Function)

```

to

```julia
function generateVector(mesh, sourceFct::F) where F

```

If there are still problems, you might need to make the same change to `generateLocalVector`, but that is _probably_ not needed because the function is called directly by it.

---

<div class="post-metadata">

**Author:** ![Domenico\_Lahaye](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/domenico_lahaye/32/203728_2.png) [@Domenico\_Lahaye](https://discourse.julialang.org/u/Domenico_Lahaye)\
**Post date:** [November 17, 2023, 8:58pm UTC](https://discourse.julialang.org/t/function-as-argument/106385/5 "2023-11-17T20:58:17Z")

</div>

Thx! Allocations are now indeed wiped out. Is compiler performance something to worry over here?

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [November 17, 2023, 9:40pm UTC](https://discourse.julialang.org/t/function-as-argument/106385/6 "2023-11-17T21:40:21Z")

</div>

I wouldn’t usually worry about the compiler in limited cases like this. The place where you might get in trouble is throwing a zillion different functions at this. Compiling with specialization for a handful (or even tens or maybe hundreds) of functions won’t be noticeable… but the runtime performance that the specializations provide certainly is!

Maybe somebody else can provide a more thorough commentary as to why this behavior is default. My understanding is that it’s very useful in situations, but this performance trap catches just about everyone sooner or later.

---

<div class="post-metadata">

**Author:** ![lrnv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lrnv/32/19373_2.png) [@lrnv](https://discourse.julialang.org/u/lrnv)\
**Post date:** [November 17, 2023, 11:43pm UTC](https://discourse.julialang.org/t/function-as-argument/106385/7 "2023-11-17T23:43:16Z")

</div>

Do I read the docs correctly if I understood that this non-specialisation of the outside method is happening because your are not actually using the function and just passing it through to the inside method ?

So that in the OP state of the code, the inner method indeed specializes on the function, but the outer one does not, and therefore cannot call the specialized inner one ?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [November 18, 2023, 1:47am UTC](https://discourse.julialang.org/t/function-as-argument/106385/8 "2023-11-18T01:47:55Z")

</div>

> [@lrnv](#):
>
> in the OP state of the code, the inner method indeed specializes on the function, but the outer one does not

Correct. Reminds me of a [past thread](https://discourse.julialang.org/t/performance-issue-due-to-function-as-an-argument/104093/10); TLDR yes this exception is unintuitive, but specializing on functions by default improves performance in uncommon situations yet severely bloats compilation of caller chains generally, and chained callee inlining can and often removes the caller chain _and_ nonspecialization issue for argument functions fixed at compile-time e.g. `foo(x, y) = map(+, x, y)`.
