Overview

Helperl

Helperl is a wrapper library for jinterface, aimed at making construction and pattern matching convenient.

Note that this is an early version, please feel free to submit reports of bugs and inconsistencies.

Most of the examples are available as unit tests in class net.shambolica.helperl.HelperlCoreQuickStartExamplesTest

Getting started

Precompiled JARs can be obtained from Maven Central and from the Bitbucket repository.

If using Maven, add the following dependency, for version 0.2.0 for example:

<dependency>
    <groupId>net.shambolica.helperl</groupId>
    <artifactId>helperl-core</artifactId>
    <version>0.2.0</version>
</dependency>

Quick start: Conversion/Construction.

First of all, the class named ET (Erlang Terms) is used for data construction, so static import it:

import static net.shambolica.helperl.ET.*;

erl(...)

Simple conversion for values can usually be handled by erl(). For example:

erl(12345) will be converted to the equivalent OtpErlangInt value.

Strings will be converted into UTF8-encoded OtpErlangBinary, Collections will be converted into OtpErlangLists, etc.

Another option is to go for more specific conversions: eAtom(), eBinary(), and eNumber().

Tuples and Lists

Tuples and lists can be constructed using eList() and eTuple. Note that both take Objects and use asObject(...) to convert them (see below).

Examples:

eList() -> []

eList(123, "abcde", eAtom("qwerty")) -> [123, <<"abcde">>, qwerty]

eTuple(123, "abcde", eAtom("qwerty")) -> {123, <<"abcde">>, qwerty}

Proplists

Proplists can be constructed using proplist(...), which takes either a collection or vararg array of:

  • 2-element tuples, which are added as-is.
  • Single atoms, which are converted a true-tuple, e.g. eAtom("xxx") -> eTuple(eAtom("xxx"),eAtom("true"))
  • 2-element object arrays, which are converted into 2-element tuples using eTuple()
  • Pairs of Objects will also be converted into 2-element tuples as above.

All other values will be ignored.

Example:

proplist(
    pair(111, "aaa"),
    eAtom("true"),
    eTuple("abcdef", 234),
    new Object[]{erl(111), erl("aaa")})

will be equivalent to

eList(
    eTuple(111, "aaa"),
    eTuple(eAtom("true"), eAtom("true")),
    eTuple("abcdef", 234),
    eTuple(111, "aaa"))

which would translate to

[{111,<<"aaa">>},{true,true},{<<"abcdef">>,234},{111,<<"aaa">>}]

General conversion

Look in net.shambolica.helperl.conversion.FromObject - the methods asObject(Object) and asObjectsArray(Object[]) will convert values according to their type, if necessary, including:

  • Numbers to the appropriate OtpErlang*.
  • Byte arrays to OtpErlangBinary.
  • Strings to UTF-8 encoded OtpErlangBinary.
  • OtpErlangObjects will pass as is.

Quick Start: Decomposition and Pattern Matching

Similarly to term construction, the class named EP (Erlang Patterns) is used for pattern construction, so static import it:

import static net.shambolica.helperl.EP.*;

This class contains constructors for various patterns. All are prefixed by a 'p' (for "Pattern"): pAny(), pIsInteger(), pSet() and so on.

CompositePattern

The base class for all patterns is CompositePattern, which implements two interesting methods:

    boolean matches(OtpErlangObject)
    Map<String,OtpErlangObject> match(OtpErlangObject)

Tuple and List patterns use asObject() to convert their parameters, so that for instance

pTuple(12345,"hello") will be the same as pTuple(erl(12345),eBinary("hello")).

matches() - match or no match.

The CompositePattern.matches() method checks whether a value is matched by a pattern, for example:

  • True: pIsInteger().matches(erl(12345)) - equivalent to is_integer(12345)
  • True: Equivalent to {12345,'hello',_}
    CompositePattern p = pTuple(erl(12345),eAtom("hello"),pAny());
    OtpErlangObject v = eTuple(eNumber(12345),eAtom("hello"),erl("xyz"));
    p.matches(v);
  • True: This time with {X,Y,_} when is_integer(X) andalso is_atom(Y)
    CompositePattern p = pTuple(pIsInteger(),pIsAtom(),pAny());
    OtpErlangObject v = eTuple(eNumber(12345),eAtom("hello"),erl("xyz"));
    p.matches(v);

match() - match with variable bindings.

The pattern p_(String name) is used to bind variables to values. This is used by the CompositePattern.match() method to return a map of bound values, or null in case of failed pattern match.

Variable names can be any string.

Examples:

  • p_("X").match(eAtom("hello")) -> X = eAtom("hello").
  • pTuple(p_("X"),p_("X")).match(eTuple(12345,12345)) -> X = eNumber(12345).
  • pTuple(p_("X"),p_("X")).match(eTuple(12345,"hello")) -> null, as the two elements differ.

When matching a literal value, it is better to use the value itself instead of the pattern, e.g. eTuple instead of pTuple.

Note that it is possible to use pAnd() to express 'andalso' guards, for example:

pAnd(
    pTuple(eAtom("request"), p_("FROM"), p("MESSAGE"))),
    pIsPid("FROM"),
    pIsTuple("MESSAGE"))