Composing a function with keyword arguments

Hi all,

I want to wrap a function with keyword arguments. Here is what I am trying to do,


# Wraps `fk(x)` with `d`, i.e. `fn(x) = fk(d * x)` 
function wrapper(fk)    
    function fn(x; d = 1)
        @show d
        fk(d * x)
    end
end

# Wraps `fi`, `niter` times 
wrap(fi, niter) = ∘([wrapper for _ in 1 : niter]...)(fi) 

# Get wrapped function `h`  
niter = 5;
f0(x) = x;
h = wrap(f0, niter);

and this is the output I get when I call h with d specified.

julia> h(5, d=10);
d = 10
d = 1
d = 1
d = 1
d = 1

The problem here is that the keyword parameter d is evaluated as 10 just once (I think just when the function is compiled), not 5 times. I wonder if it is possible to evaluate as 10 for 5 times, not just for once?

what are you *really trying to do? (smell of XY problem

2 Likes

What I am trying to do is this: given f0(x) = x, the iteration should continue like this


f1(x) = d x

f2(x) = d^2 x

f3(x) = d^3 x

f4(x) = d^4 x

f5(x) = d^5 x

After wrapping f0 5 times I should get h(x) = f5(x) = d^5 x which means I should get h(5, d=10) = 10^5 * 5 = 50000

if your goal is to obtain a sequence like this:

julia> f(x, d, n) = d^n * x
f (generic function with 1 method)

julia> f.(0.1, 10, 1:5)
5-element Vector{Float64}:
     1.0
    10.0
   100.0
  1000.0
 10000.0

or do you need a vector of functions for some other reason?

1 Like

You can achieve that with a functor:

Though it is probably good to be sure that’s is the best strategy for what you really want to do.

2 Likes

Neither of them, actually. Simply stated, consider that there is a mapping T[f_k; d[ that maps f_k to f_{k + 1} such that f_{k + 1}(x) = T[f_k; d](x) = f_k(d \cdot x). Here, d \in \mathbb{R} is a parameter of the mapping T[f_k; d]. Given an initial function f_0(x), I want to compute the limit f^* of the mapping T[f_k; d], i.e., f^*(x) = \lim\limits_{k \mapsto \infty} T[f_k; d](x) \approx T^{\circ N}[f_0; d] for some large N where \circ is the composition operator. So, what I really want is the limit f^* of T[f_k;d] (which is a composed function, not a sequence of numbers, or a vector of functions).

May be an option, yes. Thanks for the suggestion.

2 Likes

If the initial function f0(x) also accepts a keyword argument, I think the following works.

function wrapper(fk)    
    function fn(x; d = 1)
        @show d
        fk(d * x; d=d)
    end
end

wrap(fi, niter) = ∘([wrapper for _ in 1 : niter]...)(fi) 

niter = 5;
f0(x; d=1) = x;
h = wrap(f0, niter);
h(5, d = 10) 

You probably realize this already, but I’ll just comment that the behavior you see is expected. If you unroll your original h (with niter = 2 for simplicity), you get

h = function fn(x; d = 1)
    @show d
    (function fn(x; d = 1)
        @show d
        f0(d * x)
    end)(d * x)
end

so h(5, d = 10) only modifies the d of the outermost fn, not any of the inner ds.


I started this post before your most recent post, so it looks like you already figured it out. But I’ll leave this comment in case it helps someone else understand why.

1 Like

Yes, that is exactly the case. Thank you for your time and comment.