In the Melbourne ADUG meeting last night, I showed some of the functionality of the Spring4D collections, and showed how they allow you to take a functional programming approach.
@Paul_McGee mentioned fluent style programming, a style that looks very similar to functional programming. Both approaches use method chaining.
I said how much I dislike “Fluent Style”. Paul was surprised by this and asked why.
At the risk of provoking a language war, I’ll explain:
My main objection to fluent style is that it looks like functional programming, but behaves quite differently. The appearance of fluent code is misleading.
Functional programming uses functions with no side effects that return a new value. Ideally, this return value is immutable.
In contrast, the functions in fluent style rely on side effects, modifying the underlying object and returning it as the result.
Using the Spring4D collections, which allow a functional approach, you can write:
DisplayCountries(CountryList.Where(TCountryFns.GDPIsAtLeast(5E11)).
Where(TCountryFns.RegionCodeIs('ECA')));
This can be expanded to
var RichCountries := CountryList.Where(TCountryFns.GDPIsAtLeast(5E11));
var RichECACountries := RichCountries.Where(TCountryFns.RegionCodeIs('ECA'));
DisplayCountries(RichECACountries);
You could then do
var RichEAPCountries := RichCountries.Where(TCountryFns.RegionCodeIs('EAP'));
DisplayCountries(RichECACountries.Concat(RichEAPCountries));
This all works very nicely in Spring4D.
However, it would not have worked if it was using a fluent approach;
RichCountries, RichECACountries and RichEAPCountries would all refer to the same object, and would be empty after applying the three where calls.
The functional approach of Spring4D works well with multi-threading; you can pass an Enumerable to multiple threads and they can all use the iterators knowing that the other threads aren’t going to conflict with them.
Fluent can work, but it’s easy to introduce bugs. If you do want to use Fluent functions, I’d prefer to call them like procedures and ignore the results. That makes it obvious that there will be side effects.
So the fluent style code
R := A(...).B(...).C(...).D(...)
would be less misleading if coded as
R := A(...);
R.B(...);
R.C(...);
R.D(...);
But if you have the option of pure functions like you find in Spring4D, they give you more resilient code, and chaining those method calls can make code clearer.