# Bridge the gap, please! (from Matlab to Julia)

**URL:** <https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549>\
**Category:** New to Julia\
**Created:** [June 25, 2021, 1:24pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549 "2021-06-25T13:24:07Z")\
**Posts on this page:** 20\
**Page:** 2

<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:** [June 26, 2021, 10:43pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/21 "2021-06-26T22:43:40Z")

</div>

Sorry a few notes as well,

you shouldn’t benchmark in global scope, you have to put things in functions for benchmark timings to be accurate. You can read about this more in the [performance tips](https://docs.julialang.org/en/v1/manual/performance-tips/) in the docs.

Some of the slow timing in your code is because you are re-defining a function over and over again, which causes re-compilation in global scope but not (I think) inside a function. But I’m not sure and you should explore this more.

Here is a benchmark:

```julia
julia> struct B{T}
           par::Vector{T}
       end;

julia> function operate(f, a::B)
           f(a.par)
       end;

julia> function foo(n) # you need to benchmark in a function
           for i in 1:n
               if randn() > 0
                   b = B(randn(2))
                   f = sum
               else
                   b = B(rand(3))
                   f = prod
               end
               operate(f, b)
           end
       end;

julia> n = 1e3;

julia> @btime foo($n);
  55.096 μs (1000 allocations: 100.56 KiB)

```

But to be honest, I’m not 100% sure this is the correct. The variable `f` is “changing type” based off of a non-deterministic even (the `rand` call), since all functions are typed on their own. But on the other hand the `operate` call creates a function barrier so maybe it works itself out. Hopefully someone more informed can chime in.

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [June 27, 2021, 6:23am UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/22 "2021-06-27T06:23:54Z")

</div>

```julia
# create, store and evaluate random functions with random parameters

function as_tuple(n)
    println("as tuple")
    for i = 1:n
        if randn() > 0
            e = (prod, [randn(2)])
        else
            e = (sum, [randn(3)])
        end
        e[1](e[2])
    end
end

function as_array(n)
    println("as array")
    for i = 1:n
        if randn() > 0
            e = [prod, [randn(2)]]
        else
            e = [sum, [randn(3)]]
        end
        e[1](e[2])
    end
end

struct B{T}
    par::Vector{T}
end;
function operate(f, a::B)
    f(a.par)
end;
function as_function(n)
    println("as function")
    for i in 1:n
        if randn() > 0
            f = prod
            b = B(randn(2))
        else
            f = sum
            b = B(rand(3))
        end
        # operate(f, b) # have to add pack/store/unpack
        fb = (f, b)
        operate(fb[1], fb[2]) 
        # fb[1](fb[2]) # does NOT work, why?
    end
end

function run_tests(n)
    @time as_array(n)
    @time as_tuple(n)
    @time as_function(n)
end

run_tests(1e6)

```

```julia
as array
  0.339309 seconds (4.00 M allocations: 297.555 MiB, 7.22% gc time)
as tuple
  0.295214 seconds (3.00 M allocations: 206.005 MiB, 5.65% gc time)
as function
  0.210576 seconds (1.00 M allocations: 99.173 MiB, 7.51% gc time)

```

My takeaway:  
“Think julian” == think in functions, tell the compiler about stable type layout and relations.  
Here, we say that f is a function and b (a.par) is a Vector, to be used as its parameters

Still a way to go to understand why

```julia
fb[1](fb[2]) 

```

throws

```julia
ERROR: LoadError: MethodError: no method matching iterate(::B{Float64})
Closest candidates are:
  iterate(::Union{LinRange, StepRangeLen}) at range.jl:664
  iterate(::Union{LinRange, StepRangeLen}, ::Int64) at range.jl:664
  iterate(::T) where T<:Union{Base.KeySet{var"#s79", var"#s78"} where {var"#s79", var"#s78"<:Dict}, Base.ValueIterator{var"#s77"} where var"#s77"<:Dict} 
at dict.jl:693

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 27, 2021, 6:55am UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/23 "2021-06-27T06:55:56Z")

</div>

> [@Bardo](#):
>
> Still a way to go to understand why
> 
> ```julia
> fb[1](fb[2]) 
> 
> ```
> 
> throws

It’s because your `B` struct is not an iterable. It just _wraps_ a container. `prod` and `sum` iterate over their argument, so if you want to use them with your struct, you have to [implement the `iterate` interface](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration) for your struct.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 27, 2021, 7:06am UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/24 "2021-06-27T07:06:29Z")

</div>

> [@Bardo](#):
>
> `fb[1](fb[2])`

Should be

```julia
fb[1](fb[2].par)

```

Another way is to define

```julia
Base.sum(b::B) = sum(b.par)

```

Although the the “operate” approach is perfectly fine and more general.

---

<div class="post-metadata">

**Author:** ![jovansam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jovansam/32/15023_2.png) [@jovansam](https://discourse.julialang.org/u/jovansam)\
**Post date:** [June 27, 2021, 8:53am UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/25 "2021-06-27T08:53:47Z")

</div>

Some resources you will find helpful, if you are transitioning especially from Matlab.

1. [julia quant-econ](https://julia.quantecon.org/)
2. [techytok](https://techytok.com/)
3. [julia wiki](https://en.wikibooks.org/wiki/Introducing_Julia)
4. Translate code while making use of discourse, stackoverflow. At first, this annoying as productivity takes a hit but soon you appreciate the move.

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [June 27, 2021, 11:09am UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/26 "2021-06-27T11:09:15Z")

</div>

Thx!

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [June 27, 2021, 5:01pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/27 "2021-06-27T17:01:00Z")

</div>

Now happy with my solution below. Suggestions always welcome!

```julia
using Base: Float64

# store and evaluate randomly functions with different number of parameters

mutable struct MyStruct
    a::Float64
    b::Float64
end
s1 = MyStruct(1.0, 2.0)

fun1(x) = sin(x)
fun2(x,y) = cos(x) + y
function fun3(x,y,s1)
    s1.b = s1.a*(cos(x) + y)
end
function meval(cmd)
    len = length(cmd)
    if len == 2
        z = cmd[1](cmd[2])
        return
    end
    if len == 3
        z = cmd[1](cmd[2], cmd[3])
        return
    end
    if len == 4
        z = cmd[1](cmd[2], cmd[3], cmd[4])
        return
    end
end

function test1(n)
    for i = 1:n
        if randn() > 0
            cmd = (fun1, randn())
        else
            cmd = (fun3, randn(), randn(), s1)
        end
        meval(cmd)
    end
end

function run_tests(n)
    @time test1(n)
end

run_tests(1e6)

```

```julia
0.330759 seconds (2.01 M allocations: 39.025 MiB, 2.81% gc time, 5.33% compilation time)

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 27, 2021, 6:15pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/28 "2021-06-27T18:15:39Z")

</div>

Maybe you could tell us what is that you don’t like about the suggestion of @pdeffebach, which is simpler and more general. (Also you are using s1 as a global variable there, which will hurt performance).

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 27, 2021, 7:49pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/29 "2021-06-27T19:49:51Z")

</div>

> [@Bardo](#):
>
> `using Base: Float64`

You don’t have to import `Float64`, it’s available by default.

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [June 27, 2021, 7:50pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/30 "2021-06-27T19:50:51Z")

</div>

This was added by Julia or VS Code

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [June 27, 2021, 7:53pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/31 "2021-06-27T19:53:13Z")

</div>

Nothing to dislike, I only failed to apply it to the heterogenous case of fun3.  
I someone of you succeeds…

```julia
using Base: Float64

# create, store and evaluate random functions with random parameters

mutable struct MyStruct
    a::Float64
    b::Float64
end
s1 = MyStruct(1.0, 2.0)

fun1(x) = sin(x)
fun2(x,y) = cos(x) + y
function fun3(x,y,s1)
    s1.b = s1.a*(cos(x) + y)
end
function meval(cmd)
    len = length(cmd)
    if len == 2
        z = cmd[1](cmd[2])
        return
    end
    if len == 3
        z = cmd[1](cmd[2], cmd[3])
        return
    end
    if len == 4
        z = cmd[1](cmd[2], cmd[3], cmd[4])
        return
    end
end

function test1(n)
    for i = 1:n
        if randn() > 0
            cmd = (fun1, randn())
        else
            cmd = (fun3, randn(), randn(), s1)
        end
        meval(cmd)
    end
end

struct B{T}
    par::Vector{T}
end;
function operate(f, a::B)
    f(a.par)
end
function test2(n)
    for i = 1:n
        if randn() > 0
            #cmd = (fun1, randn())
            fb = (fun1, B(randn))
        else
            #cmd = (fun3, randn(), randn(), s1)
            fb = (fun3, B(randn(), randn(), s1)) 
        end
        #meval(cmd)
        operate(fb[1], fb[2]) 
    end
end

function run_tests(n)
    @time test1(n)
    @time test2(n)
end

run_tests(1e6)

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 27, 2021, 7:56pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/32 "2021-06-27T19:56:18Z")

</div>

> [@Bardo](#):
>
> ```julia
> function meval(cmd)
> len = length(cmd)
> if len == 2
> z = cmd[1](cmd[2])
> return
> end
> if len == 3
> z = cmd[1](cmd[2], cmd[3])
> return
> end
> if len == 4
> z = cmd[1](cmd[2], cmd[3], cmd[4])
> return
> end
> end
> 
> ```

This could be shortened to

```julia
function meval(cmd)
    z = cmd[1](cmd[2]...)
end

```

though I’d `return` the result directly here instead of modifying a global variable 🙂

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [June 27, 2021, 8:13pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/33 "2021-06-27T20:13:51Z")

</div>

So this is Julias version of varargin, thanks.

Repeatedly I hear sceptical remarks about global variables.  
How else can I implement in Julia what other languages call objects with properties?  
Certainly a typical mental gap of someone coming from another language like Matlab.

In a Matlab event-based simulation I had functions with local variables, all visible to the nested functions.  
I then could could use callbacks to these nested functions to modify the states of the objects.  
Quite elegant, the only issue being speed. Thats why I want to recreate it in Julia.

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [June 27, 2021, 8:38pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/34 "2021-06-27T20:38:58Z")

</div>

@Sukera: your meval replacement throws an error, did you try?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 27, 2021, 8:41pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/35 "2021-06-27T20:41:46Z")

</div>

Ah, sorry, I misread your original code - it should be

```julia
function meval(cmd)
   z = cmd[1](cmd[2:end]...)
end

```

instead.

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [June 27, 2021, 8:45pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/36 "2021-06-27T20:45:08Z")

</div>

Running, thank you very much!  
Not yet familiar with the syntax. :end and … seems telling the same, twice.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 27, 2021, 8:46pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/37 "2021-06-27T20:46:18Z")

</div>

> [@Bardo](#):
>
> In a Matlab event-based simulation I had functions with local variables, all visible to the nested functions.

I do not know Matlab, so I cannot help you with the equivalence here. But one structure that smells like what you are describing are the “functors”, and the structure of those is that I’ve shown above, as a callable object:

```julia
julia> struct Func{T}
         a::T
         b::T
       end

julia> (f::Func)(x,y) = f.a*x + f.b*y

julia> myfunc = Func(1,2)
Func{Int64}(1, 2)

julia> myfunc(5.,10.)
25.0

```

You can pass that object as a parameter to other functions:

```julia
julia> function external(f)
         x = rand()
         y = rand()
         my_result = f(x,y)
         return my_result
       end
external (generic function with 1 method)

julia> external(myfunc)
0.2535047160043371

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 27, 2021, 8:47pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/38 "2021-06-27T20:47:03Z")

</div>

The `cmd[2:end]` part is a slicing operation, taking everything from the second index on until the end of the indexable object. `f(x...)` takes an iterable object `x` and splats its content into the call to `f`, assigning it to each successive variable.

It should be mentioned while the syntax is useful, it should be limited to when you know how many elements `x` will have (and that number is somewhat small).

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [June 27, 2021, 9:07pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/39 "2021-06-27T21:07:35Z")

</div>

@lmiq  
The example is not consistent and does not run, sorry.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 27, 2021, 9:09pm UTC](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549/40 "2021-06-27T21:09:22Z")

</div>

> [@lmiq](#):
>
> ```julia
> julia> myfunc = Func(1,2)
> Func{Int64}(1, 2)
> 
> ```

Sorry, while copying/pasting this line, which instantiates `myfunc`, got lost. (fixed there)

By the way, the most common way to pass functions with variable number of parameters (not variables) to inner functions, is by the use of closures: [https://m3g.github.io/JuliaNotes.jl/stable/closures/](https://m3g.github.io/JuliaNotes.jl/stable/closures/)

```julia
julia> const a = 1
1

julia> const b = 2
2

julia> f(x,a,b) = a*x + b*x^2
f (generic function with 1 method)

julia> function outer(f,x)
         result = f(x)
         return result
       end
outer (generic function with 1 method)

julia> outer( x -> f(x,a,b), 5. )
55.0

```

If you need a variable number of variables, you can again resort to splatting (but this is much less common, and must be used with some care, because it might introduce performance problems if the number of parameters cannot be inferred at compile time):

```julia
julia> g(x,y,a,b) = x*a + y*b
g (generic function with 1 method)

julia> function outer2(f,x...)
         result = f(x...)
         return result
       end
outer2 (generic function with 1 method)

julia> outer2( (x,y) -> g(x,y,a,b), 5., 10.)
25.0

julia> outer2( (x) -> f(x,a,b), 5.)
55.0

```

[Previous page](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549.md?page=1)

[Next page](https://discourse.julialang.org/t/bridge-the-gap-please-from-matlab-to-julia/63549.md?page=3)
