digitalmars.D - Eliminate assert and lazy from D?
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Oct 12 2009
- "Robert Jacques" <sandford jhu.edu> Oct 12 2009
- "Adam D. Ruppe" <destructionator gmail.com> Oct 12 2009
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Oct 12 2009
- Chris Nicholson-Sauls <ibisbasenji gmail.com> Oct 15 2009
- "Robert Jacques" <sandford jhu.edu> Oct 12 2009
- bearophile <bearophileHUGS lycos.com> Oct 12 2009
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Oct 12 2009
- bearophile <bearophileHUGS lycos.com> Oct 12 2009
- bearophile <bearophileHUGS lycos.com> Oct 12 2009
- "Craig Black" <craigblack2 cox.net> Oct 13 2009
- language_fan <foo bar.com.invalid> Oct 15 2009
- Frank Benoit <keinfarbton googlemail.com> Oct 12 2009
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Oct 12 2009
- Frank Benoit <keinfarbton googlemail.com> Oct 12 2009
- Michel Fortin <michel.fortin michelf.com> Oct 13 2009
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Oct 13 2009
- bearophile <bearophileHUGS lycos.com> Oct 13 2009
- Jacob Carlborg <doob me.com> Oct 13 2009
- Jeremie Pelletier <jeremiep gmail.com> Oct 12 2009
- Frank Benoit <keinfarbton googlemail.com> Oct 12 2009
- language_fan <foo bar.com.invalid> Oct 15 2009
- Michel Fortin <michel.fortin michelf.com> Oct 13 2009
- Don <nospam nospam.com> Oct 13 2009
- Kagamin <spam here.lot> Oct 13 2009
- downs <default_357-line yahoo.de> Oct 13 2009
- "Denis Koroskin" <2korden gmail.com> Oct 13 2009
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Oct 13 2009
- Don <nospam nospam.com> Oct 13 2009
- Jeremie Pelletier <jeremiep gmail.com> Oct 13 2009
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Oct 13 2009
- Jeremie Pelletier <jeremiep gmail.com> Oct 13 2009
- Max Samukha <spambox d-coding.com> Oct 13 2009
- downs <default_357-line yahoo.de> Oct 13 2009
- Chris Nicholson-Sauls <ibisbasenji gmail.com> Oct 13 2009
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Oct 13 2009
- Jeremie Pelletier <jeremiep gmail.com> Oct 13 2009
- downs <default_357-line yahoo.de> Oct 14 2009
- Jeremie Pelletier <jeremiep gmail.com> Oct 13 2009
- "Steven Schveighoffer" <schveiguy yahoo.com> Oct 13 2009
- "Vladimir Panteleev" <thecybershadow gmail.com> Oct 13 2009
- "Steven Schveighoffer" <schveiguy yahoo.com> Oct 13 2009
- Leandro Lucarella <llucax gmail.com> Oct 13 2009
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? Andrei
Well, 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: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
Well, 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)
Yah, that's how the feature was initially proposed.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
Adam D. Ruppe wrote: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.
That kinda takes the wind out of the sails of the "remove assert" ship.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.
Yah, me too, enforce in particular is a happy beneficiary. Andrei
Oct 12 2009
Andrei Alexandrescu wrote:Adam D. Ruppe wrote: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.
That kinda takes the wind out of the sails of the "remove assert" ship.
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-Sauls
Oct 15 2009
On Tue, 13 Oct 2009 01:17:19 -0400, Adam D. Ruppe <destructionator gmail.com> wrote: [snip]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.
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).
Oct 12 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 the success of Java/C#, etc). So every time you want to remove a higher-level built-in feature you have to think about those factors too. Bye, bearophile
Oct 12 2009
bearophile wrote: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.
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.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 success of Java/C#, etc). So every time you want to remove a 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: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
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. -Craig
Oct 13 2009
Tue, 13 Oct 2009 02:50:11 -0400, bearophile thusly wrote: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 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 easierI 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? Andrei
I 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: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
I 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 });
std.contracts.enforce also uses it.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: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? Andrei
I 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 });
std.contracts.enforce also uses it.
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.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.
Doesn't that mean, each call with different arguments will instantiate another template instance?
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:Frank Benoit wrote: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? Andrei
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 });
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.
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.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.
Doesn't that mean, each call with different arguments will instantiate another template instance?
The template is small - all it does is pack the arguments. void funImpl(Variant[] args) { ... } void fun(T...)(T args) { return funImpl(variantArray(args)); } Andrei
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: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? Andrei
I 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 });
std.contracts.enforce also uses it.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
Templates don't work as virtual methods. Arrays of variants will probably not interact well with C variadic functions.
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? Andrei
lazy 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
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: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
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. 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?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! :)
Wow, indeed!
Oct 13 2009
downs wrote: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! :)
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! Andrei
Oct 13 2009
Andrei Alexandrescu wrote:downs wrote: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! :)
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! Andrei
There's a bug report about it, from Sean: bugzilla 1069.
Oct 13 2009
Leandro Lucarella wrote:Andrei Alexandrescu, el 13 de octubre a las 10:30 me escribiste:downs wrote: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! :)
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!
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.
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. Jeremie
Oct 13 2009
Jeremie Pelletier wrote:Leandro Lucarella wrote:Andrei Alexandrescu, el 13 de octubre a las 10:30 me escribiste:downs wrote: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! :)
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!
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.
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. Jeremie
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.) Andrei
Oct 13 2009
Andrei Alexandrescu wrote:Jeremie Pelletier wrote:Leandro Lucarella wrote:Andrei Alexandrescu, el 13 de octubre a las 10:30 me escribiste:downs wrote: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! :)
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!
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.
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. Jeremie
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.) Andrei
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(). Jeremie
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?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! :)
Yes, it is documented. "Lazy Variadic Functions" on "Functions" page.
Oct 13 2009
Max Samukha wrote:On Tue, 13 Oct 2009 15:06:25 +0200, downs <default_357-line yahoo.de> wrote: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! :)
Yes, it is documented. "Lazy Variadic Functions" on "Functions" page.
Awesome. I'll replace the use of lazy in enforce() with that. Andrei
Oct 13 2009
downs wrote: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! :)
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 syntaxWithFlag(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 syntaxWithFlag(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]); } };
That's... just beautiful... -- Chris Nicholson-Sauls
Oct 13 2009
Chris Nicholson-Sauls wrote: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 syntaxWithFlag(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]); } };
That's... just beautiful... -- Chris Nicholson-Sauls
Not getting it... could someone please explain? Andrei
Oct 13 2009
Andrei Alexandrescu wrote:Chris Nicholson-Sauls wrote: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 syntaxWithFlag(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]); } };
That's... just beautiful... -- Chris Nicholson-Sauls
Not getting it... could someone please explain? Andrei
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. Jeremie
Oct 13 2009
Jeremie Pelletier wrote:Andrei Alexandrescu wrote:Chris Nicholson-Sauls wrote: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 syntaxWithFlag(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]); } };
That's... just beautiful... -- Chris Nicholson-Sauls
Not getting it... could someone please explain? Andrei
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. Jeremie
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.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: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 syntaxWithFlag(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]); } };
That's... just beautiful... -- Chris Nicholson-Sauls
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 :) Jeremie
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 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
Andrei Alexandrescu, el 13 de octubre a las 10:30 me escribiste:downs wrote: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! :)
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!
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)
Oct 13 2009









Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> 