# Isbits functions with parameter arguments

**URL:** <https://discourse.julialang.org/t/isbits-functions-with-parameter-arguments/25397>\
**Category:** General Usage\
**Tags:** gpu\
**Created:** [June 18, 2019, 10:16am UTC](https://discourse.julialang.org/t/isbits-functions-with-parameter-arguments/25397 "2019-06-18T10:16:14Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![fedoroff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fedoroff/32/53209_2.png) [@fedoroff](https://discourse.julialang.org/u/fedoroff)\
**Post date:** [June 18, 2019, 10:16am UTC](https://discourse.julialang.org/t/isbits-functions-with-parameter-arguments/25397/1 "2019-06-18T10:16:14Z")

</div>

Imagine, I have a function that depends on some parameters, like step functions in DIfferentialEuations.jl. I would like to define these parameters once and avoid passing them as arguments at every function call. As a solution I can use function-like objects:

```julia
struct PFunction <: Function
    func :: Function
    p :: Tuple
end

function (pfunc::PFunction)(x...)
    pfunc.func(x..., pfunc.p)
end

function foo(x, y, p)
    a, b = p
    return a * x + b * y
end

p1 = (1, 2)
pfoo1 = PFunction(foo, p1)

p2 = (3, 4)
pfoo2 = PFunction(foo, p2)

@show pfoo1(1, 1)
@show pfoo2(1, 1)

```

```julia
pfoo1(1, 1) = 3
pfoo2(1, 1) = 7

```

Thus, my goal is reached: instead of calling foo as foo(x, y, p), I can use just pfoo(x, y).

However, since the type of PFunction is not isbits type, I can not use such objects in CUDA kernels. Can you please suggest any solution that will allow me to obtain the same functions behavior inside CUDA kernels. I guess, I need to look towards metaprogramming, but I have no experience with macros so far.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [June 18, 2019, 10:27am UTC](https://discourse.julialang.org/t/isbits-functions-with-parameter-arguments/25397/2 "2019-06-18T10:27:00Z")

</div>

How about:

```julia
julia> struct PFunction{T<:Tuple} <: Function
       p::T
       end

julia> function (pfunc::PFunction)(x,y)
         foo(x, y, pfunc.p)
       end

julia> function foo(x, y, p)
           a, b = p
           return a * x + b * y
       end
foo (generic function with 1 method)

julia> p1 = (1, 2)
(1, 2)

julia> pfoo1 = PFunction(p1)
(::PFunction{Tuple{Int64,Int64}}) (generic function with 1 method)

julia> pfoo1(1,1)
3

julia> isbits(pfoo1)

```

Note, that the type-parameter of `PFunction` is needed to make it isbits, as `Tuple` is not a concrete type.

---

<div class="post-metadata">

**Author:** ![fedoroff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fedoroff/32/53209_2.png) [@fedoroff](https://discourse.julialang.org/u/fedoroff)\
**Post date:** [June 18, 2019, 10:51am UTC](https://discourse.julialang.org/t/isbits-functions-with-parameter-arguments/25397/3 "2019-06-18T10:51:42Z")

</div>

Oh, thank you very much! With your approach even the original code seems to work:

```julia
struct PFunction{F<:Function, T<:Tuple} <: Function
    func :: F
    p :: T
end

function (pfunc::PFunction)(x...)
    pfunc.func(x..., pfunc.p)
end

function foo(x, y, p)
    a, b = p
    return a * x + b * y
end

p = (1, 2)
pfoo = PFunction(foo, p)

@show pfoo(1, 1)
@show isbits(pfoo)

```

```julia
pfoo(1, 1) = 3
isbits(pfoo) = true

```

Now I have to understand why type-parameters work this way. Looks a bit counterintuitive to me.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [June 18, 2019, 11:25am UTC](https://discourse.julialang.org/t/isbits-functions-with-parameter-arguments/25397/4 "2019-06-18T11:25:17Z")

</div>

Ok, I assumed that functions are not isbits, but they are and thus parameterizing them works.

See [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-fields-with-abstract-type-1)

---

<div class="post-metadata">

**Author:** ![fedoroff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fedoroff/32/53209_2.png) [@fedoroff](https://discourse.julialang.org/u/fedoroff)\
**Post date:** [June 18, 2019, 12:02pm UTC](https://discourse.julialang.org/t/isbits-functions-with-parameter-arguments/25397/5 "2019-06-18T12:02:06Z")

</div>

Thank you. Now its clear.
