Simple Functional Approach Example

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Reaction score
405
Location
I'm often asked for a simple & short example that demonstrates how the Functional paradigm is different from OOP or Imperative. Irrespective of paradigm it's often quite easy to get lost in the detail or implementation complexity (e.g. semigroups, functors, dependency injection, factory, visitor, ...), and miss the very basic differences in approach.

To demonstrate this I'm going to make use of an easy challenge, but before I provide any solutions I'd like to give anyone who'd like to attempt this a chance to submit their own solutions.

At the end of week (probably this coming Saturday or Sunday); I'll provide a solution for each of these paradigms, including describing how the approaches vary and a bit of an assessment of each of my solutions.

Challenge:
Recreate this binary triangle:
PHP:
1
0 1
1 0 1
0 1 0 1
Note:
1. the size of the triangle must be a parameter i.e. 6 instead of 4 would reproduce the following output:
PHP:
1
0 1
1 0 1
0 1 0 1
1 0 1 0 1
0 1 0 1 0 1
2. Your output should ideally exclude any unnecessary whitespace e.g. at the end of the line.

As for languages:
I have no particular preference; so pick your poison. I'll probably provide solutions for this in either C#, Java, Kotlin or Swift, or a combination of these. However I'll be quite happy to translate this to any language that supports the FP style plumbing I'll be using; so go ahead and ask.
 
Python:
Code:
def triangle(n):
  print '\n'.join([' '.join([str((i^j)&1) for j in range(i)]) for i in range(1,n+1)])
 
Last edited:
Thanks cguy

Ps. I'll also include an FP solution for Python.
 
C#

Code:
static string Triangle(int n)
{
  return String.Join(Environment.NewLine, Enumerable.Range(1, n).Select(i => Enumerable.Range(1, i).Select(j => (((i - 1) ^ j) & 1))).Select(f => String.Join(" ", f.ToArray())));
}

Edit: C# letting me down with having to scroll. Shortest. :( :p

Code:
static string Triangle(int n)
{
  return string.Join("\n",Enumerable.Range(1,n).Select(i=>Enumerable.Range(1,i).Select(j=>1&(j^i-1))).Select(k=>string.Join(" ", k)));
}
 
Last edited:
Thanks kripstoe; will also provide a FP solution for C#.
 
Scala:

For expression:
Code:
  def triangle(n: Int): String = {
    (for (i <- (1 to n)) yield Range(i, 0, -1).map(_ & 1).mkString(" ")).mkString("\n")
  }

Using two ranges:
Code:
  def triangle(n: Int): String = {
    (1 to n).map(i => Range(i, 0, -1).map(_ & 1).mkString(" ")).mkString("\n")
  }

Using two ranges with a reverse instead of the decreasing range:
Code:
  def triangle(n: Int): String = {
    (1 to n).map(i => (1 to i).reverse.map(_ & 1).mkString(" ")).mkString("\n")
  }
 
Last edited:
Excellent gkm; always good to see Scala.

FYI for everyone; I've wrapped up the FP solutions for Python, C#, Swift and Scala will now be added. If anyone is interested in Java or Kotlin or something else then please submit a solution.
 
Here is also a bit of an alternative option in Scala, making each line from the previous line by applying a function to the previous line, rather than calculating each character from scratch:

Code:
  def triangle(n: Int): String = {
    List.iterate("1", n)(s => if (s(0) == '1') "0 " + s else "1 " + s).mkString("\n")
  }
 
Here is also a bit of an alternative option in Scala, making each line from the previous line by applying a function to the previous line, rather than calculating each character from scratch:

Code:
  def triangle(n: Int): String = {
    List.iterate("1", n)(s => if (s(0) == '1') "0 " + s else "1 " + s).mkString("\n")
  }

Clever!
 
[)roi(];21231557 said:
Agreed; except it needs a trim to remove some whitespace.

Thanks. :)

However, I do not see any whitespace that needs to be trimmed? The extra characters are added to the front, so there is no whitespace around the resulting string lines.

If I change the program to:
Code:
  def triangle(n: Int): String = {
    List.iterate("1", n)(s => if (s(0) == '1') "0." + s else "1." + s).mkString("\n")
  }

I get:
Code:
1
0.1
1.0.1
0.1.0.1
1.0.1.0.1
 
Here is also a bit of an alternative option in Scala, making each line from the previous line by applying a function to the previous line, rather than calculating each character from scratch:

Code:
  def triangle(n: Int): String = {
    List.iterate("1", n)(s => if (s(0) == '1') "0 " + s else "1 " + s).mkString("\n")
  }

:D Cool
 
Thanks. :)

However, I do not see any whitespace that needs to be trimmed? The extra characters are added to the front, so there is no whitespace around the resulting string lines.

If I change the program to:
Code:
  def triangle(n: Int): String = {
    List.iterate("1", n)(s => if (s(0) == '1') "0." + s else "1." + s).mkString("\n")
  }

I get:
Code:
1
0.1
1.0.1
0.1.0.1
1.0.1.0.1
Yip, my bad.
Your code is a similar to an iterative approach I had; you however got it right.
 
FYI Scala FP work up is also complete; my FP solutions have not surprisingly aligned uniformly across languages.

Also are there still no takers for either Java or Kotlin or something else?

Btw. Failing anything else I'll submit the conclusion to this challenge tomorrow evening or at the latest on Saturday.

Side question: are there any programmers who have adopted point free styles in their code?
 
[)roi(];21236293 said:
FYI Scala FP work up is also complete; my FP solutions have not surprisingly aligned uniformly across languages.

Also are there still no takers for either Java or Kotlin or something else?

Btw. Failing anything else I'll submit the conclusion to this challenge tomorrow evening or at the latest on Saturday.

Side question: are there any programmers who have adopted point free styles in their code?

I have done it a couple of times in PHP, I like it, makes sense to me, parts to form a whole.
 
I have done it a couple of times in PHP, I like it, makes sense to me, parts to form a whole.
Cool; my FP examples will certainly touch on this. i.e. reduced arity to lead to reduced cognition, easier composition, ...
 
I have mixed feelings about point free style code. I like it in DSL's (written by somebody else) where it gives an English like syntax. For application code, I am not so sure if it aids readability, since usually less though has gone into the naming of methods etc to make it readable and therefore maintainable. I think it is cool that it is possible to write code like that, but I am not able to figure out if it makes code easier to maintain, where at the end of the day, the bulk of software cost lies.
 
I have mixed feelings about point free style code. I like it in DSL's (written by somebody else) where it gives an English like syntax. For application code, I am not so sure if it aids readability, since usually less though has gone into the naming of methods etc to make it readable and therefore maintainable. I think it is cool that it is possible to write code like that, but I am not able to figure out if it makes code easier to maintain, where at the end of the day, the bulk of software cost lies.
Sounds to me like we may be talking at odds-on this one.

I'll review for any interested parties:
  • Point-free or tacit programming as the word implies is when something is "understood or implied without being stated".
  • Also as wikipedia states "function definitions do not identify the arguments (or "points") on which they operate.
IMO it's got little to do with the naming of functions, but rather speaks to avoiding unnecessary explicitness with parameters that are implied by composition; more specifically this style of coding directs us to design low arity composition points to more easily enable this. Which in turn leads to a more streamlined integration with FP algebras. i.e. majority of which as you know mathematically hinge on a single arity.

Here's a Scala example:

Assume I define the following higher order function:
PHP:
def alternationOf(fn: (Int) => String, n: Int): Array[String] ...

And I have a function from (Int) => String
PHP:
def zeroOrOnePattern(v: Int): String ...

I could either use it explicitly like this:
PHP:
println(alternationOf(v => zeroOrOnePattern(v), 6));

Or I could use it point-free like this
PHP:
println(alternationOf(zeroOrOnePattern, 6));

For the Java guys this is typically where Java method reference operators come into play:
PHP:
e.g. System.out::println
 
Last edited:
if that is the crux of the concept, then I would say that I mostly use "point-free" style
 
if that is the crux of the concept, then I would say that I mostly use "point-free" style
Yip that's the crux; simple concept.

...but with many benefits, for example:
  • Small functions == low cognition == less opportunity for bugs -- re it's not easy to build complex functions and still make them point-free i.e. you innately comply with clean code principles
  • Small arity makes functions inherently composable without any fancy plumbing required (DI/IOC), ultimately enabling more advanced FP algebras at no extra cost.
  • Pure functions == simple to test; no mocks needed. Arguably 80%+ of most projects can be pure with state restricted to IO only.
  • etc.

Extra:
Btw if anyone was wondering about multiple parameters functions; then yes these can be accommodated as follows:
  • Currying (mathematic concept taken from calculus) introduced by Haskell Curry, but also know as "Schönfinkel-ing" after Moses Schönfinkel on whose ideas Haskell Curry concepts were based.
  • Partial Application : Basically FP's alternative to dependency injection
Currying
Currying basically turns a multi parameter function into a single parameter function that returns another single parameter function, and so on until all parameters have been fulfilled and the function computes.

Partial Application
Partial Application is similar to Dependency Injection allowing pre-inject of parameter values into a function; essentially partially completing some of the parameters required by the base function. This pre-injected function then can be passed around and/or composed with other functions, etc.

Note:
Both of these concepts don't have to be designed into the base function because we typically create helper functions that will curry functions of any arity. More so it's even possible to switch the order that parameters need to be completed in.
Similarly with Partial Application, we typically create helpers functions to partially apply some of the parameter values, return a function representing only the missing parts with the other parameters pre-injected similar to DI.
 
Last edited:
Top
Sign up to the MyBroadband newsletter
X