mpen
mpen

Reputation: 283083

Languages that take chaining to the extreme?

So, I was just thinking about how cool chaining is and how it makes things easier to read. With a lot of languages, when applying a bunch of functions to a variable, you'd write something like this:

i(h(g(f(x))))

And you have to read it from right-to-left or inner-most to outer-most. You apply f first, then g, and so forth. But if it were chained, it would look more like

x|f|g|h|i

And you could read it like a normal human being. So, my question is, there has to be some languages that do it that way, what are they? Is that what these fancy-pants functional programming languages do?


Because of this, I usually end up creating a whole bunch of temp variables so that I can split it onto separate lines and make it more readable:

a = f(x)
b = g(a)
c = h(b)
what_i_really_wanted_all_along = i(c)

Where's with my magical language, you could still split it onto different lines, if they're getting too long, without needing intervening variables:

x | f
  | g
  | h
  | i

Upvotes: 2

Views: 537

Answers (8)

S.Lott
S.Lott

Reputation: 391952

Haskell. The following three examples are equivalent:

  • i(h(g(f(x)))) (Nested function calls)
  • x & f & g & h & i (Left-to-right chaining as requested)
  • (i . h . g . f)(x) (Function composition, which is more common in Haskell)

http://www.haskell.org/haskellwiki/Function_composition

http://en.wikipedia.org/wiki/Function_composition_(computer_science)

Upvotes: 2

Jonathan
Jonathan

Reputation: 2213

As has been previously mentioned, Haskell supports function composition, as follows:

(i . h . g . f) x, which is equivalent to: i(h(g(f(x))))

This is the standard order of operations for function composition in mathematics. Some people still consider this to be backward, however. Without getting too much into a debate over which approach is better, I would like to point out that you can easily define the flipped composition operator:

infixr 1 >>>, <<<
(<<<) = (.) -- regular function composition
(>>>) = flip (.) -- flipped function composition

(f >>> g >>> h >>> i) x
    -- or --
(i <<< h <<< g <<< f) x

This is the notation used by the standard library Control.Category. (Although the actual type signature is generalized and works on other things besides functions). If you're still bothered by the parameter being at the end, you can also use a variant of the function application operator:

infixr 0 $
infixl 0 #
f $ x = f x -- regular function application
(%) = flip ($) -- flipped function application

i $ h $ g $ f $ x
    -- or --
x % f % g % h % i

Which is close to the syntax you want. To my knowledge, % is NOT a built-in operator in Haskell, but $ is. I've glossed over the infix bits. If you're curious, thats a technicality that makes the above code parse as:

(((x % f) % g) % h) % i -- intended

and not:

x % (f % (g % (h % i))) -- parse error (which then leads to type error)

Upvotes: 1

Serguei
Serguei

Reputation: 2958

C# extension methods accomplish something very close to your magical language, if a little less concisely:

x.f()
 .g()
 .h()
 .i();

Where the methods are declared thus:

static class Extensions 
{
    static T f<T>(this T x) { return x; }
    static T g<T>(this T x) { return x; }
    ...
}

Linq uses this very extensively.

Upvotes: 2

Dr. belisarius
Dr. belisarius

Reputation: 61046

I am not suggesting you could use Mathematica if you don't do some math usually, but it certainly is flexible enough for supporting Postfix notation. In fact, you may define your own notation, but let's keep with Postfix for simplicity.

You may enter:

Postfix[Sin[x]]

To get

x // Sin  

Which translates to Postfix notation. Or if you have a deeper expression:

MapAll[Postfix, Cos[Sin[x]]]

To get:

(Postfix[x]//Sin)//Cos  

Where you may see Postfix[x] first, as for Mathematica x is an expression to be evaluated later.

Conversely, you may input:

x // Sin // Cos  

To get of course

Cos[Sin[x]]  

Or you can use an idiom very frequently used, use Postfix in Postfix form:

Cos[x] // Postfix

To get

x // Cos

HTH!

BTW: As an answer to Where's with my magical language,? , see this:

(x//Sin 
  // Cos
  // Exp 
  // Myfunct)  

gives

Myfunct[E^Cos[Sin[x]]]  

PS: As an excercise to the readers :) ... How to do this for functions that take n vars?

Upvotes: 1

Zecc
Zecc

Reputation: 4340

Well, you can do this in JavaScript and its relatives:

function compose()
{
    var funcs = Array.prototype.slice.call(arguments);
    return function(x)
    {
        var i = 0, len = funcs.length;
        while(i < len)
        {
            x = funcs[i].call(null, x);
            ++i;
        }
        return x;
    }
}

function doubleIt(x) { print('Doubling...'); return x * 2; }

function addTwo(x) { print('Adding 2...'); return x + 2; }

function tripleIt(x) { print('Tripling...'); return x * 3; }

var theAnswer = compose(doubleIt, addTwo, tripleIt)( 6 );
print( 'The answer is: ' + theAnswer );
// Prints:
//   Doubling...
//   Adding 2...
//   Tripling...
//   The answer is: 42

As you can see, the functions read left-to-right and neither the object nor the functions need any special implementation. The secret is all in compose.

Upvotes: 3

elmattic
elmattic

Reputation: 12184

Yes, with F# you have a pipeline operator |> (also called forward pipe operator, and you have a backward pipe <|).

You write it like: x |> f |> g |> h |> i

Check this blog post that gives a good idea of real life usage.

Upvotes: 5

DVK
DVK

Reputation: 129481

It's not exclusive to functional programming, though it probably best implemented in functional languages, since the whole concept of function composition is squarely in the functional programming's domain.

For one thing, any language with object-oriented bent has chaining for methods which return an instance of the class:

obj.method1().method2().method3(); // JavaScript
MyClass->new()->f()->g()->i(); # Perl

Alternately, the most famous yet the least "programming-language" example of this chaining pattern would be something completely non-OO and non-functional ... you guessed it, pipes in Unix. As in, ls | cut -c1-4 | sort -n. Since shell programming is considered a language, I say it's a perfectly valid example.

Upvotes: 3

Michael
Michael

Reputation: 20069

What you're describing is essentially the Fluent Interface pattern.

Wikipedia has a good example from a number of languages:

http://en.wikipedia.org/wiki/Fluent_interface

And Martin Fowler has his write up here:

http://www.martinfowler.com/bliki/FluentInterface.html

As DVK points out - any OO language where a method can return an instance of the class it belongs to can provide this functionality.

Upvotes: 2

Related Questions