Task

Create a function, compose,   whose two arguments   f   and   g,   are both functions with one argument.



The result of compose is to be a function of one argument, (lets call the argument   x),   which works like applying function    f    to the result of applying function    g    to    x.



Example

 compose(f, g) (x) = f(g(x))



Reference: Function composition

Hint: In some languages, implementing compose correctly requires creating a closure.




# -*- ObjectIcon -*-
#
# The Rosetta Code function composition task, in Object Icon.
# Composition will result in a co-expression.
#
# Object Icon co-expressions are closures: they share the local
# variables of the context in which they are created. In Arizona Icon,
# co-expressions obtain only the *values* of those variables. However,
# this difference, despite its significance, is not really important
# to the notion of composition.
#
# This example is adapted from the Unicon implementation of the
# task. To simplify the example, I have removed support for string
# invocations.
#
 
import io
 
procedure main (arglist)
  local f, g
 
  # f gets a co-expression that is a composition of three procedures.
  f := compose(append_exclamation, string_repeat, double_it)
  write(123@f)
 
  # g gets a co-expression that is a composition of a procedure and f.
  g := compose(string_repeat, f)
  write(123@g)
end
 
procedure double_it (n)
  return n + n
end
 
procedure string_repeat (x)
  return string(x) || string(x)
end
 
procedure append_exclamation (s)
  return s || "!"
end
 
procedure compose (rfL[])
    local x, f, saveSource, fL, cf
 
    every push(fL := [], !rfL)
    cf := create {
      saveSource := &source
      repeat {
        x := x@saveSource
        saveSource := &source
        every f := !fL do {
          case type(f) of {
            "co-expression": x := x@f
            default: x := f(x)
          }
        }
      }
    }
 
    # Co-expressions often need to be "primed" before they can be
    # used.
    @cf
 
    return cf
end