10

I've heard that in javascript world there is an emergent ecosystem of functional libraries (like lodash, rxjs but also es6 promise) and also in the java world (guava or Java8 with lambdas).

Is there any functional programming attempt in apex?

2
  • 4
    Just like Java, Apex would require changes to be a good language on which to build such libraries.
    – Keith C
    Commented Jul 6, 2015 at 14:13
  • 1
    Technically, it should be feasible: e.g. the functional language Scala compiles to Java bytecode. But Salesforce would need to have a compelling reason to make such a non-trivial effort. I think it would have to come from Salesforce's own developers. Any of those here who are looking at this question? Commented May 4, 2016 at 13:58

3 Answers 3

9

Apex is a very static language. For example, you cannot reliably determine the class name of an object at run time (Can I determine the class name of an object instance at run-time?). Generics were removed from the language starting with API version 26.0, except for leftovers like collections.

There is a very small surface of the language where something dynamic can happen and it's mostly related to SObject class which is a syntactic sugar over a Map<String, Object>, and offers a way to dynamically get and set field values.

Luckily, the range of types of SObject fields are limited, so each type can be covered with an appropriate method. This allows you to do replicate some capabilities of lodash, like plucking fields:

public class Pluck {
    public static List<String> strings(List<SObject> records, Schema.SObjectField field) {
            List<String> results = new List<String>();
            for (SObject rec : records) {
                results.add((String)rec.get(field));
            }
            return results;
    } 
}

Collections of SObject and subclasses are implemented in an unexpected way, and you can assign a collection of superclass to a collection of subclass, and the other way around (more details are available on Map<Object, List<SObject>> cannot be cast to Map<String, List<Account>>)=:

List<SObject> objects = new List<SObject>();
List<Account> accounts = objects; // compiles!

List<Account> accounts = new List<Account>();
List<SObject> objects = accounts; // compiles as well!

An SObject list is an instance of any SObject “subclass” list (you can sneak any SObject subclass into a collection of any other SObject subclass and wait for it to blow at runtime)! This can be exploited with methods which return collections of SObject which can be assigned to collections of subclasses without a cast:

// filter returns a List<SObject>, but can be assigned to List<Account>
List<Account> filtered = SomeClass.filter(...);

Limited range of types in fields and SObject collection can be used to get further lodash-like capabilities, like grouping:

public class GroupBy {
    public static Map<String, List<sObject>> strings(List<sObject> records, Schema.SObjectField field, Type listType) {
            Map<String, List<SObject>> grouped = new Map<String, List<SObject>>();
            for (sObject rec : records) {
                String key = (String)rec.get(field);
                if (!grouped.containsKey(key)) {
                    grouped.put(key, (List<SObject>)listType.newInstance());
                }
                grouped.get(key).add(rec);
            }
            return grouped;
        }

    public static Map<String, List<sObject>> strings(List<sObject> records, Schema.SObjectField field) {
        return strings(records, field, List<SObject>.class);
    }
}

Outside SObject, everything has to either be of fixed type or not type safe.

For example, a case insensitive string always works with a fixed type, String. Convenience methods can be written on it to make it easier to work with collections of String, like public static List<CaseInsensitiveString> listOf(Iterable<String> strings).

An example of type-unsafe class would be an Optional which mimics Guava’s or Java 8’s Optional. Since classes cannot be parametrised, we're forced to work with Object and cast it ourselves (or again decide to support just the limited range of types, like primitives):

public class Optional {
    ...  
    public static Optional of(Object value)
    public Object get()
}

Optional opt = Optional.of(3);
Integer result = (Integer) Optional.get();

One way out would be to create a language that transpiles to Apex but offers better features (let’s call it Peak). When Optional<String> and Optional<Foo__c> are used in Peak, the transpiler would create an OptionalString and OptionalFoo__c classes in Apex which would be type-safe.

Until then, I have a small apex-fp library on github which contains most of what I've described above.

2

I was searching for the same but there is almost no information available related to functional programming in salesforce. I did my own research of implementing RXjs in Lightning Framework by creating an autocomplete for an input text. see http://www.ngpillango.com/?p=134 It works quite elegantly but downside is that you have to disable salesforce locker service for it as it's need access to native dom events. Hopefully salesforce will release some wrappers to overcome this.

0

Pure functional programming is almost impossible in Apex currently. R.apex(https://github.com/Click-to-Cloud/R.apex) is a nice attempt to provide pseudo functional programming.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .