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

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?

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.

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.

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.

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