Is there a way in Julia to modify a function f(x) such that it will return f(x)*g(x)

Viewed 229

I came across Julia in some graduate research and have done a few projects already in C++. I'm trying to "translate" some of my C++ work into Julia to compare performance, among other things.

Basically what I'm trying to do is implement something like the functional library from C++ such that I can do something like

g(x, b) = x*b # Modifier function

A = [1,2,...] # Some array of values

f(x) = 1 # Initialize the function

### This is the part that I am seeking
for i = 1:length(A) 
  f(x) = f(x)*g(x, A[i]) # This thing right here
end
###

and then be able to call f(x) and get the value of all the g(x, _) terms included (similar to using bind in C++) I'm not sure if there is native syntax to support this, or if I'll need to look into some symbolic representation stuff. Any help is appreciated!

2 Answers

You are probably looking for this:

julia> g(x, b) = x * b
g (generic function with 1 method)

julia> bind(g, b) = x -> g(x, b) # a general way to bind the second argument in a two argument function
bind (generic function with 1 method)

julia> A = [1, 2, 3]
3-element Vector{Int64}:
 1
 2
 3

julia> const f = bind(g, 10) # bind a second argument of our specific function g to 10; I use use const for performance reasons only
#1 (generic function with 1 method)

julia> f.(A) # broadcasting f, as you want to apply it to a collection of arguments
3-element Vector{Int64}:
 10
 20
 30

julia> f(A) # in this particular case this also works as A*10 is a valid operation, but in general broadcasting would be required
3-element Vector{Int64}:
 10
 20
 30

In particular for fixing the first and the second argument of the two argument function there are standard functions in Julia Base that are called Base.Fix1 and Base.Fix2 respectively.

You may be looking for the function composition operator ∘

help?> ∘
"∘" can be typed by \circ<tab>

search: ∘

  f ∘ g

  Compose functions: i.e. (f ∘ g)(args...) means f(g(args...)). The ∘ symbol can be
  entered in the Julia REPL (and most editors, appropriately configured) by typing
  \circ<tab>.

  Function composition also works in prefix form: ∘(f, g) is the same as f ∘ g. The
  prefix form supports composition of multiple functions: ∘(f, g, h) = f ∘ g ∘ h and
  splatting ∘(fs...) for composing an iterable collection of functions.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> map(uppercase∘first, ["apple", "banana", "carrot"])
  3-element Vector{Char}:
   'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
   'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
   'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)

  julia> fs = [
             x -> 2x
             x -> x/2
             x -> x-1
             x -> x+1
         ];

  julia> ∘(fs...)(3)
  3.0

so, for example

julia> g(b) = function(x); x*b; end # modifier function
g (generic function with 1 method)

julia> g(3)(2)
6

julia> f() = 3.14
f (generic function with 1 method)

julia> h = g(2) ∘ f
var"#1#2"{Int64}(2) ∘ f

julia> h()
6.28
Related