Tag “Uniform function call syntax”

I was fiddling with D during my vacation, when I had a rest from my house building. So I am going to write about the most exciting (from my point of view) feature of this programming language—the uniform function call syntax.

As it goes, an example is the best explanation.

import std.stdio;

int twice(int i) {
    return i * 2;
}

void main() {
    assert(twice(10) == 20);
}

There is nothing interesting. Code is executed as expected. But let’s make some changes.

import std.stdio;

int twice(int i) {
    return i * 2;
}

void main() {
    assert(10.twice == 20);  // Does it work?
}

Oh heck, that works! Yes, that is exactly what you think. You can call any non-member function like a member one of some type (generic or user-defined, never mind), if this function accepts argument of this type as a first parameter. In other words, you can write obj.func(arg1, arg2) instead of func(obj, arg1, arg2). In addition, you can omit parens, if there are no other arguments.

The first benefit of the feature is chaining:

import std.array;
import std.algorithm;

void main() {
    auto arr = [1, 2, 3, 4, 5]
        .filter!("a % 2")
        .map!("a * 2")
        .array();
    assert(arr == [2, 6, 10]);
}

dQuery is waiting for its heroes :)

The second one is some sort of monkey patching. However, you cannot totally change third-party class behavior. Because your non-member functions have no access to the private and protected members. But you can extend it.

And the last but not least, it significantly improves code readability.

import std.file;
import std.json;

void configure(string configPath) {
    // auto config = parseJSON(readText(configPath));  Never again!
    auto config = configPath.readText().parseJSON();
    // Do something useful...
}

P.S. Even though this feature had been mentioned in Andrei Alexandrescu’s book, “The D Programming Language” it was working for arrays only for a long time. But now it works for any type. I have checked it in DMD v2.062 compiler.