www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to define infix function

reply greatsam4sure <greatsam4sure gmail.com> writes:
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
Jun 02 2018
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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
Jun 02 2018
next sibling parent greatsam4sure <greatsam4sure gmail.com> writes:
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
Jun 02 2018
prev sibling parent reply KnightMare <black80 bk.ru> writes:
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
Apr 11
parent KnightMare <black80 bk.ru> writes:
 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
Apr 11
prev sibling parent reply Neia Neutuladh <neia ikeran.org> writes:
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); }
Jun 02 2018
next sibling parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
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
Jun 02 2018
next sibling parent Meta <jared771 gmail.com> writes:
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.
Jun 03 2018
prev sibling parent Andrea Fontana <nospam example.com> writes:
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 :)
Jun 04 2018
prev sibling parent greatsam4sure <greatsam4sure gmail.com> writes:
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
Jun 03 2018