Search code examples
functionrecursiongnuplothigher-order-functions

Functions as arguments in gnuplot


In gnuplot, is there a way to pass a user defined function as an argument to another user defined function? For example, I can write a function loop which will sum shifts of a given function:

f(x) = (x <= 0) ? 0 : 1/(1+x)**2
loop(x, i, s) = (i == 0) ? f(x) : loop(x-s, i-1, s) + f(x)

Then I can do things like:

plot loop(x, 10, 1)

But, how do I define a function loop2 that does this for any function, as in something like:

loop2(g, x, i, s) = (i == 0) ? g(x) : loop2(g, x-s, i-1, s) + g(x)

so that I can then do things like:

f3(x) = (x <= 0) ? 0 : 1/(1+x)**3
plot loop2(f, x, 10, 1)
replot loop2(f3, x, 10, 1)

Solution

  • I think this is not possible in gnuplot 5.4.

    The development version (gnuplot 5.5) has recently gained the ability to label a block of text commands as a named executable function, known as a "function block". This gives you access to commands in a function block that are not possible in a one-line user defined function. Here is your example run in a recent build of the development version. At the top level the name of the function ("f" or "f3") is passed as a parameter that can be used to construct a call of the function itself.

    function $loop2(name, x, i, s) << EOF
      local temp = 0
      eval sprintf("temp = %s(x)", name)
      return (i == 0) ? temp : temp + $loop2(name, x-s, i-1, s)
    EOF
    
    f(x) = (x <= 0) ? 0 : 1/(1+x)**2
    f3(x) = (x <= 0) ? 0 : 1/(1+x)**3  
    
    set key left Left reverse
    set tics nomirror
    set border 3
    set xrange [0:10]
    set yrange [0:1.5]
    
    plot $loop2("f", x, 10, 1), $loop2("f3", x, 10, 1)
    

    enter image description here

    And here is a link to an example in the demo collection that illustrates calling one function block from another, wrapping both in a top-level user defined function. function_block demo