digitalmars.D - The Tail Operator '#' enables clean typechecked builders with minimal
- FeepingCreature (39/39) Jan 24 2019 A problem that's come up before is how to specify builders in a
- Eugene Wissner (7/46) Jan 25 2019 $ is a simple function in Haskell that is defined in a library,
- Kagamin (7/15) Jan 25 2019 This is shorter and cleaner:
- bauss (3/22) Jan 25 2019 And easy to implement:
- FeepingCreature (12/21) Jan 25 2019 Yeah but it doesn't look like assignment. And it's only as
A problem that's come up before is how to specify builders in a typechecked manner. In my language syntax experiment, Neat, I'd copied Haskell's '$' operator, which means "capture everything to the right of here in one set of parens", in order to avoid writing parentheses expressions: foo(2 + 2); // becomes foo $ 2 + 2; But what if we wanted the *opposite*? What if we wanted to capture everything to the *left* of an operator in one set of parens? Enter the tail operator: (2 + 2).foo; // becomes Why is this useful? Well, we've had the debate before about struct initializers. The irksome thing is that the language is *almost* there! We can already write function calls as assignments: foo(5); // becomes foo = 5; The main problem is that there's no way in the language to chain assignments together in that syntax. If we could, we could generate very clean looking builder expressions. But (((Foo.build .a = 3) .b = 4) .c = 5) .value; Just doesn't look good and isn't as easy to modify as it should be either. But with the tail operator, this becomes: Foo.build Which is pure, typechecked, easy to extend and still readable. What do you think?
Jan 24 2019
On Friday, 25 January 2019 at 07:24:10 UTC, FeepingCreature wrote:A problem that's come up before is how to specify builders in a typechecked manner. In my language syntax experiment, Neat, I'd copied Haskell's '$' operator, which means "capture everything to the right of here in one set of parens", in order to avoid writing parentheses expressions: foo(2 + 2); // becomes foo $ 2 + 2; But what if we wanted the *opposite*? What if we wanted to capture everything to the *left* of an operator in one set of parens? Enter the tail operator: (2 + 2).foo; // becomes Why is this useful? Well, we've had the debate before about struct initializers. The irksome thing is that the language is *almost* there! We can already write function calls as assignments: foo(5); // becomes foo = 5; The main problem is that there's no way in the language to chain assignments together in that syntax. If we could, we could generate very clean looking builder expressions. But (((Foo.build .a = 3) .b = 4) .c = 5) .value; Just doesn't look good and isn't as easy to modify as it should be either. But with the tail operator, this becomes: Foo.build Which is pure, typechecked, easy to extend and still readable. What do you think?$ is a simple function in Haskell that is defined in a library, the same as '+', '-' are just functions and not special operators as in D. In D you have to define each operator in the language itself and the compiler should understand them. Defining a language construct for each use case doesn't seems pretty to me, it makes the grammar overcomplicated.
Jan 25 2019
On Friday, 25 January 2019 at 07:24:10 UTC, FeepingCreature wrote:But with the tail operator, this becomes: Foo.build Which is pure, typechecked, easy to extend and still readable. What do you think?This is shorter and cleaner: Foo.build .a(3) .b(4) .c(5) .value;
Jan 25 2019
On Friday, 25 January 2019 at 08:33:51 UTC, Kagamin wrote:On Friday, 25 January 2019 at 07:24:10 UTC, FeepingCreature wrote:And easy to implement: https://run.dlang.io/is/0Z0GKbBut with the tail operator, this becomes: Foo.build Which is pure, typechecked, easy to extend and still readable. What do you think?This is shorter and cleaner: Foo.build .a(3) .b(4) .c(5) .value;
Jan 25 2019
On Friday, 25 January 2019 at 10:31:15 UTC, bauss wrote:Yeah but it doesn't look like assignment. And it's only as readable because the examples are oversimplified. Foo.build .property(source.property.call(bla, bla, bla).map!"a.BlaAttribute")) And it becomes much harder to understand the builder principle as compared to Foo.build bla).map!"a.BlaAttribute" We have operators for a reason.This is shorter and cleaner: Foo.build .a(3) .b(4) .c(5) .value;And easy to implement: https://run.dlang.io/is/0Z0GKb
Jan 25 2019