Haxe Code Cookbook
Haxe programming cookbookAbstract typesPipe using Abstract Operator Overloading

Pipe using Abstract Operator Overloading

Reading time: 1 minute

The following example demonstrates how the pipe operator is used to clean up nested function calls with Abstract Operator Overloading.

Motivation

Function calls can take up a lot of real estate when transforming data. A developer may need to transform data through multiple utility functions. In doing so the developer may create temporary variables to transfer value from and to each function or they may write code using function calls as function arguments. Piping data from one function to another and assigning the data to a single identifier cleans up unnecessary variables while still showing the developers intention.

Abstract Pipe

abstract Pipe<T>(T) to T {
    public inline function new(s:T) {
        this = s;
    }

    @:op(A | B)
    public inline function pipe1<U>(fn:T->U):Pipe<U> {
        return new Pipe(fn(this));
    }

    @:op(A | B)
    public inline function pipe2<A, B>(fn:T->A->B):Pipe<A->B> {
        return new Pipe(fn.bind(this));
    }

    @:op(A | B)
    public inline function pipe3<A, B, C>(fn:T->A->B->C):Pipe<A->B->C> {
        return new Pipe(fn.bind(this));
    }

    @:op(A | B)
    public inline function pipe4<A, B, C, D>(fn:T->A->B->C->D):Pipe<A->B->C->D> {
        return new Pipe(fn.bind(this));
    }
}

Usage

inline function addWorld(str:String):String {
    return str + " world!";
}

inline function capitalize(str:String):String {
    return str.toUpperCase();
}

inline function count(str:String):Int {
    return str.length;
}

function main() {
    // function call as argument version
    var nestedHelloWorld = capitalize(addWorld("Hello"));
    trace(nestedHelloWorld); // HELLO WORLD!

    // update variable version
    var hello = "Hello";
    hello = addWorld(hello);
    hello = capitalize(hello);
    trace(hello); // HELLO WORLD!

    // piped version
    var helloWorld:String = new Pipe("Hello")
      | addWorld
      | capitalize;
    trace(helloWorld); // HELLO WORLD!

    // piped version changing type from String to Int
    var helloWorldCount:Int = new Pipe("Hello")
      | addWorld
      | capitalize
      | count;
    trace(helloWorldCount / 2); // 6
}

Learn about Haxe Abstracts here: https://haxe.org/manual/types-abstract.html


Contributors:
Last modified:
Created:
Category:  Abstract types