Thread overview
how to define infix function
Jun 02, 2018
greatsam4sure
Jun 02, 2018
Ali Çehreli
Jun 02, 2018
greatsam4sure
Apr 11, 2019
KnightMare
Apr 11, 2019
KnightMare
Jun 02, 2018
Neia Neutuladh
Jun 02, 2018
Simen Kjærås
Jun 03, 2018
Meta
Jun 04, 2018
Andrea Fontana
Jun 03, 2018
greatsam4sure
June 02, 2018
Sorry for the typo

is it possible to define infix function in D

3.min(5)// 3: where min is a function, works in D
3 min 5 // does not work.

thanks in advance
June 02, 2018
On 06/02/2018 02:44 PM, greatsam4sure wrote:

> is it possible to define infix function in D
>
> 3.min(5)// 3: where min is a function, works in D
> 3 min 5 // does not work.

This is called universal function call syntax (UFCS) in D. The idea is simple: You can pull the first argument out as if the function is a member function of that argument. So, in your case it already works because there is already a min() function that works with two (actually, many) parameters:

import std.algorithm;

void main() {
    assert(min(3, 5) == 3);
    assert(3.min(5) == 3);
}

However, many people don't like overusing it; it works well only in cases where the first parameter is arguably the "main character" in the operation. For example, min doesn't look good because all parameters have equal roles in that function.

Ali

June 02, 2018
On Saturday, 2 June 2018 at 21:44:39 UTC, greatsam4sure wrote:
> Sorry for the typo
>
> is it possible to define infix function in D
>
> 3.min(5)// 3: where min is a function, works in D
> 3 min 5 // does not work.
>
> thanks in advance

This is a horrible abuse of D's operator overloading discovered by FeepingCreature in the distant past.

You have to delimit your custom infix operator with slashes; you can't make `3 min 5` work, but you can make `3 /min/ 5` work.

Observe:

struct Min
{
    MinIntermediate!T opBinaryRight(string op, T)(T value) if (op == "/")
    {
        return MinIntermediate!T(value);
    }
}
struct MinIntermediate(T)
{
    T value;
    T opBinary(string op, T)(T value2) if (op == "/")
    {
        if (value < value2) return value;
        return value2;
    }
}
Min min;
void main()
{
    writeln(1 /min/ 2);
}
June 02, 2018
On Saturday, 2 June 2018 at 22:01:02 UTC, Ali Çehreli wrote:
> On 06/02/2018 02:44 PM, greatsam4sure wrote:
>
> > is it possible to define infix function in D
> >
> > 3.min(5)// 3: where min is a function, works in D
> > 3 min 5 // does not work.
>
> This is called universal function call syntax (UFCS) in D. The idea is simple: You can pull the first argument out as if the function is a member function of that argument. So, in your case it already works because there is already a min() function that works with two (actually, many) parameters:
>
> import std.algorithm;
>
> void main() {
>     assert(min(3, 5) == 3);
>     assert(3.min(5) == 3);
> }
>
> However, many people don't like overusing it; it works well only in cases where the first parameter is arguably the "main character" in the operation. For example, min doesn't look good because all parameters have equal roles in that function.
>
> Ali

Thanks for your reply to my question.
Your book: programming in D is real a great help learning D. I will appreciate it if your can expand the book to advance use of D. That is, dealing with D advance use Case. I discover that the D language is very advance but I am lock in the elementary yet don't know the way out. This is because D is the most Higher programming language that I ever use. Better still you can direct me to more materials about D. I am already familiar will all D books.

thanks
June 02, 2018
On Saturday, 2 June 2018 at 22:09:49 UTC, Neia Neutuladh wrote:
> On Saturday, 2 June 2018 at 21:44:39 UTC, greatsam4sure wrote:
>> Sorry for the typo
>>
>> is it possible to define infix function in D
>>
>> 3.min(5)// 3: where min is a function, works in D
>> 3 min 5 // does not work.
>>
>> thanks in advance
>
> This is a horrible abuse of D's operator overloading discovered by FeepingCreature in the distant past.
>
> You have to delimit your custom infix operator with slashes; you can't make `3 min 5` work, but you can make `3 /min/ 5` work.
>
> Observe:
>
> struct Min
> {
>     MinIntermediate!T opBinaryRight(string op, T)(T value) if (op == "/")
>     {
>         return MinIntermediate!T(value);
>     }
> }
> struct MinIntermediate(T)
> {
>     T value;
>     T opBinary(string op, T)(T value2) if (op == "/")
>     {
>         if (value < value2) return value;
>         return value2;
>     }
> }
> Min min;
> void main()
> {
>     writeln(1 /min/ 2);
> }

And of course, this can be generalized:

struct Operator(alias fn, string operator = "/")
{
    static auto opBinaryRight(string op : operator, T...)(T value1)
    {
        struct Result
        {
            auto opBinary(string op : operator, U...)(U value2)
                if (__traits(compiles, fn(value1, value2)))
            {
                return fn(value1, value2);
            }
        }

        Result result;
        return result;
    }
}

unittest
{
    import std.algorithm.comparison;

    alias min = Operator!(std.algorithm.comparison.min);

    assert(1 /min/ 3 == 1);
}

Note also the use of static opBinaryRight, allowing one to eschew the 'min' variable.

All of this said, I would suggest not using this in prod - it's a neat trick that shows off some of D's power, but I don't see a case where this would be easier to understand than a straightforward function call.

--
  Simen
June 03, 2018
On Saturday, 2 June 2018 at 22:09:49 UTC, Neia Neutuladh wrote:
> On Saturday, 2 June 2018 at 21:44:39 UTC, greatsam4sure wrote:
>> [...]
>
> This is a horrible abuse of D's operator overloading discovered by FeepingCreature in the distant past.
>
> You have to delimit your custom infix operator with slashes; you can't make `3 min 5` work, but you can make `3 /min/ 5` work.
>
> Observe:
>
> struct Min
> {
>     MinIntermediate!T opBinaryRight(string op, T)(T value) if (op == "/")
>     {
>         return MinIntermediate!T(value);
>     }
> }
> struct MinIntermediate(T)
> {
>     T value;
>     T opBinary(string op, T)(T value2) if (op == "/")
>     {
>         if (value < value2) return value;
>         return value2;
>     }
> }
> Min min;
> void main()
> {
>     writeln(1 /min/ 2);
> }

thanks
June 03, 2018
On Saturday, 2 June 2018 at 23:17:48 UTC, Simen Kjærås wrote:
> On Saturday, 2 June 2018 at 22:09:49 UTC, Neia Neutuladh wrote:
>> On Saturday, 2 June 2018 at 21:44:39 UTC, greatsam4sure wrote:
>>> Sorry for the typo
>>>
>>> is it possible to define infix function in D
>>>
>>> 3.min(5)// 3: where min is a function, works in D
>>> 3 min 5 // does not work.
>>>
>>> thanks in advance
>>
>> This is a horrible abuse of D's operator overloading discovered by FeepingCreature in the distant past.
>>
>> You have to delimit your custom infix operator with slashes; you can't make `3 min 5` work, but you can make `3 /min/ 5` work.
>>
>> Observe:
>>
>> struct Min
>> {
>>     MinIntermediate!T opBinaryRight(string op, T)(T value) if (op == "/")
>>     {
>>         return MinIntermediate!T(value);
>>     }
>> }
>> struct MinIntermediate(T)
>> {
>>     T value;
>>     T opBinary(string op, T)(T value2) if (op == "/")
>>     {
>>         if (value < value2) return value;
>>         return value2;
>>     }
>> }
>> Min min;
>> void main()
>> {
>>     writeln(1 /min/ 2);
>> }
>
> And of course, this can be generalized:
>
> struct Operator(alias fn, string operator = "/")
> {
>     static auto opBinaryRight(string op : operator, T...)(T value1)
>     {
>         struct Result
>         {
>             auto opBinary(string op : operator, U...)(U value2)
>                 if (__traits(compiles, fn(value1, value2)))
>             {
>                 return fn(value1, value2);
>             }
>         }
>
>         Result result;
>         return result;
>     }
> }
>
> unittest
> {
>     import std.algorithm.comparison;
>
>     alias min = Operator!(std.algorithm.comparison.min);
>
>     assert(1 /min/ 3 == 1);
> }
>
> Note also the use of static opBinaryRight, allowing one to eschew the 'min' variable.
>
> All of this said, I would suggest not using this in prod - it's a neat trick that shows off some of D's power, but I don't see a case where this would be easier to understand than a straightforward function call.
>
> --
>   Simen

That is interesting. I don't know yet whether it's good or bad, but certainly, it's interesting.
June 04, 2018
On Saturday, 2 June 2018 at 23:17:48 UTC, Simen Kjærås wrote:
> unittest
> {
>     import std.algorithm.comparison;
>
>     alias min = Operator!(std.algorithm.comparison.min);
>
>     assert(1 /min/ 3 == 1);
> }
>

Why not:

alias Δ = Operator!(std.algorithm.comparison.min);
assert(1 /Δ/ 3 == 1);

To improve readibility :)
April 11, 2019
On Saturday, 2 June 2018 at 22:01:02 UTC, Ali Çehreli wrote:
> On 06/02/2018 02:44 PM, greatsam4sure wrote:
> > is it possible to define infix function in D
> > 3.min(5)// 3: where min is a function, works in D
> > 3 min 5 // does not work.
> This is called universal function call syntax (UFCS) in D.
> Ali

UFCS is not same as infix functions.
infix allow to u write code like:

1)for (i in 0 to 10 step 2) // `in`(can be keyword too), `to` and `step` can be some functions that change range or something
2) auto shiftedRes = someVar shr 13; // `shr` is infix function too

u can use infix function with 1arg without any parentheses.
why this need? how it can be useful? look at Kotlin lang.
pure functional programming.
it can be useful for code looks like LINQ(.NET): DB, UI...

and I think UFCS should be improved too: function with 1arg can be written without parenthesis too. for example
some declarations:
class Task<T> { .. };
Task<Buffer> asyncRead( File file ) { .. }
T await!(T)( Task<T> task ) { .. }
we can use await like:
auto buf = asyncRead( file ).await();
or
auto buf = await( asyncRead( file )); // I like spaces between fn-names and args
but more clear IMO:
auto buf = await asyncRead( file ); // less parenthesis

more improvements:
1) see Kotlin passing lambda as last parameter
https://kotlinlang.org/docs/reference/lambdas.html#passing-a-lambda-to-the-last-parameter

2) Kotlin/when with pattern matching. dont need change current `switch` instruction. and we can make `when` as expression (look Kotlin samples)

3) scope functions https://kotlinlang.org/docs/reference/scope-functions.html
with(button) { text = "hello"; background = Colors.Yellow; }
text & background are props of some Button class for instance button. {} is a lambda as last arg
April 11, 2019
> u can use infix function with 1arg without any parentheses.
UPD
with 2args
arg1 `infix func` arg2

latter I told about UFCS with 1arg
`UFCS func` arg1