August 22, 2006 Re: about { expr }syntax for anonymous delegate | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sai | Sai wrote:
> Other people already proposed the { expr } syntax, I liked it too, can't we think of it like this ...
>
>
> We usually write compound statement as:
>
> {
> statement1;
> statement2;
> return expr;
> }
>
> We can ignore ';' if there is only statement, so following is valid:
>
> {
> statement
> }
>
> {
> return expr
> }
>
> If there is only a return statement, and the return type of the delegate matches the expression, we can make the 'return' keyword optional:
>
> {
> expr
> }
>
>
> well ... what do you all say ?
> (hope Walter likes this)
> Sai
Sure is better than deliberately introducing ambiguity into the language.
|
August 22, 2006 Re: Lazy eval | ||||
---|---|---|---|---|
| ||||
Posted in reply to BCS | BCS wrote:
> Thinking of it that way, changing the API from one to the other is *never* safe. This means that using a T delegate() as a parameter might as well be considered an unsafe practice. If you started with just T, your locked in for all time. Starting with T delegate() is almost as bad.
>
> Having a feature that is nearly impossible to use safely may well be worse than not having the feature.
Changing the API is always problematic, including with traditional features like implicit conversions, inout, etc. As I posted before, the pragmatic way to change an API is to create a new name with the new interface, and deprecate the old one. This is not a problem that is new or unique to delegate conversions. It's as old as programming.
As for delegate conversions being nearly impossible to use safely, I don't understand that at all. I would agree that it is a probably unique feature for C like languages, and hence people will perhaps make mistakes with it until it becomes familiar, expected, and passe.
|
August 22, 2006 Re: Lazy eval -- an example issue | ||||
---|---|---|---|---|
| ||||
Posted in reply to kris | kris wrote: > Walter Bright wrote: > >> I've been thinking a lot about the escape problem. I'm pretty sure that: >> char[] delegate() { return "foo"; } >> can be detected and so I can assure you it won't cause the enclosing function's variables to be allocated on the heap. > > And what about those cases where the expression is somewhat more complex? Will you revert all this ambiguity when a bogus heap-frame is demonstrated? One where the intent was never to create a delegate, but simply to evaluate an argument expr instead? Or will you insist that a smarter detector is the solution? It's straightforward at one level - if a delegate does not reference any variables on the enclosing functions stack frame, there's no reason to allocate it on the heap. Something very similar is done now: variables referenced by nested functions are marked so they are not allocated into registers. > One has to suspect that there are far more productive ways to take risks with a language than this one: > > # somefunk (++i); > # > # vs > # > # somefunk ({++i}); > > the latter is not only unambiguous, it even /looks/ like a delegate. The former? Who knows what it does anymore Without knowledge of what somefunc() does by looking at the declaration for it and the documentation, there's no way to know what it does anyway. If one does look at the function declaration, it's pretty obvious if it has a delegate parameter. I expect function writers to use this in a way that makes sense, not in a way to pull the rug out from under client code. At some level, you have to trust them, with or without this feature. For example, doesn't it make sense that dotimes(int n, void delegate() exp) evaluates exp n times? |
August 22, 2006 Re: Lazy eval -- an example issue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote: > I'll admit that doing so makes a difference to me, as it allows for tricks that aren't possible with explicit delegate signifiers. But I'm undecided as to whether this is a "good thing" or not--I plan to give it some time before I decide. Good - I don't think any of us are prescient enough to see all the ramifications of this. Nobody predicted where C++ templates wound up (the good and the bad). > I do think it's unfortunate that Kris' logging code will be unable to accept both string and delegate parameters however. True, but I don't think it's a serious deficiency. At worst, Kris can define two sets of them with different names, one set with values and the other with delegate parameters. > And I'd like to note that all the tricks I'm thinking of for the new syntax tend to involve refactoring existing code (which is potentially dangerous, given the issue with side-effects) rather than writing new code. With new code I don't see much benefit to omitting all evidence that a parameter will be converted to a delegate, as it's something the user must be aware of to write correct code. I can't stress this enough - one must *already* be aware of the declaration to write correct code. Implicit conversions can cause trouble, as well as in, out, inout, const, and all the other storage classes discussed. Previous discussions here frequently revolved around the need to put information in the function declaration so people have some guarantees about what the function does - const is a prime example. Another is the suggestion to move the contracts from the implementation to the declaration. There is no way to know what: somefunc(++i); does without looking at the declaration for somefunc() - even without lazy evaluation. Heck, you can't even know what ++i does without looking at the type of i. It might be a class instance with a bizarre operator overload. |
August 23, 2006 Re: Lazy eval | ||||
---|---|---|---|---|
| ||||
Posted in reply to BCS | BCS wrote:
> I feel confident I can document all sorts of bazaar things in my own code. I also feel confident that if they are allowed/promoted then other people will use them and *NOT* document them.
>
> As to others using your/my code, you can put a page and a half of documentation in warning about side effects and it wont do one wit of good if the other guy doesn't read it. And there is no way to ensure that it will get read.
>
> I can just see the buzz now: "Did you hear about the bonehead over in XYZ department that messed up the billing program? He didn't read all of the comments in the new library and ended up costing the cooperation $n million dollars because of this "cool" feature in the D programming language. I'll never use a D lib in /my/ work."
I agree with you that comments are always wrong, out of date, or missing. With the delegate feature, one doesn't need to document it, as it is there in the declaration of the function.
The fact that the delegate parameter exists is a pretty good sign that the function isn't intended to evaluate the argument exactly once, so it is worth trying to figure out what the function is doing before calling it with parameters that have side effects.
Sometimes, corporations have coding standards that ban certain constructs - like using templates in C++. If a particular feature does turn out to cause grief, it can be so banned.
|
August 23, 2006 Re: Lazy eval -- an example issue | ||||
---|---|---|---|---|
| ||||
Posted in reply to kris | kris wrote:
> Can't do that; the char[] version have to stay.
Why?
|
August 23, 2006 Re: Lazy eval -- an example issue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote:
> Walter Bright wrote:
>>
>> 3) It is possible that the delegate can be inlined, thus eliminating any extra overhead.
>
> Really? Are you saying that if the receiving function is short enough the function and its delegate use may be inlined in the calling code? I can't imagine that it would simply be inlined in the receiving function and duplicates of that wold be generated. Or at least, DMD doesn't appear to do that now.
It doesn't do it now, but it is possible to do. What an advanced compiler can do is duplicate the function into two, one gets the value arguments that have no computation, the other gets the side effect arguments and ones that involve computation as delegates.
|
August 23, 2006 Re: Lazy eval -- an example issue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright wrote:
> kris wrote:
>
>> Can't do that; the char[] version have to stay.
>
>
> Why?
Because my Boss says so
|
August 23, 2006 Re: Lazy eval -- an example issue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright wrote:
> kris wrote:
>
>> Can't do that; the char[] version have to stay.
>
>
> Why?
Further, I had to remove the very useful delegate() overload that was added using dmd164, since dmd165 just had a fit about ambiguous arguments. So much for backward compatability :/
I don't know where you get your claim about people not willing to use "{}" but, judging by the response around here, it has no truth behind it whatsoever. Perhaps you'll honour us with some background on that?
I remember when you asked folks here if it would be ok to change the cast() syntax way back when, to remove that minor ambiguity. Now you're using a suspect and pithy "{}" assertion to deliberately break what is otherwise an unambiguous syntax. And you don't ask or care whether anyone would actually mind the ensuing chaos. Whatever you've been smoking, Walter, I'd like to try some of it ~ please pass it around
Cheers;
|
August 23, 2006 Re: Lazy eval -- an example issue | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright wrote: > Sean Kelly wrote: >> I'll admit that doing so makes a difference to me, as it allows for tricks that aren't possible with explicit delegate signifiers. But I'm undecided as to whether this is a "good thing" or not--I plan to give it some time before I decide. > > Good - I don't think any of us are prescient enough to see all the ramifications of this. Nobody predicted where C++ templates wound up (the good and the bad). C++ templates are well-intentioned and really quite powerful, but they're a horrible hack, even when used as originally intended. The need for "template" as a means to distinguish dependent type names is a perfect example of something that should be completely unnecessary. >> And I'd like to note that all the tricks I'm thinking of for the new syntax tend to involve refactoring existing code (which is potentially dangerous, given the issue with side-effects) rather than writing new code. With new code I don't see much benefit to omitting all evidence that a parameter will be converted to a delegate, as it's something the user must be aware of to write correct code. In light of my opening paragraph, I really shoudn't have said "all." > I can't stress this enough - one must *already* be aware of the declaration to write correct code. Implicit conversions can cause trouble, as well as in, out, inout, const, and all the other storage classes discussed. True enough. But I consider this a somewhat different class of unpredictable behavior, if only because it isn't something present in this way in any other C-like language (C# 3.0 will have lambda functions similar to this with a leading => at the call point). > Previous discussions here frequently revolved around the need to put information in the function declaration so people have some guarantees about what the function does - const is a prime example. Another is the suggestion to move the contracts from the implementation to the declaration. > > There is no way to know what: > > somefunc(++i); > > does without looking at the declaration for somefunc() - even without lazy evaluation. But the possibilities are rather limited, either i will be mutated or it will not. I suppose what worries me isn't that I need to look at the declaration to determine what will happen with implicit delegate conversion, but that even looking at the declaration won't tell me what may happen. By the same token, I actually like C's method of pass-by-reference because call-side code inspection reveals which parameters may be modified. I think this is why I like the suggestion to retain curly braces and perhaps derive the return value automatically--it makes the contract between caller and callee explicit. But this is a new feature and I do want to spend more time with it before making a final decision. If nothing else, I agree that time and experience will reduce the chance of mistakes demonstrated recently, as this becomes "just another tool" we have available. Sean |
Copyright © 1999-2021 by the D Language Foundation