digitalmars.D - Eliminate assert and lazy from D?
- Andrei Alexandrescu (15/15) Oct 12 2009 Right now, the language has enough power to express assert as a library
- Robert Jacques (12/27) Oct 12 2009 Well, a lazy 'variable' is really a delegate of an expression, so implic...
- Andrei Alexandrescu (11/49) Oct 12 2009 It's simpler actually:
- Adam D. Ruppe (9/15) Oct 12 2009 What about static assert? Can it be moved to the library too?
- Robert Jacques (6/11) Oct 12 2009 On Tue, 13 Oct 2009 01:17:19 -0400, Adam D. Ruppe
- Andrei Alexandrescu (4/20) Oct 12 2009 Yah, me too, enforce in particular is a happy beneficiary.
- Chris Nicholson-Sauls (10/16) Oct 15 2009 It randomly occurred to me earlier today that one *could* implement stat...
- bearophile (6/12) Oct 12 2009 I refuse that critics about lazy. They know D far less than me.
- Andrei Alexandrescu (18/58) Oct 12 2009 I use lazy too, it is sometimes useful. The problem is that lazy is very...
- bearophile (7/14) Oct 12 2009 I was talking about language design in general, it was very in-topic in ...
- bearophile (8/11) Oct 12 2009 Sorry, I'm not a computer scientist, and surely I am not a language desi...
- Craig Black (6/26) Oct 13 2009 Since it seems there are fundamental changes already going into D 2.0, I...
- language_fan (10/31) Oct 15 2009 I thought the priorities were
- Frank Benoit (11/33) Oct 12 2009 I have seen lazy only used in its own show case. In log functions. In
- Andrei Alexandrescu (4/38) Oct 12 2009 I'm hoping that template variadics + arrays of Variant cover all needs.
- Frank Benoit (10/51) Oct 12 2009 Yes, this is, both are functions that try to help the programmer itself
- Michel Fortin (9/13) Oct 13 2009 Hum, side effects...
- Andrei Alexandrescu (17/67) Oct 13 2009 I'm wary about magic capabilities that are reserved only to the core
- bearophile (4/7) Oct 13 2009 Have you seen the asm produced by a small console D2 program? Even if yo...
- Jacob Carlborg (3/42) Oct 13 2009 Templates don't work as virtual methods. Arrays of variants will
- Jeremie Pelletier (13/35) Oct 12 2009 lazy is a great feature of D, although you need some sort of usage
- Frank Benoit (8/16) Oct 12 2009 ref and out are not the same category of weirdness for the caller. the
- language_fan (3/6) Oct 15 2009 Call by name has its uses. E.g. custom control structures, infinite list...
- Kagamin (3/6) Oct 13 2009 I second this :)
- Justin Johansson (12/21) Oct 13 2009 I third this.
- Michel Fortin (25/30) Oct 13 2009 According to the spec, 'assert' also allows the compiler to know
- Jason House (4/18) Oct 13 2009 You should be throwing AssertError
- Steven Schveighoffer (5/23) Oct 13 2009 With macros, this can be solved without lazy.
- Don (9/31) Oct 13 2009 assert: should remain. It is important to the compiler. I can easily
- Kagamin (11/17) Oct 13 2009 how about this?
- downs (2/14) Oct 13 2009 It's true! :)
- Denis Koroskin (3/20) Oct 13 2009 Wow, indeed!
- Andrei Alexandrescu (23/43) Oct 13 2009 Gosh!!! What's happening over here? I even tried this:
- Don (2/54) Oct 13 2009 There's a bug report about it, from Sean: bugzilla 1069.
- Leandro Lucarella (15/64) Oct 13 2009 What is the relation between assert and pure/nothrow? Is assert allowed?
- Jeremie Pelletier (11/67) Oct 13 2009 It works for the reason you said, assertions either guard against an
- Andrei Alexandrescu (8/80) Oct 13 2009 I think that's sensible, and thanks all for revealing reasons for assert...
- Jeremie Pelletier (7/91) Oct 13 2009 I wouldn't mind lazy going away, its something that can be 100% covered
- Steven Schveighoffer (6/8) Oct 13 2009 Do you mean lazy in the way that lazy variadic functions *imply* lazy vi...
- Max Samukha (3/20) Oct 13 2009 Yes, it is documented. "Lazy Variadic Functions" on "Functions" page.
- Andrei Alexandrescu (3/27) Oct 13 2009 Awesome. I'll replace the use of lazy in enforce() with that.
- downs (3/32) Oct 13 2009 Here is a funny consequence of this amusing fact:
- Chris Nicholson-Sauls (3/18) Oct 13 2009 That's... just beautiful...
- Andrei Alexandrescu (3/25) Oct 13 2009 Not getting it... could someone please explain?
- Jeremie Pelletier (31/58) Oct 13 2009 From what I get, he has something like this:
- downs (8/93) Oct 14 2009 Very close. There's another workaround required to enable the = {} synta...
- Jeremie Pelletier (5/27) Oct 13 2009 If you forget the fact that he is using GL's immediate mode which is
- Vladimir Panteleev (8/22) Oct 13 2009 No one seems to have mentioned this, but please don't overlook that when...
- Steven Schveighoffer (7/21) Oct 13 2009 How to trigger assert when no -debug or -release flag is set? Is there ...
Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality? Andrei
Oct 12 2009
On Tue, 13 Oct 2009 00:33:57 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality? AndreiWell, a lazy 'variable' is really a delegate of an expression, so implicit conversion of an expression to a delegate would be one way to remove lazy. (Not sure how practical/easy that is though) And then assert (I think) becomes void assert( bool delegate() expr, string delegate() msg ) { debug { if(!expr) throw new Exception(msg); } }
Oct 12 2009
Robert Jacques wrote:On Tue, 13 Oct 2009 00:33:57 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Yah, that's how the feature was initially proposed.Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality? AndreiWell, a lazy 'variable' is really a delegate of an expression, so implicit conversion of an expression to a delegate would be one way to remove lazy. (Not sure how practical/easy that is though)And then assert (I think) becomes void assert( bool delegate() expr, string delegate() msg ) { debug { if(!expr) throw new Exception(msg); } }It's simpler actually: debug void assert(T)( T expr, string delegate() msg ) { if(!expr) throw new Exception(msg); } else void assert(T)( T delegate(), string delegate() ) { } Hm, actually it's more complicated than your version :o). Andrei
Oct 12 2009
On Mon, Oct 12, 2009 at 11:33:57PM -0500, Andrei Alexandrescu wrote:Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d.What about static assert? Can it be moved to the library too? If not, it seems kinda weird that assert() is just a lib function, but if you put static before it, it becomes a completely different thing.I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that.I pretty rarely use it, but I'd be sad to see it go - it really does make a few things more elegant. -- Adam D. Ruppe http://arsdnet.net
Oct 12 2009
On Tue, 13 Oct 2009 01:17:19 -0400, Adam D. Ruppe <destructionator gmail.com> wrote: [snip]I use lazy for C function wrapping (i.e. converting C error codes to exceptions and/or taking a corrective action based on the error code and re-running the C function).I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that.I pretty rarely use it, but I'd be sad to see it go - it really does make a few things more elegant.
Oct 12 2009
Adam D. Ruppe wrote:On Mon, Oct 12, 2009 at 11:33:57PM -0500, Andrei Alexandrescu wrote:That kinda takes the wind out of the sails of the "remove assert" ship.Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d.What about static assert? Can it be moved to the library too? If not, it seems kinda weird that assert() is just a lib function, but if you put static before it, it becomes a completely different thing.Yah, me too, enforce in particular is a happy beneficiary. AndreiI personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that.I pretty rarely use it, but I'd be sad to see it go - it really does make a few things more elegant.
Oct 12 2009
Andrei Alexandrescu wrote:Adam D. Ruppe wrote:It randomly occurred to me earlier today that one *could* implement static assert in the library, albeit with a different (sensical) name, IF the compiler guaranteed a pragma(halt) or pragma(exit) that prematurely terminates a compile the same way current static assert does. Given that, a template in the library could output a custom message with pragma(msg) and then issue the halt. Its really just taking static assert's check expression away from it and giving it a new name... but still. The downside is having a pragma that every compiler would actually *have* to implement (to be worth using at least). -- Chris Nicholson-SaulsIf not, it seems kinda weird that assert() is just a lib function, but if you put static before it, it becomes a completely different thing.That kinda takes the wind out of the sails of the "remove assert" ship.
Oct 15 2009
Andrei Alexandrescu:This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/I refuse that critics about lazy. They know D far less than me. I like lazy as it is now, I use it often. It allows me to simulate (in a not perfect way, but sometimes acceptable) Python list comphrensions that no D dev seems interested in adding (or even understanding why they are useful, it seems) to the D language. General note: removing features from a language, making a language more general to allow programmers to implement such feature by themselves, sometimes looks positive. But you must keep in mind that it also has some drawbacks and costs. So you must always balance such costs with such advantages. For example compilation times and compilation memory may grow, the syntax may become a little worse, recovery in case of programmer/syntax mistakes may be a little worse, and error messages may become a little (or a lot) worse. The complexity of the language may increase, so people need a bit more time to learn the language (while learning higher-level built-in features often doesn't require a lot of time). A higher number of low level & general features (necessary to manually implement the higher level features that have being removed) make the language more flexible, but this is the kind of flexibility of an "amoeba", like Forth & Lisp, that despite being very flexible languages with 30-45+ years of life, can become hard to use, quite hard to understand, and so on. Languages that hope to become very widespread have to offer a very well chosen set of features, must not offer too much flexibility, they need a certain amount of rigidity and "internal constraints" that make them a bit less flexible and nice, but make them fit for teams of programmers to build large programs (see built-in feature you have to think about those factors too. Bye, bearophile
Oct 12 2009
bearophile wrote:Andrei Alexandrescu:I use lazy too, it is sometimes useful. The problem is that lazy is very much an oddball. It's a storage class that actually changes the type of a value. You sometimes need to add parens to get the value of a lazy variable, and sometimes not. It's unclear how lazy works with forwarding and how it interacts with templates. One litmus test is that it's very difficult to explain someone how lazy exactly works. I think it's a bad feature, and within reason we should clean the language of bad features.This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/I refuse that critics about lazy. They know D far less than me. I like lazy as it is now, I use it often. It allows me to simulate (in a not perfect way, but sometimes acceptable) Python list comphrensions that no D dev seems interested in adding (or even understanding why they are useful, it seems) to the D language.General note: removing features from a language, making a language more general to allow programmers to implement such feature by themselves, sometimes looks positive. But you must keep in mind that it also has some drawbacks and costs. So you must always balance such costs with such advantages. For example compilation times and compilation memory may grow, the syntax may become a little worse, recovery in case of programmer/syntax mistakes may be a little worse, and error messages may become a little (or a lot) worse. The complexity of the language may increase, so people need a bit more time to learn the language (while learning higher-level built-in features often doesn't require a lot of time). A higher number of low level & general features (necessary to manually implement the higher level features that have being removed) make the language more flexible, but this is the kind of flexibility of an "amoeba", like Forth & Lisp, that despite being very flexible languages with 30-45+ years of life, can become hard to use, quite hard to understand, and so on. Languages that hope to become very widespread have to offer a very well chosen set of features, must not offer too much flexibility, they need a certain amount of rigidity and "internal constraints" that make them a bit less flexible and nice, but make them fit for teams of programmers to build large programs (see the higher-level built-in feature you have to think about those factors too.IMHO what makes a language real hard to learn and use is the presence of misdesigned features. Then I'm not sure what you enjoy. Usually you're all for adding features (hey, you just brought up the switch again! isn't that ironic?) and cleaning up bad parts of the language, and now all of a sudden you wax poetic about this and that and the other, few of which have anything to do with the topic at hand. Next time I'll try a post "Let's keep lazy in the language" - that's bound to get a better response. Andrei
Oct 12 2009
Andrei Alexandrescu:IMHO what makes a language real hard to learn and use is the presence of misdesigned features.I don't agree, the situation is far more complex; good languages are the result of a fine balance between many opposed needs and constraints.and cleaning up bad parts of the language, and now all of a sudden you wax poetic about this and that and the other, few of which have anything to do with the topic at hand.I was talking about language design in general, it was very in-topic in this thread. I try to help, but often I fail... I am sorry.Next time I'll try a post "Let's keep lazy in the language" - that's bound to get a better response.Good. Inverting points of view is often positive in discussions. It's one of the bases of dialectics. Bear hugs, bearophile
Oct 12 2009
Andrei Alexandrescu Wrote:Usually you're all for adding features (hey, you just brought up the switch again! isn't that ironic?) and cleaning up bad parts of the language,Sorry, I'm not a computer scientist, and surely I am not a language designer (especially for a C++-class language), so you may see some contradictions in what I sometimes say :-) I have brought up the switch again because I was nervous, after spending some time to find a bug caused by the current design of the switch. There are classes of bugs that aren't easy to avoid, but I think with a less bug-prone switch I may avoid bugs like the one I have removed from my code. One of the most basic part of the Zen of D is to help programmers to avoid bugs, where possible. I hate the idea of having 3 different switches in the language (that's why I was not happy to see the static switch, because a better redesign of the *second* switch was in order). But the current situation of switch is not good for D yet. Bye, bearophile
Oct 12 2009
"bearophile" <bearophileHUGS lycos.com> wrote in message news:hb17v3$1e4r$1 digitalmars.com...Andrei Alexandrescu Wrote:Since it seems there are fundamental changes already going into D 2.0, I agree with bearophile. I don't like the syntax of switch, which is based on the old C switch syntax. Yuck! But I digress, this is not on topic. -CraigUsually you're all for adding features (hey, you just brought up the switch again! isn't that ironic?) and cleaning up bad parts of the language,Sorry, I'm not a computer scientist, and surely I am not a language designer (especially for a C++-class language), so you may see some contradictions in what I sometimes say :-) I have brought up the switch again because I was nervous, after spending some time to find a bug caused by the current design of the switch. There are classes of bugs that aren't easy to avoid, but I think with a less bug-prone switch I may avoid bugs like the one I have removed from my code. One of the most basic part of the Zen of D is to help programmers to avoid bugs, where possible. I hate the idea of having 3 different switches in the language (that's why I was not happy to see the static switch, because a better redesign of the *second* switch was in order). But the current situation of switch is not good for D yet. Bye, bearophile
Oct 13 2009
Tue, 13 Oct 2009 02:50:11 -0400, bearophile thusly wrote:Andrei Alexandrescu Wrote:I thought the priorities were 1) efficient systems programming features 2) metaprogramming fun 3) easy to use (if you come from c/c++) 4) cool new high level features (DbC etc.) 5) other features that make writing bug-free code easierUsually you're all for adding features (hey, you just brought up the switch again! isn't that ironic?) and cleaning up bad parts of the language,Sorry, I'm not a computer scientist, and surely I am not a language designer (especially for a C++-class language), so you may see some contradictions in what I sometimes say :-) I have brought up the switch again because I was nervous, after spending some time to find a bug caused by the current design of the switch. There are classes of bugs that aren't easy to avoid, but I think with a less bug-prone switch I may avoid bugs like the one I have removed from my code. One of the most basic part of the Zen of D is to help programmers to avoid bugs, where possible.I hate the idea of having 3 different switches in the language (that's why I was not happy to see the static switch, because a better redesign of the *second* switch was in order). But the current situation of switch is not good for D yet.A pattern matching switch which always returns a value, detects unhandled cases, matches more than just ints, enums, and strings, does not support break and goto, and automatically casts, would be nice.
Oct 15 2009
Andrei Alexandrescu schrieb:Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality? AndreiI have seen lazy only used in its own show case. In log functions. In Tango too it is used in log functions. I use delegates as function parameters often, but not lazy. This is because I may add parameters and on the caller site, IMO it must be obvious, this expression is not evaluated as others. Maybe it is acceptable to remove lazy and write logging statements with delegate and the curly braces. log({ "bla bla "~info }); A related issue with passing arguments, that i think needs a better solution in D are the variadic arg list. No magic param names and the possibility to pass this list - or a slice of it - to another function.
Oct 12 2009
Frank Benoit wrote:Andrei Alexandrescu schrieb:std.contracts.enforce also uses it.Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality? AndreiI have seen lazy only used in its own show case. In log functions. In Tango too it is used in log functions. I use delegates as function parameters often, but not lazy. This is because I may add parameters and on the caller site, IMO it must be obvious, this expression is not evaluated as others. Maybe it is acceptable to remove lazy and write logging statements with delegate and the curly braces. log({ "bla bla "~info });A related issue with passing arguments, that i think needs a better solution in D are the variadic arg list. No magic param names and the possibility to pass this list - or a slice of it - to another function.I'm hoping that template variadics + arrays of Variant cover all needs. Andrei
Oct 12 2009
Andrei Alexandrescu schrieb:Frank Benoit wrote:Yes, this is, both are functions that try to help the programmer itself and are part of the infrastructure. But is lazy useful for e.g. user libs? Is it useful in an API the user is not fully aware of? I mean if you call a function and you did not know the argument is lazy, it may have strange effects. This is why i would avoid lazy. I think the callers code should have the noticeable different syntax, and we already have that with the curly braces.Andrei Alexandrescu schrieb:std.contracts.enforce also uses it.Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality? AndreiI have seen lazy only used in its own show case. In log functions. In Tango too it is used in log functions. I use delegates as function parameters often, but not lazy. This is because I may add parameters and on the caller site, IMO it must be obvious, this expression is not evaluated as others. Maybe it is acceptable to remove lazy and write logging statements with delegate and the curly braces. log({ "bla bla "~info });Doesn't that mean, each call with different arguments will instantiate another template instance?A related issue with passing arguments, that i think needs a better solution in D are the variadic arg list. No magic param names and the possibility to pass this list - or a slice of it - to another function.I'm hoping that template variadics + arrays of Variant cover all needs.
Oct 12 2009
On 2009-10-13 02:44:52 -0400, Frank Benoit <keinfarbton googlemail.com> said:I mean if you call a function and you did not know the argument is lazy, it may have strange effects. This is why i would avoid lazy. I think the callers code should have the noticeable different syntax, and we already have that with the curly braces.Hum, side effects... I'm thinking lazy makes more sense if it was forcing the expression to be pure. With provably no side effects, this would make lazy a good optimization technique you can opt-in whenever you need to. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 13 2009
Frank Benoit wrote:Andrei Alexandrescu schrieb:I'm wary about magic capabilities that are reserved only to the core compiler and library. Among other things, one wouldn't be able to write their own logging/enforcement library. Historically, Walter has been prone to magic, but since recently he has started systematically using lowering - implement a higher-level feature by rewriting it in terms of simpler D code. He eliminated wads of code from the compiler that way. Maybe it's just me, but I clearly remember: after my first Pascal class, when I learned that writeln is a "special" function that takes variadic arguments, my only desire has been to be able to write "writeln" itself.Frank Benoit wrote:Yes, this is, both are functions that try to help the programmer itself and are part of the infrastructure. But is lazy useful for e.g. user libs? Is it useful in an API the user is not fully aware of? I mean if you call a function and you did not know the argument is lazy, it may have strange effects. This is why i would avoid lazy. I think the callers code should have the noticeable different syntax, and we already have that with the curly braces.Andrei Alexandrescu schrieb:std.contracts.enforce also uses it.Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality? AndreiI have seen lazy only used in its own show case. In log functions. In Tango too it is used in log functions. I use delegates as function parameters often, but not lazy. This is because I may add parameters and on the caller site, IMO it must be obvious, this expression is not evaluated as others. Maybe it is acceptable to remove lazy and write logging statements with delegate and the curly braces. log({ "bla bla "~info });The template is small - all it does is pack the arguments. void funImpl(Variant[] args) { ... } void fun(T...)(T args) { return funImpl(variantArray(args)); } AndreiDoesn't that mean, each call with different arguments will instantiate another template instance?A related issue with passing arguments, that i think needs a better solution in D are the variadic arg list. No magic param names and the possibility to pass this list - or a slice of it - to another function.I'm hoping that template variadics + arrays of Variant cover all needs.
Oct 13 2009
Andrei Alexandrescu:Maybe it's just me, but I clearly remember: after my first Pascal class, when I learned that writeln is a "special" function that takes variadic arguments, my only desire has been to be able to write "writeln" itself.Have you seen the asm produced by a small console D2 program? Even if you do very little there's a good amount of templates. That's one of the prices you have to pay, I was talking about in the poetic part of my post. Bye, bearophile
Oct 13 2009
On 10/13/09 08:21, Andrei Alexandrescu wrote:Frank Benoit wrote:Templates don't work as virtual methods. Arrays of variants will probably not interact well with C variadic functions.Andrei Alexandrescu schrieb:std.contracts.enforce also uses it.Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality? AndreiI have seen lazy only used in its own show case. In log functions. In Tango too it is used in log functions. I use delegates as function parameters often, but not lazy. This is because I may add parameters and on the caller site, IMO it must be obvious, this expression is not evaluated as others. Maybe it is acceptable to remove lazy and write logging statements with delegate and the curly braces. log({ "bla bla "~info });A related issue with passing arguments, that i think needs a better solution in D are the variadic arg list. No magic param names and the possibility to pass this list - or a slice of it - to another function.I'm hoping that template variadics + arrays of Variant cover all needs. Andrei
Oct 13 2009
Andrei Alexandrescu wrote:Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality? Andreilazy is a great feature of D, although you need some sort of usage convention to not get confused with it. For example, there is no way to tell a parameter is lazy from a function call, you need to look at the prototype. But the same can be said with ref and out too so if you remove lazy you also need to rethink these two. I therefore made myself a simple convention on how I use lazy: if the value is evaluated only once I use lazy, otherwise I use a delegate. This makes it clear from the call context what I'm doing. Sometimes I use lazy for values evaluated multiple times (I did it in the json module i posted to D.announce) when the method is private because I'm too lazy (pun intended) to write a full delegate. Jeremie
Oct 12 2009
Jeremie Pelletier schrieb:For example, there is no way to tell a parameter is lazy from a function call, you need to look at the prototype. But the same can be said with ref and out too so if you remove lazy you also need to rethink these two.ref and out are not the same category of weirdness for the caller. the compiler will tell that a lvalue is needed for ref and out. But the expression may have side effects, evaluating never/once/multiple is easy to hide errors.I therefore made myself a simple convention on how I use lazy: if the value is evaluated only once I use lazy, otherwise I use a delegate. This makes it clear from the call context what I'm doing.If it is evaluated exactly once, you do not need lazy at all. And if it may also not be evaluated, the callers code is not less safe as when evaluated multiple times.
Oct 12 2009
Tue, 13 Oct 2009 08:51:16 +0200, Frank Benoit thusly wrote:If it is evaluated exactly once, you do not need lazy at all. And if it may also not be evaluated, the callers code is not less safe as when evaluated multiple times.Call by name has its uses. E.g. custom control structures, infinite lists etc.
Oct 15 2009
Frank Benoit Wrote:Maybe it is acceptable to remove lazy and write logging statements with delegate and the curly braces. log({ "bla bla "~info });I second this :) http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=97504
Oct 13 2009
Kagamin Wrote:Frank Benoit Wrote:I third this. The above article raises a valid observation which needs, uhm well, ..., observing. Why disguise Smiths with Jones? Better to work out a briefer syntax for lambda and "half-lambdas". Now for a way out idea, since D source is cognisant of Unicode, albeit UTF-8, why not make use of (U+03BB), Greek Small Letter Lambda in the language? http://www.fileformat.info/info/unicode/char/03bb/index.htm (not the best reference but it will do) Of course this idea is not original, see following for "prior art" http://community.schemewiki.org/?syntax-unicode-lambda Bests to all, Justin JohanssonMaybe it is acceptable to remove lazy and write logging statements with delegate and the curly braces. log({ "bla bla "~info });I second this :) http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=97504
Oct 13 2009
On 2009-10-13 00:33:57 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d.According to the spec, 'assert' also allows the compiler to know something will always be true, which could result in optimizations. The compiler also enforce that you have an assert(false) at the end of a function when the control flow can't be proven to never reach it. So no, 'assert' should stay in the language.This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way?There are two uses for 'lazy': 1. provide a statement that can be executed by the function you're calling to perform some action. 2. to give a lazy-evaluated value to the calling function, removing the cost of evaluation when unnecessary I'm willing use the delegate literal syntax for case 1. But I'd like to keep 'lazy' for case 2. The problem with case 2 is that it's more an optimization technique used within the function (lazy evaluation) and it would be better if the caller didn't have to care about such details. So here's my idea to fix 'lazy': make sure 'lazy' can only work with case 2 by forcing the lazy expression to be pure, thus with no side effects. This way, 'lazy' becomes an almost-transparent optimization technique and stays true to its meaning of 'lazy evaluation'. And it'll give more optimization opportunities to the compiler. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Oct 13 2009
Andrei Alexandrescu Wrote:It's simpler actually: debug void assert(T)( T expr, string delegate() msg ) { if(!expr) throw new Exception(msg); } else void assert(T)( T delegate(), string delegate() ) { } Hm, actually it's more complicated than your version :o). AndreiYou should be throwing AssertError I really like lazy for log messages and asserts. I like the implicit cast to (scope) pure delegate idea. It works well in those contexts. How hard would it be to use a library assert in ctfe context?
Oct 13 2009
On Tue, 13 Oct 2009 08:21:44 -0400, Jason House <jason.james.house gmail.com> wrote:Andrei Alexandrescu Wrote:With macros, this can be solved without lazy. I'd say work on getting macros working, then drop lazy and assert. -SteveIt's simpler actually: debug void assert(T)( T expr, string delegate() msg ) { if(!expr) throw new Exception(msg); } else void assert(T)( T delegate(), string delegate() ) { } Hm, actually it's more complicated than your version :o). AndreiYou should be throwing AssertError I really like lazy for log messages and asserts. I like the implicit cast to (scope) pure delegate idea. It works well in those contexts.
Oct 13 2009
Andrei Alexandrescu wrote:Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality? Andreiassert: should remain. It is important to the compiler. I can easily imagine it participating in range checking. uint x = whatever(); assert(x<100); ubyte b = x; // This implicit conversion is OK; we know x is in the appropriate range. lazy: should be removed. It seems to me that 'lazy' covers just a single use case for macros.
Oct 13 2009
Don Wrote:assert: should remain. It is important to the compiler. I can easily imagine it participating in range checking. uint x = whatever(); assert(x<100); ubyte b = x; // This implicit conversion is OK; we know x is in the appropriate range.how about this? long more=fileLength; ubyte[256] buff; for(; more>=buff.length ; more-=buff.length) { //read from file, no breaks } //last read read(file,buff.ptr,more); auto rd=buff[0..more]; //can't cast long to uint
Oct 13 2009
Did you know the following code compiles?module test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)
Oct 13 2009
On Tue, 13 Oct 2009 17:06:25 +0400, downs <default_357-line yahoo.de> wrote:Did you know the following code compiles?Wow, indeed!module test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)
Oct 13 2009
downs wrote:Did you know the following code compiles?Gosh!!! What's happening over here? I even tried this: import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } string fun(string a, string b) { writeln("Concatenating..."); return a ~ b; } void main() { Assert(true, fun("O hai thar! ", "wyda")); Assert(false, fun("O hai thar! ", "wyda")); } This example only prints "Concatenatning..." once, meaning that fun is also lazified!!! This is very exciting! The fact that this little anomaly hasn't caused trouble is a good sign it could actually replace lazy! Andreimodule test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)
Oct 13 2009
Andrei Alexandrescu wrote:downs wrote:There's a bug report about it, from Sean: bugzilla 1069.Did you know the following code compiles?Gosh!!! What's happening over here? I even tried this: import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } string fun(string a, string b) { writeln("Concatenating..."); return a ~ b; } void main() { Assert(true, fun("O hai thar! ", "wyda")); Assert(false, fun("O hai thar! ", "wyda")); } This example only prints "Concatenatning..." once, meaning that fun is also lazified!!! This is very exciting! The fact that this little anomaly hasn't caused trouble is a good sign it could actually replace lazy! Andreimodule test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)
Oct 13 2009
Andrei Alexandrescu, el 13 de octubre a las 10:30 me escribiste:downs wrote:What is the relation between assert and pure/nothrow? Is assert allowed? I think it should be, since an assert is expressing a very essential property of the software, it can't happen in a normal flow of the program. If this is the case, I guess assert should be kept as a language construct so it can be always be used in pure/nothrow functions. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- En la calle me crucé con un señor muy correcto, que habitualmente anda en Falcon; iba corriendo con dos valijas en la mano y dijo: "Voy para Miami, tiene algún mensaje o ..." y le dije: "No, no, no..." -- Extra Tato (1983, Triunfo de Alfonsín)Did you know the following code compiles?Gosh!!! What's happening over here? I even tried this: import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } string fun(string a, string b) { writeln("Concatenating..."); return a ~ b; } void main() { Assert(true, fun("O hai thar! ", "wyda")); Assert(false, fun("O hai thar! ", "wyda")); } This example only prints "Concatenatning..." once, meaning that fun is also lazified!!! This is very exciting! The fact that this little anomaly hasn't caused trouble is a good sign it could actually replace lazy!module test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)
Oct 13 2009
Leandro Lucarella wrote:Andrei Alexandrescu, el 13 de octubre a las 10:30 me escribiste:It works for the reason you said, assertions either guard against an unreachable code path or invalid values. AssertError throwables aren't meant to be recovered from (as should any Error) so they're perfectly fine in pure or nothrow contexts. I often use assert(0) to mark unreachable paths, and the compiler don't warn me that some paths of a function have no return value. For that reason I also want assert() to stay a compiler intrinsic, especially since having assert() as a library routine and static assert() as a compiler feature sounds weird. Jeremiedowns wrote:What is the relation between assert and pure/nothrow? Is assert allowed? I think it should be, since an assert is expressing a very essential property of the software, it can't happen in a normal flow of the program. If this is the case, I guess assert should be kept as a language construct so it can be always be used in pure/nothrow functions.Did you know the following code compiles?Gosh!!! What's happening over here? I even tried this: import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } string fun(string a, string b) { writeln("Concatenating..."); return a ~ b; } void main() { Assert(true, fun("O hai thar! ", "wyda")); Assert(false, fun("O hai thar! ", "wyda")); } This example only prints "Concatenatning..." once, meaning that fun is also lazified!!! This is very exciting! The fact that this little anomaly hasn't caused trouble is a good sign it could actually replace lazy!module test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)
Oct 13 2009
Jeremie Pelletier wrote:Leandro Lucarella wrote:I think that's sensible, and thanks all for revealing reasons for assert to stay in the language. As far as lazy goes, I think the lazy variadic functions are a compelling feature that renders lazy unnecessary. I plan to put no reference to lazy in TDPL. (Before someone else leaves the group: I just talked to Walter and he approved that.) AndreiAndrei Alexandrescu, el 13 de octubre a las 10:30 me escribiste:It works for the reason you said, assertions either guard against an unreachable code path or invalid values. AssertError throwables aren't meant to be recovered from (as should any Error) so they're perfectly fine in pure or nothrow contexts. I often use assert(0) to mark unreachable paths, and the compiler don't warn me that some paths of a function have no return value. For that reason I also want assert() to stay a compiler intrinsic, especially since having assert() as a library routine and static assert() as a compiler feature sounds weird. Jeremiedowns wrote:What is the relation between assert and pure/nothrow? Is assert allowed? I think it should be, since an assert is expressing a very essential property of the software, it can't happen in a normal flow of the program. If this is the case, I guess assert should be kept as a language construct so it can be always be used in pure/nothrow functions.Did you know the following code compiles?Gosh!!! What's happening over here? I even tried this: import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } string fun(string a, string b) { writeln("Concatenating..."); return a ~ b; } void main() { Assert(true, fun("O hai thar! ", "wyda")); Assert(false, fun("O hai thar! ", "wyda")); } This example only prints "Concatenatning..." once, meaning that fun is also lazified!!! This is very exciting! The fact that this little anomaly hasn't caused trouble is a good sign it could actually replace lazy!module test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)
Oct 13 2009
Andrei Alexandrescu wrote:Jeremie Pelletier wrote:I wouldn't mind lazy going away, its something that can be 100% covered by delegates and closures, maybe keep lazy as a lazy way of writing a delegate? 'lazy int foo' could semantically equivalent to 'scope int delegate() foo'. It would get called as {return 1;} and evaluated as foo(). JeremieLeandro Lucarella wrote:I think that's sensible, and thanks all for revealing reasons for assert to stay in the language. As far as lazy goes, I think the lazy variadic functions are a compelling feature that renders lazy unnecessary. I plan to put no reference to lazy in TDPL. (Before someone else leaves the group: I just talked to Walter and he approved that.) AndreiAndrei Alexandrescu, el 13 de octubre a las 10:30 me escribiste:It works for the reason you said, assertions either guard against an unreachable code path or invalid values. AssertError throwables aren't meant to be recovered from (as should any Error) so they're perfectly fine in pure or nothrow contexts. I often use assert(0) to mark unreachable paths, and the compiler don't warn me that some paths of a function have no return value. For that reason I also want assert() to stay a compiler intrinsic, especially since having assert() as a library routine and static assert() as a compiler feature sounds weird. Jeremiedowns wrote:What is the relation between assert and pure/nothrow? Is assert allowed? I think it should be, since an assert is expressing a very essential property of the software, it can't happen in a normal flow of the program. If this is the case, I guess assert should be kept as a language construct so it can be always be used in pure/nothrow functions.Did you know the following code compiles?Gosh!!! What's happening over here? I even tried this: import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } string fun(string a, string b) { writeln("Concatenating..."); return a ~ b; } void main() { Assert(true, fun("O hai thar! ", "wyda")); Assert(false, fun("O hai thar! ", "wyda")); } This example only prints "Concatenatning..." once, meaning that fun is also lazified!!! This is very exciting! The fact that this little anomaly hasn't caused trouble is a good sign it could actually replace lazy!module test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)
Oct 13 2009
On Tue, 13 Oct 2009 16:39:13 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:As far as lazy goes, I think the lazy variadic functions are a compelling feature that renders lazy unnecessary.Do you mean lazy in the way that lazy variadic functions *imply* lazy via typing their arguments as delegates, or simply only allow lazy variadic functions? If the latter, why must a lazy function be variadic? -Steve
Oct 13 2009
On Tue, 13 Oct 2009 15:06:25 +0200, downs <default_357-line yahoo.de> wrote:Did you know the following code compiles?Yes, it is documented. "Lazy Variadic Functions" on "Functions" page.module test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)
Oct 13 2009
Max Samukha wrote:On Tue, 13 Oct 2009 15:06:25 +0200, downs <default_357-line yahoo.de> wrote:Awesome. I'll replace the use of lazy in enforce() with that. AndreiDid you know the following code compiles?Yes, it is documented. "Lazy Variadic Functions" on "Functions" page.module test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)
Oct 13 2009
downs wrote:Did you know the following code compiles?Here is a funny consequence of this amusing fact: if you overload opAssign in a struct with lazy T[] dgs..., you can achieve the following syntaxmodule test; import std.stdio; void Assert(bool cond, string delegate()[] dgs...) { debug if (!cond) { string str; foreach (dg; dgs) str ~= dg(); throw new Exception(str); } } void main() { Assert(false, "O hai thar! "); }It's true! :)WithFlag(GL_BLEND, true) = WithDepthMask(false) = tex.With = Quads = { foreach (i, q; qa) { float f = 1f*i / qa.length; Color(1f-f, f, 1f); TexCoord(0f, 0f); Vertex(q.points[0]); TexCoord(1f, 0f); Vertex(q.points[1]); TexCoord(1f, 1f); Vertex(q.points[3]); TexCoord(0f, 1f); Vertex(q.points[2]); } };
Oct 13 2009
downs wrote:Here is a funny consequence of this amusing fact: if you overload opAssign in a struct with lazy T[] dgs..., you can achieve the following syntaxThat's... just beautiful... -- Chris Nicholson-SaulsWithFlag(GL_BLEND, true) = WithDepthMask(false) = tex.With = Quads = { foreach (i, q; qa) { float f = 1f*i / qa.length; Color(1f-f, f, 1f); TexCoord(0f, 0f); Vertex(q.points[0]); TexCoord(1f, 0f); Vertex(q.points[1]); TexCoord(1f, 1f); Vertex(q.points[3]); TexCoord(0f, 1f); Vertex(q.points[2]); } };
Oct 13 2009
Chris Nicholson-Sauls wrote:downs wrote:Not getting it... could someone please explain? AndreiHere is a funny consequence of this amusing fact: if you overload opAssign in a struct with lazy T[] dgs..., you can achieve the following syntaxThat's... just beautiful... -- Chris Nicholson-SaulsWithFlag(GL_BLEND, true) = WithDepthMask(false) = tex.With = Quads = { foreach (i, q; qa) { float f = 1f*i / qa.length; Color(1f-f, f, 1f); TexCoord(0f, 0f); Vertex(q.points[0]); TexCoord(1f, 0f); Vertex(q.points[1]); TexCoord(1f, 1f); Vertex(q.points[3]); TexCoord(0f, 1f); Vertex(q.points[2]); } };
Oct 13 2009
Andrei Alexandrescu wrote:Chris Nicholson-Sauls wrote:From what I get, he has something like this: struct WithFlag(int OP, bool enable) { static void opAssign(T)(lazy T next) { static if(enable) glEnable(OP); else glDisable(OP); next(); } } struct WithDepthMask(bool enable) { static void opAssign(T)(lazy T next) { glDepthMask(enable); next(); } } struct Tex { void opAssign(T)(lazy T next) { glBindTexture(_tex); next(); } } struct Quads { static void opAssign(T)(lazy T commands) { glBegin(GL_QUADS); commands(); glEnd(); } } I don't know if thats his exact code, but from what I can remember of gl from memory it should look like this. Jeremiedowns wrote:Not getting it... could someone please explain? AndreiHere is a funny consequence of this amusing fact: if you overload opAssign in a struct with lazy T[] dgs..., you can achieve the following syntaxThat's... just beautiful... -- Chris Nicholson-SaulsWithFlag(GL_BLEND, true) = WithDepthMask(false) = tex.With = Quads = { foreach (i, q; qa) { float f = 1f*i / qa.length; Color(1f-f, f, 1f); TexCoord(0f, 0f); Vertex(q.points[0]); TexCoord(1f, 0f); Vertex(q.points[1]); TexCoord(1f, 1f); Vertex(q.points[3]); TexCoord(0f, 1f); Vertex(q.points[2]); } };
Oct 13 2009
Jeremie Pelletier wrote:Andrei Alexandrescu wrote:Very close. There's another workaround required to enable the = {} syntax. The T in question can either be a void, in which case we're assigning a function call, or a void delegate(), in which case we're assigning a subscope. Because the parameter is lazy, in the case of void delegate() we actually have to call it doubly nestedly! This leads to the following code.Chris Nicholson-Sauls wrote:From what I get, he has something like this: struct WithFlag(int OP, bool enable) { static void opAssign(T)(lazy T next) { static if(enable) glEnable(OP); else glDisable(OP); next(); } } struct WithDepthMask(bool enable) { static void opAssign(T)(lazy T next) { glDepthMask(enable); next(); } } struct Tex { void opAssign(T)(lazy T next) { glBindTexture(_tex); next(); } } struct Quads { static void opAssign(T)(lazy T commands) { glBegin(GL_QUADS); commands(); glEnd(); } } I don't know if thats his exact code, but from what I can remember of gl from memory it should look like this. Jeremiedowns wrote:Not getting it... could someone please explain? AndreiHere is a funny consequence of this amusing fact: if you overload opAssign in a struct with lazy T[] dgs..., you can achieve the following syntaxThat's... just beautiful... -- Chris Nicholson-SaulsWithFlag(GL_BLEND, true) = WithDepthMask(false) = tex.With = Quads = { foreach (i, q; qa) { float f = 1f*i / qa.length; Color(1f-f, f, 1f); TexCoord(0f, 0f); Vertex(q.points[0]); TexCoord(1f, 0f); Vertex(q.points[1]); TexCoord(1f, 1f); Vertex(q.points[3]); TexCoord(0f, 1f); Vertex(q.points[2]); } };const string LazyCall=" static if (is(T==void)) t(); else static if (is(T==void delegate())) t()(); else static assert(false, T.stringof); ";...template PrimitiveScope(string NAME, string WHICH) { const string PrimitiveScope="struct "~NAME~" { static void opAssign(T)(lazy T t) { glBegin("~WHICH~"); scope(exit) glEnd(); "~LazyCall~" } }"; }...mixin(Concat!(MAP!(PrimitiveScope, 2, "Points", "GL_POINTS", "Lines", "GL_LINES", "LineLoop", "GL_LINE_LOOP", "LineStrip", "GL_LINE_STRIP", "Triangles", "GL_TRIANGLES", "TriangleStrip", "GL_TRIANGLE_STRIP", "TriangleFan", "GL_TRIANGLE_FAN", "Quads", "GL_QUADS", "QuadStrip", "GL_QUAD_STRIP", "Polygon", "GL_POLYGON" )));:deranged grin: I love templates!
Oct 14 2009
Chris Nicholson-Sauls wrote:downs wrote:If you forget the fact that he is using GL's immediate mode which is slooooow, yeah it's beautiful, would be better with an interlaced vertex buffer :) JeremieHere is a funny consequence of this amusing fact: if you overload opAssign in a struct with lazy T[] dgs..., you can achieve the following syntaxThat's... just beautiful... -- Chris Nicholson-SaulsWithFlag(GL_BLEND, true) = WithDepthMask(false) = tex.With = Quads = { foreach (i, q; qa) { float f = 1f*i / qa.length; Color(1f-f, f, 1f); TexCoord(0f, 0f); Vertex(q.points[0]); TexCoord(1f, 0f); Vertex(q.points[1]); TexCoord(1f, 1f); Vertex(q.points[3]); TexCoord(0f, 1f); Vertex(q.points[2]); } };
Oct 13 2009
On Tue, 13 Oct 2009 07:33:57 +0300, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality?No one seems to have mentioned this, but please don't overlook that when compiling in release mode, assert (or at least assert(0)) works as a compiler hint. -- Best regards, Vladimir mailto:thecybershadow gmail.com
Oct 13 2009
On Tue, 13 Oct 2009 00:33:57 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Right now, the language has enough power to express assert as a library function, as opposed to a primitive construct. (See e.g. enforce.) I think it would be good to relegate assert to object.d. This also brings up "lazy", which seems to be quite botched. Are there suggestions on how to replicate its functionality in a different way? I even seem to recall lazy was discussed as a disadvantage in the recent dialog on reddit, see http://www.reddit.com/r/programming/comments/9qf8i/i_wrote_some_d_today_and_its_completely_blowing/ I personally believe it's useful to be able to pass an unevaluated expression into a function, for example assert and enforce themselves use that. But let's open this for discussion: should assert and/or lazy be removed? If not, why not? It yes, why? How can we replicate their functionality?How to trigger assert when no -debug or -release flag is set? Is there a flag we can trigger on? From what I understand assert triggers when -debug or no flag is set, but not when -release flag is set. -Steve
Oct 13 2009