Passing `limits` as function arguments

I’m tryin to build a function that take 2 inputs limits and Function, so I wrote the below:

function Σ(limits, f::Function)
    @show limits
    @show f
end

Σ((i=1:3), :(x->x^2))

But it could not run, with the below error:

ERROR: LoadError: function Σ does not accept keyword arguments

I did not understand shall I change something in the function declaration, or in the function execution?

Σ((i=1:3,), x->x^2)? It depends what you’re trying to do. :(x->x^2) is a quoted expression, not a function.

The typeof function is your friend here.

julia> typeof(:(x->x^2))
Expr

julia> :(x->x^2) isa Function
false

julia> typeof((i=1:3))
ERROR: function typeof does not accept keyword arguments
Stacktrace:
 [1] kwfunc(::Any) at ./boot.jl:321
 [2] top-level scope at none:0

julia> typeof((i=1:3,))
NamedTuple{(:i,),Tuple{UnitRange{Int64}}}

As such, to call your function you need to write it as

Σ((i=1:3,), x->x^2)
1 Like

Thanks, but how can I read the limits range in my function!

I want to get something like:

start = limit.first
stop = limits.last

Then you can pass a Pair:

julia> limits = 1 => 3
1 => 3

julia> limits.first
1

julia> limits.second
3

:frowning:
Got this error:

ERROR: LoadError: type NamedTuple has no field first

Then you didn’t use a pair. Can you show your code instead of making people guessing what you have?

Here it is:

function Σ(limits, f::Function)
    @show limits
    out = 0.0
    start = limits.first
    stop = limits.second

    for i=start:stop
        out += f(i)
    end
    out
end

result = Σ((i=1:6,), n->(6n + 2))
@show result

You are passing a named tuple and not a Pair as I suggested. Change (i = 1:6,) to 1 => 6:

julia> function Σ(limits, f::Function)
           out = 0.0
           start = limits.first
           stop = limits.second
           for i = start:stop
               out += f(i)
           end
           out
       end
Σ (generic function with 1 method)

julia> Σ(1=>6, n->(6n + 2))
138.0

But if you just use start and stop to recreate the range start:stop in the function, then maybe it makes more sense to just use the range, that is, pass 1:6 and remove start and stop:

julia> function Σ(range, f::Function)
           out = 0.0
           for i = range
               out += f(i)
           end
           out
       end
Σ (generic function with 1 method)

julia> Σ(1:6, n->(6n + 2))
138.0
2 Likes

Thanks a lot, I loved the solution of using range
I re-wrote it as:

function Σ(range, f::Function)
    out = 0.0
    (for i = range; out += f(i) ; end)
    out
end

result = Σ(1:6, n->(6n + 2))
@show result

If you don’t mind relying on the already existing sum function, this is also an option:

Σ(range, f::Function) = sum(f(i) for i in range)
2 Likes

Supreme, very silky solution, thanks :hugs:

So, Apparently I can avoid adding my function, by using the below

f(n) = 6n + 2
result = sum(f(n) for n=1:6)
@show result

Here’s the slickest way (you can pass the function you are summing with as the first argument):

julia> f(n) = 6n + 2
f (generic function with 1 method)

julia> sum(f, 1:6)
138
3 Likes

By the way, with my Reduce.jl package, you can do this

julia> using Reduce
Reduce (Free CSL version, revision 4590), 11-May-18 ...

julia> @force using Reduce.Algebra

julia> ∑(:(x^2),:x,1,3)
14

julia> ∏(:(x^2),:x,1,3)
36

it takes summation limits and symbolic expressions as arguments, of course it’s not as fast as using a function.

Thanks, the link is not working.

They work for me. I’m not sure I fully understand the documentation though.