Functional programming for Salesforce Apex
null
values now compared in PrimitiveComparer
. Where relevant, null
is smaller than non null.OptionalDouble
and OptionalDecimal
values are final
.DoubleCollection
, DecimalCollection
and ObjectCollection
constructors take Iterable
instead of List
. Constructors are private and collections are build with of
to match SObjectCollection
.sf
(sfdx
) template.min
and max
to DoubleCollection
and DecimalCollection
AssignTo
to Modify
Fn
structureFn.MapTo
ObjectCollection
to serve as a target for object mappingsSObjectStream
apex-fp
, to avoid confusion with apex/up
for AWS LambdaMapTo
Fp
Project moved to SFDX
Transform
and resulting RecordTransform
functionality were moved to explicitly named CopyFields
to make the purpose clearer.
Experimental reduceType methods were removed in favour of mapToType style of methods, which return TypeCollection. This is similar to Java's Stream. For example,
Decimal totalAmount = Collection.of(opps).mapToDecimal(Opportunity.Amount).sum();
Current API is also unstable, and will possibly change to make the naming more consistent or to remove redundancies.
Previous naming favoured plural endings (groupByStrings
, pluckDoubles
), while new type collections use Java's singular convention.
One example of redundancy is Collection.of(opps).pluckDecimals(Opportunity.Amount)
which yields the same result as Collection.of(opps).mapToDecimal(Opportunity.Amount).asList()
.
Adds Transform
to support prototype-matching definition of SObjectToSobject
functions. Put simply,
Opportunity prototype = new Opportunity(Name = 'Test')
Collection.of(opps).mapAll(Transform.record(prototype));
will copy all defined field values on the provided prototype
to records in collection, overwriting any existing values for those fields. Other fields will not be touched.
Implements the general programme described in #4. Collection
class has been introduced as a view of underlying Apex collections which provides functional methods.
For simpler cases, the change brings more verbosity, for example:
Pluck.strings(Account.Name, accounts);
Collection.of(accounts).pluckStrings(Account.Name);
However, for more complex cases, the readability is improved, and the library is more flexible. Compare previously required nesting with chaining:
Pluck.strings(..., MapAll.records(..., Filter.field(...)));
Collection.of(accounts).filter(...).mapAll(...).pluckStrings(...);
The number of classes was reduced, and behaviour generally harmonized across different functionalities. Since the API was completely changed, a migration is required, which should be straightforward in most cases.