Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

SCIP 1.3 Formulating Abstractions with Higher-Order Procedures

1.3_formulating_abstractions_with_higher_order_procedures.livemd

SCIP 1.3 Formulating Abstractions with Higher-Order Procedures

Mix.install([])

1.3

Higher Order Procedure: a procedure that manipulates a procedure.

1.3.1 Procedures as Arguments

When you observe muliple procedures share the same pattern or structure it is indicative of a useful abstraction waiting to be brought to the surface. In such a case, you would map out the common structure and then pass the actual computation as an argument. This is not a new concept as mathematicians have identified such abstractions for centuries, e.g. sigma notation and “summation of a series”.

1.3.2 Constructing Procedures Using Lambda

It would be cumbersome to define a named abstraction for trivial operations only so that they could be passed as arguments. Programming languages will provide a lambda.

lambda definitions are used to create procedures with no name.

multiply = fn a, b -> a * b end
multiply.(5, 5)
perform_operation = fn operation, a, b -> operation.(a, b) end
perform_operation.(multiply, 5, 5)

We will often need local variables in our procedures other than those bound as formal parameters.

Let’s say we wanted to compute:

$f(x, y) = x(1 + xy)^2 + y(1 - y) + (1 + xy)(1-y)$

That’s confusing! It could be simplified as:

$a = 1 + xy$

$b = 1 - y$

$f(x, y) = xa^2 + yb + ab$

If we were simply using functions, we could use lambda functions to facilitate this local binding.

f = fn x, y ->
  (fn a, b ->
     x * (a * a) + y * b + a * b
   end).(1 + x * y, 1 - y)
end

f.(3, 4)

That’s not very readable! We are using an anonymous function to capture (a, b) as local parameters. Scheme has a let special form that allows you do define local parameters. (Fun fact: the let special form is in fact syntactic sugar for the underlying lambda application).

Elixir has function level scope, allowing for the above to be refactored:

f = fn x, y ->
  a = 1 + x * y
  b = 1 - y
  x * (a * a) + y * b + a * b
end

f.(3, 4)