Functional Programming

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Reaction score
405
Location
Untitled.png
Functional Programming
I've decided to start this thread in order to share knowledge on the programming paradigm referred to as Functional Programming.

History
For many Functional Programming is something they've either never heard about or only recently heard about.

So you'd probably be surprised to know that Functional Programming one of the oldest paradigms; far older than Object Oriented Programming (OOP), in actual fact it's roots stem from Lamba Calculus in the 1930s, to the first real functional enabled language, `Lisp` developed in the late 1950s.

Style
Functional Programming, like OOP is simply just style of programming; one which in this case:
  • Models methods in similar style to mathematical functions
  • Avoids hidden inputs, side effects, and mutable state (i.e. referentially transparent).
  • Employs techniques like mapping, pipelining, recursion, currying and the use of higher order functions.

Misconceptions:
  • No paradigm or style is ever mutually exclusive. Meaning it's safe to mix.
  • No paradigm enforces a All-or-Nothing approach. Meaning they mix well together.
  • Incremental integration is not only possible; it's an great way to start.

FP Adoption in Languages
Many languages that weren't previously consider functional, have been in the last decade or so enhanced to support a functional programming, for example:
  • C# (Since Linq, released in 2007)
  • Java (Since Java 8, released in 2014)
  • PHP (Since PHP 4, released in 2008)
  • Python (Since Python 2, released in 2000)
Of the above four languages Java was probably the most assertive in enforcing a single paradigm: OOP. However since Java 8, under the banner `Project Lambda`, significant strides have been made to undo that, and a relatively clear roadmap lies ahead for Java's functional future.

Java like many other languages is transforming into a multi paradigm friendly language: one which enables us to search for the perfect balance ostensively by `separating logic from action`, or stated differently `separating the value and object layers`.

Here's just a few of the changes planned for Java 9 / 10:
  • Optional as a proto-value type. They're testing the idea of either migrating many of the stdlib reference types to value types, and to introduce new value type constructs that `Codes like a class, works like an int!`
  • Generics over value types (primitives)
  • Revamp of Java's type system, specifically to support small immutable, identityless value types.

You can read more about the Java roadmap here:

What I hope to share
Many of the functional programming articles that you'll find on the Internet tend to focus on the abstract parts of functional techniques and type theory.

What I'm going to try to do different, is that I hope to better explain the underpinnings of these techniques, by showing you practical examples of both imperative, and "unfunctional" code that people write every day, and then demonstrate how we go about translating this into a more a functional style.

During this process I also hope to convince you that many of the approaches underpinning FP aren't completely new; and that many of the techniques are probably already employed in a somewhat similar fashion in your own code.

Articles planned
  1. The first article will focus on what constitutes functional style code; with the end goal to explain why it matters, or why we need a distinguish between value and object types.
  2. The second article will focus on accumulator loops (e.g. sum of values) using the `Fold (higher-order function)`, also called `reduce` or `aggregate`, and ultimately try to explain why this technique was developed and why it's useful.
  3. The third article will focus on transformative loops (e.g. adjusting values) using the `Map (higher-order function)`, also called `select`, with the same end goal: to explain why this technique exists and why it's useful.

Multi Language Examples:
In an attempt to make these articles more useful I'm going to try to present code examples in each of the following languages:
  • C#
  • Java
  • PHP
  • Swift

Future articles could cover aspects like:
  • Combinatorial logic
  • Pipelining,
  • Recursion,
  • Currying
  • More higher order functions (flatmap, filter, foreach, ...)
...and hopefully by the end of this, you'll have a better understanding of how to take advantage of FP in your code; and if I'm at all successfull you should also have a better (if not simplistic) understanding of what constitutes: Functors, Applicatives and Monads.
 
Last edited:
Article 1: What is Functional Programming?

What is Functional Programming?
Some explanations of functional programming, can involve a laundry list of “functional” characteristics.

They'll often mention:
  • Immutable data,
  • Value types,
  • First class functions,
  • Tail call optimisation
[table="width: 70%, class: outer_border"]
[tr]
[td]> Language features that aid functional programming. [/td]
[/tr]
[/table]

... or they'll mention:
  • Mapping,
  • Reducing,
  • Pipelining,
  • Recursion,
  • Currying
  • Higher order functions
[table="width: 70%, class: outer_border"]
[tr]
[td]> Programming techniques used to write functional code. [/td]
[/tr]
[/table]

... and maybe even mention:
  • Parallelisation,
  • Lazy evaluation
  • Determinism
[table="width: 70%, class: outer_border"]
[tr]
[td]> Advantageous properties of functional programs.[/td]
[/tr]
[/table]

But let's for moment just ignore all that. Functional code is really only characterised by one very specific thing:
[table="width: 70%, class: outer_border"]
[tr]
[td]> the absence of side effects. [/td]
[/tr]
[/table]

It doesn’t rely on data outside the current function, it doesn’t change data that exists outside the current function, and it always evaluates to the same result, given the same input. Every other “functional” thing can be derived from this property. Btw we call this a `pure function`. https://en.wikipedia.org/wiki/Pure_function



Code Examples

To further our understanding, let's look at a few code examples

Code:
var sum = 0
func sum(values: [Int]) -> Int {
  for value in values {
    sum += value
  }
  return sum
}

print(sum(values: [1, 2, 3, 4, 5, 6, 7, 8, 9])) // 45
print(sum(values: [1, 2, 3, 4, 5, 6, 7, 8, 9])) // 90
In the above example we might have expected the print statements to return the same answer; they don't -- which means that we can classify the `sum` function as not pure, or not-functional.

Now let's see what needs to change to make this a functional or pure version of this.
Code:
func sum(values: [Int]) -> Int {
  var sum = 0
  for value in values {
    sum += value
  }
  return sum
}

print(sum(values: [1, 2, 3, 4, 5, 6, 7, 8, 9])) // 45
print(sum(values: [1, 2, 3, 4, 5, 6, 7, 8, 9])) // 45
The print statements now return the same answer. The difference is that this version is conforming to a key requirement of a `pure function`, namely:
  • The function result value cannot depend on any hidden information or state that may change while program execution proceeds or between different executions of the program.
Basically the variable `sum` that we use to keep track of our accumulative total is now contained within the scope of the function, or more specifically the only external input that the function relies upon is it's specified parameters, the values property.



So how is this different from objects (OOP)?

An element is considered an Object if all three of the following statements hold true:
  • They represent Identity: the property of objects that distinguishes them from other objects.
  • Manage State Transitions
  • Perform Side Effects
The only current exceptions in Java, C# and PHP are value type structures i.e. `Structs` and `Enumerators`.



Definition Of Values Types

Value types always have the following behaviours:
  • They're inert,
  • they're isolated,
  • and they're interchangeable.
Values types are generally either copied on assignment or copy on write (compiler level for optimisation) i.e. Assignment shares the same values in memory, until a write operation is performed. Reference types in comparison are always shared on assignment, and have multiple owners. e.g. Objects

Whilst we can can create object types to behave in a similar way to value types, it always takes more effort to get there, plus under covers it still will be tracked i.t.o. it's identity, and will have none of the resources advantages that real value types offer.

It is these advantages that are probably the single biggest driving force behind putting value types into C# and Java.

Here's a summary from Java's Language team:
[table="width: 70%, class: outer_border"]
[tr]
[td]> Object identity serves only to support mutability, where an object’s state can be mutated but remains the same intrinsic object. But many programming idioms do not require identity, and would benefit from not paying the memory footprint, locality, and optimisation penalties of identity. Despite significant attempts, JVMs are still poor at figuring out whether an object’s identity is significant to the program, and so must pessimistically support identity for many objects that don’t need it.
>
> More detail: Even a nominally stateless object (with all final fields) must have its identity tracked at all times, even in highly optimised code, lest someone suddenly use it as a means of synchronisation. This inherent “statefulness” impedes many optimisations. Escape analysis techniques can sometimes mitigate some of these costs, but they are fragile in the face of code complexity, and break down almost completely with separate compilation. The root problem is identity.[/td]
[/tr]
[/table]



So what does it mean?
The lack of real value types by itself is not a hinderance here. We can still implement specially designed classes as a substitute for value types; basically by ensuring that any instances of the class behave in accordance with the rules of a `pure function` i.e. no side effects.

Java, C# and PHP's String type is an example of this.

In addition to this; Java, C# and PHP built their functional features to operate within the current constraints of the language, meaning even without strict value types, you will be able to take full advantages of the functional features.


Easy versus Simple
  • Easy: Something familiar, close to hand - comparison with learning to touch-type; an initially difficult task which became immensely easier over time.
  • Simple: Involving fewer concerns, for example: functions like min and max are simple, whereas objects are not simple.
[table="width: 70%, class: outer_border"]
[tr]
[td]>Functional Programming like OOP is not simple, but it can be easy.[/td]
[/tr]
[/table]
The point here is that all `Concepts have a Cost`, but just like learning the Delegate pattern in OOP or learning to touch-type; these concepts once grounded have immense pay back.
 
Last edited:
Article 1: Java

Code:
public class Art1 {
  private int total = 0;
  int sum(int[] values) {
    for (int value : values) {
      this.total += value;
    }
    return this.total;
  }
}

public class main {	
  public static void main(String[] args) {		
    Art1 art1 = new Art1();
    System.out.println(art1.sum(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}));  // 45
    System.out.println(art1.sum(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9})); // 90
  }
}
Java, unlike PHP and Swift doesn't support declaration of functions or variable at the global scope, hence in this example the sum function is defined with a class: Art1. The outcome is however the same, the results are inconsistent.
Code:
public class Art1 {
  int sum(int[] values) {
    int total = 0;
    for (int value : values) {
      total += value;
    }
    return total;
  }
}

public class main {	
  public static void main(String[] args) {		
    Art1 art1 = new Art1();
    System.out.println(art1.sum(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}));  // 45
    System.out.println(art1.sum(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9})); // 45
  }
}
To ensure consistency of the result, we similar to the Swift example defined the total variable within the scope of the sum function, meaning that the total variable would be reset to 0 for every call.
 
Last edited:
Article 1: C#

Code:
using System;

namespace Functional
{
  internal class Art1
  {
    int total = 0;
    internal int sum(int[] values)
    {
      foreach (int value in values) {
        total += value;
      }
      return total;
    }
  }

  class MainClass
  {
    public static void Main(string[] args)
    {
      Art1 art1 = new Art1();
      Console.WriteLine(art1.sum(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }));  // 45
      Console.WriteLine(art1.sum(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }));  // 90
    }
  }
}
C# like Java, doesn't support declaration of functions or variable at the global scope, hence in this example the sum function is defined with a class: Art1. The outcome is however the same, the results are inconsistent.
Code:
using System;

namespace Functional
{
  internal class Art1
  {
    internal int sum(int[] values)
    {
      int total = 0;
      foreach (int value in values) {
        total += value;
      }
      return total;
    }
  }

  class MainClass
  {
    public static void Main(string[] args)
    {
      Art1 art1 = new Art1();
      Console.WriteLine(art1.sum(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })); // 45
      Console.WriteLine(art1.sum(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 })); // 45
    }
  }
}
To ensure consistency of the result, similar to the Swift example we defined the total variable within the scope of the sum function.
 
Article 1: PHP

PHP:
<?php
class Art1 {
  private $total = 0;
  public function sum($values) {
  	foreach($values as $value) {
      $this->total += $value;
  	}
  	return $this->total;
  }
}

$art1 = new Art1();
print $art1->sum([1, 2, 3, 4, 5, 6, 7, 8, 9]) . "\n";  // 45
print $art1->sum([1, 2, 3, 4, 5, 6, 7, 8, 9]) . "\n";  // 90
?>
PHP like Swift supports declaration of functions or variable at the global scope, however the scope of a variable is by default restricted to the context that it is defined in (we can however override the default behaviour using the global keyword. However in this example the sum function is defined within a class: Art1. The outcome is therefore the same; results are inconsistent.
PHP:
<?php
class Art1 {
  public function sum($values) {
    $total = 0;
    foreach($values as $value) {
      $total += $value;
    }
    return $total;
  }
}

$art1 = new Art1();
print $art1->sum([1, 2, 3, 4, 5, 6, 7, 8, 9]) . "\n";  // 45
print $art1->sum([1, 2, 3, 4, 5, 6, 7, 8, 9]) . "\n";  // 45
?>
To ensure consistency of the result, similar to the Swift example we defined the total variable within the scope of the sum function.
 
Last edited:
Awesome. Been thinking about this a lot recently. Been getting into Elm lately, it is beautiful
 
Awesome. Been thinking about this a lot recently. Been getting into Elm lately, it is beautiful
I've never tried Elm, so had a brief look over.
Clean and concise syntax, that feels and looks a lot like F#, plus the language is quite easily extended -- nice!
 
Article 2: Fold / Reduce Higher Order Function

Fold / Reduce Higher Order Function
In this article I'm going to be focusing on loops that make use of an accumulation variable, for example:

  • Sum of values
  • Product of values
  • Concatenation (sum of strings)

Scenario 1: Sum of Integer Values
We have an array of integer and need to return their combined sum.

Code:
func sum(values: [Int]) -> Int {
  var total = 0
  for value in values {
    total += value
  }
  return value
}
print(sum(value: [1, 2, 3, 4, 5, 6, 7, 8, 9]) \\ 45

Ok, quite easy. We create a pure function with values parameter, to accept the array of integers that we need to sum, but what if instead of summing the values, we need to find the product of the values.

Scenario 2: Product of Integer Values
Code:
func product(values: [Int]) -> Int {
  var total = 1
  for value in values {
    total *= value
  }
  return value
}
print(product(value: [1, 2, 3, 4, 5, 6, 7, 8, 9]) \\ 362880
Ok, again a fairly easy task... but did you notice how much of the code is similar between the `sum` and `product` functions? Essentially we only changed the name, and these two lines:

Code:
var accumulator = 0   	--->	var accumulator = 1
accumulator += value  	--->	accumulator *= value
The rest of the code is essentially duplication.

Ok, but how can we do this in a more "functional way"?
I say "more functional way", because if you look at both of the above functions; they both classify as `Pure Functions`, i.e. no side effects.

Well..., so let's frame this part a little different: how can functional techniques assist us to reduce the amount of code duplication. So for this section we're going to use one the Higher-order Functions (HOF);

Fold (also is called reduce, accumulate, aggregate).
This takes a function, a collection of items and returns a value that is created by combining the items.

Code:
print([1, 2, 3, 4, 5, 6, 7, 8, 9].reduce(0, +)) // 45 (sum)
print([1, 2, 3, 4, 5, 6, 7, 8, 9].reduce(1, *)) // 362880 (product)
Huh?
I agree it's less code, ... but really WTF is going on, confused?

What's probably confusing the picture a bit is that I've chosen to use some `Syntactic Sugar`; syntax within a programming language that is designed to make things easier to read or to express.

Before I try to explain what's going on; let me first remove the sugar by expanding those two examples.

Code:
print([1, 2, 3, 4, 5, 6, 7, 8, 9].reduce(0, { total, value in total + value })) // 45
print([1, 2, 3, 4, 5, 6, 7, 8, 9].reduce(1, { total, value in total * value })) // 362880
Ok, so let me help you with understanding of this; we basically have a function called `reduce` that operates on a list of values (the array) and also takes two additonal parameter values:

  • The Initial or starting value; which in this case is 0 for sum, and 1 for product.
  • A Closure (or a block of code to process the values); this closure recieves two values: `total` & `value`; to which we then apply an operator, for example: `+` for sum, and `*` for product.

Too further alleviate any confusion, let's have a look at the function definition for `reduce`

Code:
extension Sequence {
  public func reduce<Result>(
    _ initialValue: Result,
    _ nextValue: (_ partialTotal: Result, Iterator.Element}) throws -> Int) rethrows -> Int {
      var total = initialValue
      for element in self {
        total = try nextValue(total, element)
      }
      return total
    }
  }
}
Huh?... there's quite a bit of Swift specific syntax in this code; however let's ignore most of that and focus on the middle part of this function:

Code:
var total = initialValue
for element in self {
  total = try nextValue(total, element)
}
return total
Does this seem at all familiar? Go back and look at the two functions (sum & product) that we defined at the beginning of this article. Yes, it's essentially same code. `self` refers to the sequence of integer values (Array), the only part that looks a little different is this line:

Code:
total = try nextValue(total, element)
More specifically the second part `nextValue(total, element)`. nextValue if you look at reduce function parameters refers to a closure i.e. a block of code that was passed in as a parameter. This block of code is provided with two values; the current `total` and the next `element` or next value in the sequence.

Let's look again at our expanded single line solution for sum:

Code:
print([1, 2, 3, 4, 5, 6, 7, 8, 9].reduce(0, { total, value in total + value })) // 45
The passed in closuure (or block of code) refers to this part:

Code:
{ total, value in total + value }
This basically says, we receive two values `total, value in`, and then proceed to add them together `total + value`. This is a rudimentary example of a block of code (closure); far more complex logic and/or process can be performed in these closure. The only restrictions is that your block of code at the end, conforms to type of the closure:

Code:
nextValue: (_ partialTotal: Result, Iterator.Element}) throws -> Int
i.e. We are provided two values; `we add our processing code` and finally we're expected to provide a `Int` return value. Btw the `throw` keyword is simply telling us that whatever exception we encounter in the closure, will be thrown, similarly `rethrows` keyword implies that any lower level exceptions will be passed upwards through the call stack, meaning that our originating command would be able trap for these.

Almost there...

Whew, so to summarize reduce is essentially the same accumulation process as our first two functions (sum & product). The benefit is that it helps to remove unnecessary code duplication for common aggregation processes, secondly it has been specifically designed for flexibility by using a closure i.e. a custom block of processing code.

Now if I've haven't completely lost you in the process of this explanation, let me try to explain ...
How exactly does the Sugar Syntax work?

Code:
print([1, 2, 3, 4, 5, 6, 7, 8, 9].reduce(0, +)) // 45 (sum)
As we said the closure receives two values: `total` and `value`. The `+` symbol in the above code refers to the operator `+`. Ok, so let's have a look at the function signature for the `+` operator.

Code:
infix func +(lhs: Int, rhs: Int) -> Int { }
It takes two values (Left hand side & right hand side), adds them together and returns an Int. In Swift values passed to a closure are tuples, and tuples can be used as a substitute for function parameters, as long as they are provided in the same order. Which in this case it does; so lhs = `total` and rhs = `value`, because the expected parameters are a perfect match to the provided closure values.

Conclusion
Whew, ok that's enough for this article... You can expect matching `reduce` code examples for Java, C# and PHP (in due course), with one restriction; neither of them have support for sugar syntax as it relates to the `+` and `*` operators.

I really hope you're were able to follow along; please feel free to ask for more examples if you need them, even for more clarity on anything that you're struggling with.

Peformance Note:
[table="width: 80%, class: outer_border"]
[tr]
[td]It's also important to appreciate that the underlying code for Higher-order Functions are built by the compiler teams of each language, meaning they would have taken additonal steps to ensure that this code is highly performant.[/td]
[/tr]
[/table]


Bonus
As a bonus I'm a going to also include code on how we can use `reduce` to solve the first Euler challenge (equivalent examples in Java, C# and PHP will also be made available).

The problem is as follows:
[table="width: 80%, class: outer_border"]
[tr]
[td]> Multiples of 3 and 5: If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000.[/td]
[/tr]
[/table]


Code:
print((1..<1000).reduce(0, {$0 + ($1 % 3 == 0 || $1 % 5 == 0 ? $1 : 0) }))
FYI the $0 and $1 are substitute tuple tags that refer respectively to the first and second values that were passed to the closure i.e. `total` and `value`
 
Last edited:
Article 2: Java

Code:
import java.util.Arrays;
import java.util.stream.IntStream;

public class main {	
  public static void main(String[] args) {

     // Scenario 1		
     System.out.println(Arrays.stream(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9})
		 .reduce(0, (total, value) -> total + value));

     // Scenario 2
     System.out.println(Arrays.stream(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9})
		 .reduce(1, (total, value) -> total * value));
		
     // Euler Problem 1
     System.out.println(IntStream.range(1, 1000)
		 .reduce(0, (total, value) -> total + 
			     (value % 3 == 0 || value % 5 == 0 ? value : 0)));
  }
}
 
Last edited:
Article 2: C#

Code:
using System;
using System.Linq;

namespace Functional
{
  class MainClass
  {
    public static void Main(string[] args)
    {
      // Scenario 1
      Console.WriteLine(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
                        .Aggregate(0, (total, value) => total + value));

      // Scenario 2
      Console.WriteLine(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
                        .Aggregate(1, (total, value) => total * value));


      // Euler Problem 1
      Console.WriteLine(Enumerable.Range(1, 999)
                        .Aggregate(0, (total, value) => total + 
                                   (value % 3 == 0 || value % 5 == 0 ? value : 0)));

    }
  }
}
Note: C#'s higher order functions fall under the banner of Linq, and the Reduce equivalent is Aggregate.
 
Article 2: PHP

PHP:
<?php
// Scenario 1
print array_reduce([1, 2, 3, 4, 5, 6, 7, 8, 9], 
	function($total, $value) { return $total + $value; }, 0) . "\n";

// Scenario 2
print array_reduce([1, 2, 3, 4, 5, 6, 7, 8, 9], 
	function($total, $value) { return $total * $value; }, 1) . "\n";

// Euler Problem 1
print array_reduce(range(1, 999), 
	function($total, $value) { return $total + 
		($value % 3 == 0 || $value % 5 == 0 ? $value : 0); }, 0) . "\n";
?>
 
Extra bonus for PHP: Chained method calls

As you probably noticed the way in which PHP calls it's Higher-Order Functions is different from C#, Java and Swift. Basically PHP by default uses method calls that wrap the input as opposed to the C#, Java and Swift which rely on method chaining.

Here's a Swift example of method chaining; the array of values is passed to the map using the chain dot syntax, similarly the result of that is chained to the sorted method, and ultimately to the foreEach method.

Not only does this make it easy to understand the process flow, but also helps with the formatting of the processing block. In this example, I've pressed carriage return, after each method call in the chain in order to align their dots. This is a natural formatting feature in these languages.
Code:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
  .map { $0 * 2 }
  .sorted(by: >)
  .forEach { print($0, terminator: ", ") }

Note: Chaining methods calls is not only nice for conciseness, but also to aid the compiler during optimisation i.e. this is one block of code.

Here's the equivalent in Java:
Code:
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
	.map((value) -> value * 2)
	.sorted(Collections.reverseOrder())
	.forEach((value) -> System.out.print(value + ", "));

Here's the equivalent in PHP:
PHP:
$answer = array_map(function($value) { return $value * 2; }, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
rsort($answer);
foreach ($answer as $value) {
  print $value . ",";
}

It's broken up into a few separated commands, rsort(reverse sort) in particular must be separated from array_map, because array_map returns a new array, where as rsort sorts in place i.e. we can't merge the two. However all is not lost, you can have something quite similar to Swift, Java and C# with a bit of PHP magic methods..

To achieve this we're going to create a new class that extends ArrayObject and implements the magic method __call:
PHP:
class MyArray extends ArrayObject {
  public function __call($func, $argv)
  {
    switch ($func) {
      case 'map':
        return new MyArray(call_user_func_array('array_map', array_merge($argv, array($this->getArrayCopy()))));
      case 'sort':
        $copyOfArray = $this->getArrayCopy();
        sort($copyOfArray, $argv[0]);
        return new MyArray($copyOfArray);
      case 'reverseSort':
        $copyOfArray = $this->getArrayCopy();
        rsort($copyOfArray, $argv[0]);
        return new MyArray($copyOfArray);
      case 'reduce':
        return call_user_func_array('array_reduce', array_merge(array($this->getArrayCopy()), $argv));
      case 'product':
        return call_user_func_array('array_product', array_merge(array($this->getArrayCopy()), $argv));
      case 'sum':
        return call_user_func_array('array_sum', array_merge(array($this->getArrayCopy()), $argv));
      case 'forEach':
        return call_user_func_array('array_walk', array_merge(array($this->getArrayCopy()), $argv));
      default:
        throw new BadMethodCallException(__CLASS__.'->'.$func);
    }
  }

  public function __toString() {
    return '[' . join(", ", $this->getArrayCopy()) . ']';
  }
}

Whew quite a bit of code... but I promise it's all worth it. So after adding this class to your code, you can now rewrite the PHP version as follows:
PHP:
(new MyArray([1, 2, 3, 4, 5, 6, 7, 8, 9]))
  ->map(function($v) { return $v * 2; })
  ->reverseSort()
  ->forEach(function($v) { return print $v . ", "; });
Note:
  • in PHP method chaining is done with -> instead .
  • __call() magic method is triggered when invoking inaccessible methods in an object context.
  • MyArray can be called anything you like; and it acts as a stand-in for arrays. Similarly in the __call() method, you can name the methods anything you like; you could even choose to keep them the same as PHP's default. i.e. instead of case 'map':, you could use case 'array_map' instead.

The result btw is:
Code:
18, 16, 14, 12, 10, 8, 6, 4, 2,

Anyway hope this helps in your coding...
 
Last edited:
Article 3: Map, Option Type and Flatmap

Map (iteration & transformation)
Map is the name of a higher-order function that applies a given function to each element of a list, returning a list of results in the same order.

Let's look at a procedural example of taking a list of values (the type is not important); to which we then apply a transform, and finally return the transformed result.

Code:
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var mutable = [Int]()
for value in numbers {
  let newNumber = value + 1
  mutable.append(newNumber)
}
let numbersPlusOne = mutable

  1. We start off recieving an immutable array of numbers; stored in a variable called `numbers`.
  2. In order to apply a transform to these numbers, we need a mutable (modifyable) place to store them.
  3. Now we iterate through each of the numbers in the `numbers` array
  4. We apply a transform `+ 1` and store result in `newNumber`.
  5. We then append this `newNumber` to our `mutable` array.
  6. And finally we take a immutable copy of the mutable and store this in `numbersPlusOne` variable.

In Functional programming we call this process Map, here is one possible implementation of `map`.

Code:
extension Array<T> {
  func map<U>(_ transform: T -> U) -> [U] {
    var array: [U] = []
    for element in self {
      let newValue = transform(x)
      array.append(newValue)
    }
    return array
  }
}
You can basically see it's the exact same iteration / transformation pattern (aside from the generics). If this is the exact same pattern we have used for all these years, why all of a sudden is it interesting.

Well once we move that abstraction up a level, you end up with much cleaner code. So you no longer need to manage the details of the iteration, instead you get to focus only on the transformation, which is the important part of what you want to achieve. Plus is much more declarative, and far less procedural.

Code:
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let numbersPlusOne = numbers.map { $0 + 1 }

...and as an added bonus, because closures are functions, and similarly functions are closure, you can easily abstract any common transformation process into a reusable function.

Code:
extension Int {
  func increment(by amount: Int) -> Int {
    return self + amount
  }
}

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let numbersPlusOne = numbers.map { $0.increment(by: 1) }


Real world example

Code:
struct User {
  let name: String
  let email: String
}

let mcdonald = User(name: "Ronald Mcdonald", email: "[email protected]")
let sanders = User(name: "Colonel Sanders", email: "[email protected]")
let users = [mcdonald, sanders]
let emails = users.map { $0.email }
sendCorrespondence(emails)
Simple and easy way to split off just the data that you need...but what if some users don't have a valid email, how can I get just a list of those users i.e. to forward to the sales team to complete.

Code:
let mcdonald = User(name: "Ronald Mcdonald", email: "[email protected]")
let sanders = User(name: "Colonel Sanders", email: "[email protected]")
let nandos = User(name: "Barci Nandos", email: "")
let users = [mcdonald, sanders, nandos]
let missingEmails = users.map { $0.email.characters.count == 0 ? $0.name : nil}
sendSales(missingEmails)


Option Type
In FP there is however a far better way to deal with data that could either be valid or not. This construct is referred to as Option type. Here's an example defintion for an Option type in Swift:

Code:
enum Optional<T> {
  case .Some(T)
  case .None
}
Basically it's a simple enumerator, with only two possible outcomes:

  • It's has `Some` value, denoted as T (a generic placeholder for any type)
  • Or it has `None`, meaning no value or nil.


Option types are essentially a box or container structure that either holds a value or not. The benefit of this Option type will become more apparent when we redefined `User` type:

Code:
struct User {
  let name: String
  let email: String?
}

The only difference is the `?` next to the email property. In Swift the `?` is used to denote a property that could either have a value or be nil. Let's reload our users to see how this works.

Code:
let mcdonald = User(name: "Ronald Mcdonald", email: "[email protected]")
let sanders = User(name: "Colonel Sanders", email: "[email protected]")
let nandos = User(name: "Barci Nandos")
let users = [mcdonald, sanders, nandos]
let missingEmails = users.map { $0.email == nil ? $0.name : nil }
sendSales(missingEmails)
The changes are as follows:
  • We now can simply leave out any fields that are Optional, i.e. for nandos we didn't have to specify a blank email.
  • The logic used is filtering out missing emails is now more familiar i.e. instead of counting the character length, we simply check for a nil value.

The only problem with this solution and the prior one is that resulting array will contain the following values: `[nil, nil, "Barci Nandos"]` -- because our ternary (if) statement, returns the name if the email is nil, and a nil when the email is not nil.


Flatmap
To remove the nils and not have to deal with them later on, we can simply use a different (but similar) higher-order function to `map`, namely: `flatMap`. Flatmap is for all intensive purposes the same as map, except that in this case it's going to strip out the nils. Here's an example of that:

Code:
let missingEmails = users.flatMap { $0.email == nil ? $0.name : nil }
sendSales(missingEmails)
`missingEmails` in this case only has one value: `["Barci Nandos"]`

...but that's not the only thing that flatMap does; the second part relates to it's name, the `flat` part. Let's say we have a 2D array (an array within another array), for example here's a 2D array, representing different apartments and their occupants:

Code:
let apartments = [["jack", "betty"], ["john", "nancy"], ["peter", "stacey"]]

Now let's say all I need is a list of these occupants, how would I do that:

Code:
let occupants = apartments.flatMap { $0 }
The result of from this is:

Code:
["jack", "betty", "john", "nancy", "peter", "stacey"]
Similarly if any of the apartments were empty (nil); flatMap would have filtered these out.


Note: flatMap will only flatten one level at time i.e. a 3D Array would become a 2D array. If you wanted the 3D array flattened to a 1D array, you would have to run the flatMap operation twice, for example:

Code:
let occupants = apartments.flatMap { $0.flatMap { $0 } }

Also: Flatmap when used in conjunction with a decision step, like the ternary operator we used to check for nil emails, can be a very powerful and reasonably low cost filter implementation i.e. values to ignore are returned as nils, which then are stripped by flatMap before the return. Complexity wise this is O(n) vs. double that with separate transform and filter steps.
Plus both map and flatmap are not confined to return the same type that they are processing i.e. data can be transformed and loaded into an entirely different structure or object.


Touching the surface
I'm only touching the surface when it comes to ways in which these higher-order functions can be utilised... yet the reason why they exist should hopefully be a bit more obvious:

  • It removes procedural duplication.
  • It allows more declarative code, with a focus on the transformation rather than underlying procedural implementation.



C#, Java and PHP Examples
Not all languages support Option Types in the same way, and there some languages like PHP that don't currently support it, but we can simulate it by creating our box type. This and the differences between the language implementations is going to take a bit more time i.r.o. providing language relevant examples.

Until then you can peruse these links related to this:
* C# Nullable Types: https://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx
* Java Optional: https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
* PHP: https://gist.github.com/jan-j/f86ab6a9935b22469b43
 
Last edited:
What are the pro's/con's in filtering inside ".map()" vs using ".filter()"
 
What are the pro's/con's in filtering inside ".map()" vs using ".filter()"
If you consider that the transform process that occurs within map and flatmap, is basically the same as what would occur inside a single iteration loop -- it has no cost beyond O(n) i.e. processing every element, and I'm ignoring for the moment the possibility for parallel processing which many FP implementations support.

Separate, transform and filter steps typically incur twice that cost. i.e. once for the transform and again for filter.


Exception to the rule:
Many LLVM implementation, have the ability to optimise away a lot of that complexity, meaning that it really depends own the compiler setting and what optimisation is possible; you would have to check. C# Linq does pretty well with this type of optimisation, so too Swift. Java is still fighting their decision to centre everything on reference types, so I doubt it would be fully optimised atm; for that I think we need Java 10.
 
Last edited:
Thanks for starting this thread, FP certainly looks like a paradigm I'd want to become comfortable with. I hope you dont mind if I occassionally PM you on FP?

Edit: you think it'd be useful to start familiarising myself with say Haskell to sink my teeth into FP?
 
Last edited:
Thanks for starting this thread, FP certainly looks like a paradigm I'd want to become comfortable with. I hope you dont mind if I occassionally PM you on FP?

Edit: you think it'd be useful to start familiarising myself with say Haskell to sink my teeth into FP?

R, Haskell, Ruby, F#, JavaScript are either pure functional languages or have support for the functional programming paradigm.

R, F#, Haskell are pure functional languages as far as I know. (I use R)

Ruby and JavaScript, like the ones mentioned above by Droid, support the functional programming paradigm.
 
Thanks for starting this thread, FP certainly looks like a paradigm I'd want to become comfortable with. I hope you dont mind if I occassionally PM you on FP?

Edit: you think it'd be useful to start familiarising myself with say Haskell to sink my teeth into FP?

I would really recommend starting out by doing the Coursera course on Functional Programming. It is one of the best courses I have ever done. You can also do it for free if you do not want the certificate.
 
Thanks for starting this thread, FP certainly looks like a paradigm I'd want to become comfortable with. I hope you dont mind if I occassionally PM you on FP?

Edit: you think it'd be useful to start familiarising myself with say Haskell to sink my teeth into FP?
You're more than welcome to .

As for Haskell, it's what we call a pure functional language, meaning you won't be able to mix in other paradigms like you can with Java, Swift, C#, PHP, Rust, Ruby, Javascript, ... It's a powerful language but at the same time very complicated. The easier road would always be to start within the language that you are currently most familiar with and expand from there. Happy to help you get started if it's something other than the four I have been covering.

Naturally a language like Haskell would expose you to FP concepts far greater than what is currently supported in the more popular languages e.g. Higher kinded types., but at the same time expose you to some of the current difficulties in FP; event / state management; in that regard OOP is still the easier route. Hence many approaches to employing FP in your code, talk about layers of code:
  • Object layer (OOP) -- roughly 10 to 20%
  • Value Layer (FP) -- the bulk 80 to 90%
Ostensively the value layer can cover most of the framework of your applications, including the models, and much of the underlying view code (MVC: Model, View, Controller), however when it comes to the controller, state and mutability, OOP is certainly the easier route, hence I still use OOP for events management; trapping for example:
  • Mouse clicks
  • Keyboard presses
  • Button preses
  • Touch zones (tablets, phones)
I.e. We contain the areas where we use state & mutability, it's certainly not needed everywhere, neither does it add value, and more often than not can simply overcomplicate things, as for example: Java's key designers have posited.

Anyway back to Haskell, it's a very different langauge, and many of the things you were familiar with won't be there; this can be very daunting; so whilst it still remains one of the best ways to completely explore the paradigm, it's also can be one of the most confusing. The tools for Haskell are however brilliant, so too the documentation + they even created Playgrounds (fast and fun way to explore code) similar to what Apple introduced with Swift.

As for languages that are multi paradigm, there are a few that are far more capable when it comes to FP e.g. Rust, Swift, Python, Ruby, Javascript, ... C# and Java whilst playing a catch up game, already have quite a bit -- primarily they're missing a lot of the type stuff (e.g. Generics, Custom Operators, Higher Kinded Types), certainly none of the stuff you'd want to start with.

Btw if you're a C# programmer you might also want to consider F# as it ties in well with the .Net frameworks and is a powerful FP focused language, but like Haskell, expect to be confused by the syntax.
 
Last edited:
I would really recommend starting out by doing the Coursera course on Functional Programming. It is one of the best courses I have ever done. You can also do it for free if you do not want the certificate.
I would also suggest you just watch some videos on Youtube, there are some very good university level courses on FP, e.g.
..but at the same time, just look for topic specific videos e.g map, reduce, ...
 
Last edited:
Top
Sign up to the MyBroadband newsletter
X