October 02, 2008 Re: Revised RFC on range design for D2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | On Thu, 02 Oct 2008 03:38:51 +0200, Simen Kjaeraas <simen.kjaras@gmail.com> wrote: > On Wed, 01 Oct 2008 15:28:36 +0200, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote: > >> Simen Kjaeraas wrote: >>> It seems we will soon get reference return values, in which case this would >>> no longer be a problem. I have also written a property template that enables >>> things such as that, but it would also benefit immensely from reference >>> return values. >> >> Not quite. Sorry, I woke up all negative this morning :o). >> >> Consider the .length property for built-in arrays. Better yet, consider you implement your own array and want to define a .length property. >> >> You don't want it to return a reference! You want to have control over the assignment so that you execute the actual array change. >> >> What I'd proposed to Walter for a long time is to allow a.b @= c to work if a.b = a.b @ c works. I'm sure people around here will find reasons to dislike that :o). >> >> >> Andrei > > Ah, of course. So that leaves us with the property template. I've got a > fairly nice implementation running, but I dislike the syntax. > > class foo > { > int _bar; > myStruct _baz; > > mixin property!(_bar, properties.readwrite, barChanged) bar; // This is ugly. > mixin property!(_baz, properties.read) baz; > > void barChanged(int value) > { > //... > } > } > > This supports all manners of operator overloading at the moment. > Though now that I look at it again (it's been a few months since last I worked on it), I see problems with more complex properties. Ah, more for me to code, then. :p -- Simen |
October 02, 2008 Re: Revised RFC on range design for D2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun | Yigal Chripun wrote: > auto test = new Test(); > auto y = &test.x; // consistent with the above > auto g = &test.func; // this is inconsistent! > in the above g is a delegate which is not a function pointer. > just as int* is different from int[]. you wouldn't expect to get an > int[] in the above, would you? &obj.method returns a pointer to a method for this instance. &obj.field returns a pointer to a field in this instance. If &obj.method returns a function pointer instead, &obj.field should return an OffsetTypeInfo struct. obj.field returns the value of the field. obj.method returns the result of executing obj.method(). The value of a method is either its return value or the machine code that corresponds with that method; and it's rarely the case that you intend to deal with machine code as data. Additionally, for obj.method to return machine code, D would have to support functions returning static arrays. > a more consistent approach would be to have: > - func and obj.method to be treated as delegates, of course for function > pointers there should be an implicit cast to delegate. > - &func and &obj.method would be strictly function pointers. > - using parentheses is mandatory for function calls. > IMHO, current low usage of delegates is not a reason to keep the current > syntax but rather a result of the current syntax. > > --Yigal I wasn't aware that delegates were poorly used in D. If I had a use for event-driven design, I'd use delegates all the time. If I did functional programming, likewise. |
October 02, 2008 Re: Revised RFC on range design for D2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 2008-09-30 09:42:43 -0400, "Steven Schveighoffer" <schveiguy@yahoo.com> said: > "Michel Fortin" wrote >> On 2008-09-29 12:55:18 -0400, "Steven Schveighoffer" said: >> >>> Stdout.newline.formatln("Hi there {}", var); >>> >>> Is newline a property of Stdout, on which I'm calling formatln, or is >>> newline a function that I'm calling, and then using the result of that >>> function to call formatln? Compare with: >>> >>> Stdout.newline().formatln("Hi there {}", var); >>> >>> There is no ambiguity. newline is clearly a function, not a property. >> >> Interesting. To me both of these things have exactly the same meaning. >> Perhaps it's because I'm used to D, but I think it's more because I can't >> count how many times I've seen this pattern in C++: >> >> SomeSimgleton::Instance().doSomething(); >> >> where Instance() is simply an accessor. > > Yes, that is a workaround for not having property constructs available. The > intuitive label of 'property' comes from the name of the getter 'Instance'. > It screams that you are getting the instance of the class, and it's well > accepted as a property. What has happened is that instead of relying on the > compiler to enforce what is a property and what is not, you are relying on > the interpretation of English words. But one problem is that the distinction between a accessor (of a property) and a function is often matter to interpretation. In the case above, most likely the Instance() function will create the singleton object if it doesn't exist yet; seen that way it isn't a simple accessor. If you ask if Instance() should be a property or not, you're likely to get different answers from different people. Arguably, there are cases even more ambiguous than this one. The issue I want to bring is that without having a formal definition of what is a property and what is not -- one the compiler can enforce -- people will make different choices, not always coherent with each others, and you may very well find yourself having to call Instance() with parenthesis in one D lib and without parenthesis in another. > But in a language like C#, you would define Instance as a property, not a > function. So it would never look like that. I could, but should I? I'm very interested in your criterions about why Instance would qualify to be a property and not as a function in this case. It's not just me. Just as an example, this article's author doesn't want to decide if Instance() should be a property or not: <http://www.yoda.arachsys.com/csharp/singleton.html> "Note that all of these implementations also use a public static property Instance as the means of accessing the instance. In all cases, the property could easily be converted to a method, with no impact on thread-safety or performance." > In D, properties are equivalent to functions, so you have a choice as to > whether to use the parentheses or not. But that isn't the problem, the > problem is really that you can call functions as properties. But what is the difference between a property and a function (beside the syntax?). I can find countless discussions on the net about this; interesting discussions but with no definitive answer. In the end, it all boils down to the author's feeling about his function/property, which may be the opposite from its user's. I'd like very much to quote Bruce Wood from this discussion: <http://bytes.com/forum/thread478064.html> (feel free to comment the quote) """ You see, it's not always so cut-and-dried. On the one hand, if you make something a property, you are implying that getting the information will be quick. So, if getting the information is slow, that is a hint that it shouldn't be a property. On the other hand, you don't want to determine what is a property or not based upon implementation details. By doing so you're letting the internal guts of how your class works leak out into its interface with the outside world. That's bad style. So, something should be a property if it makes sense that it be a property. Certainly, anything that affects the state of the object in a manner more sophisticated than just "set this to that" should be a method. That's painfully obvious. Similarly, an aspect of your class that can be read and set, even if setting it does more than just set a variable, should probably be a property. Reasonably straightfoward. However, sometimes the two design goals above-properties that return results quickly and not letting implementation determine interface-are at odds with each other, and you have to make a judgement call. In the case of my system, I had things that logically should be properties (from an interface point of view) but the object held only keys, not references to the objects themselves, so the "get" on the property has to fetch the object in question from the database. It was an open question whether to code: Supplier theSupplier = stockItem.Supplier; or Supplier theSupplier = stockItem.GetSupplier(); I chose the former, preferring to hide the implementation (holding supplier UID, not supplier itself) rather than let it leak out that getting the supplier was actually a lot of work. In our case it's no problem, because we're a very small shop. In a different situation I might have gone for door #2. """ With the current approach in D, you just don't need to choose, just document what your function/property is doing and be done with it... well you may still have to choose about the name :-), so in a way the argument is still there, but what I mean is that I don't think we really need a black and a white syntax for one concept that may take many shades of gray. >> In my opinion, "newline" isn't a good function name for what it does >> because it has no verb. Having no verb makes it look like an accessor much >> more than the absence or presence of parenthesis. > > So newline() seems like a property to you more than 'start a new line'? I > suppose I can see that, but consider if you were used to a system where > properties *prohibited* parentheses, and functions *required* them. It > becomes less about interpretation of English vocabulary and more about > compiler-enforced interface. I like that system better. But I'm still puzzled by what being a property means in opposition as if it was a function. The thing is that the compiler just can't guaranty anything about properties: it's really just another syntax for calling a function, a function the author has classified as a property by some subjective standard, a standard which will often differ between authors. Properties are often touted as an indicator for low-cost functions -- whatever "low-cost" means --, but even this fuzzy standard somewhat hinder the often seeked goal of separating interface and implementation. Without aggreement on a formal definition for properties and compiler enforcability, I find it very difficult to justify a formal syntax for properties. -- Michel Fortin michel.fortin@michelf.com http://michelf.com/ |
October 02, 2008 Re: Revised RFC on range design for D2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | On Thu, Oct 2, 2008 at 1:22 PM, Michel Fortin <michel.fortin@michelf.com> wrote:
> On 2008-09-30 09:42:43 -0400, "Steven Schveighoffer" <schveiguy@yahoo.com> said:
>
>> "Michel Fortin" wrote
>>>
>>> On 2008-09-29 12:55:18 -0400, "Steven Schveighoffer" said:
>>>
>>>> Stdout.newline.formatln("Hi there {}", var);
>>>>
>>>> Is newline a property of Stdout, on which I'm calling formatln, or is newline a function that I'm calling, and then using the result of that function to call formatln? Compare with:
>>>>
>>>> Stdout.newline().formatln("Hi there {}", var);
>>>>
>>>> There is no ambiguity. newline is clearly a function, not a property.
>>>
>>> Interesting. To me both of these things have exactly the same meaning. Perhaps it's because I'm used to D, but I think it's more because I can't count how many times I've seen this pattern in C++:
>>>
>>> SomeSimgleton::Instance().doSomething();
>>>
>>> where Instance() is simply an accessor.
>>
>> Yes, that is a workaround for not having property constructs available.
>> The
>> intuitive label of 'property' comes from the name of the getter
>> 'Instance'.
>> It screams that you are getting the instance of the class, and it's well
>> accepted as a property. What has happened is that instead of relying on
>> the
>> compiler to enforce what is a property and what is not, you are relying on
>> the interpretation of English words.
>
> But one problem is that the distinction between a accessor (of a property) and a function is often matter to interpretation. In the case above, most likely the Instance() function will create the singleton object if it doesn't exist yet; seen that way it isn't a simple accessor. If you ask if Instance() should be a property or not, you're likely to get different answers from different people.
>
> Arguably, there are cases even more ambiguous than this one. The issue I want to bring is that without having a formal definition of what is a property and what is not -- one the compiler can enforce -- people will make different choices, not always coherent with each others, and you may very well find yourself having to call Instance() with parenthesis in one D lib and without parenthesis in another.
>
>
>> But in a language like C#, you would define Instance as a property, not a function. So it would never look like that.
>
> I could, but should I?
>
> I'm very interested in your criterions about why Instance would qualify to be a property and not as a function in this case.
>
> It's not just me. Just as an example, this article's author doesn't want to
> decide if Instance() should be a property or not:
> <http://www.yoda.arachsys.com/csharp/singleton.html>
> "Note that all of these implementations also use a public static property
> Instance as the means of accessing the instance. In all cases, the property
> could easily be converted to a method, with no impact on thread-safety or
> performance."
>
>
>> In D, properties are equivalent to functions, so you have a choice as to whether to use the parentheses or not. But that isn't the problem, the problem is really that you can call functions as properties.
>
> But what is the difference between a property and a function (beside the syntax?). I can find countless discussions on the net about this; interesting discussions but with no definitive answer. In the end, it all boils down to the author's feeling about his function/property, which may be the opposite from its user's.
>
> I'd like very much to quote Bruce Wood from this discussion: <http://bytes.com/forum/thread478064.html>
>
> (feel free to comment the quote)
>
> """
> You see, it's not always so cut-and-dried.
>
> On the one hand, if you make something a property, you are implying that getting the information will be quick. So, if getting the information is slow, that is a hint that it shouldn't be a property.
>
> On the other hand, you don't want to determine what is a property or not based upon implementation details. By doing so you're letting the internal guts of how your class works leak out into its interface with the outside world. That's bad style. So, something should be a property if it makes sense that it be a property.
>
> Certainly, anything that affects the state of the object in a manner more sophisticated than just "set this to that" should be a method. That's painfully obvious.
>
> Similarly, an aspect of your class that can be read and set, even if setting it does more than just set a variable, should probably be a property. Reasonably straightfoward.
>
> However, sometimes the two design goals above-properties that return results quickly and not letting implementation determine interface-are at odds with each other, and you have to make a judgement call.
>
> In the case of my system, I had things that logically should be properties (from an interface point of view) but the object held only keys, not references to the objects themselves, so the "get" on the property has to fetch the object in question from the database. It was an open question whether to code:
>
> Supplier theSupplier = stockItem.Supplier;
>
> or
>
> Supplier theSupplier = stockItem.GetSupplier();
>
> I chose the former, preferring to hide the implementation (holding
> supplier UID, not supplier itself) rather than let it leak out that
> getting the supplier was actually a lot of work. In our case it's no
> problem, because we're a very small shop. In a different situation I
> might have gone for door #2.
> """
>
> With the current approach in D, you just don't need to choose, just document what your function/property is doing and be done with it... well you may still have to choose about the name :-), so in a way the argument is still there, but what I mean is that I don't think we really need a black and a white syntax for one concept that may take many shades of gray.
>
>
>>> In my opinion, "newline" isn't a good function name for what it does
>>> because it has no verb. Having no verb makes it look like an accessor
>>> much
>>> more than the absence or presence of parenthesis.
>>
>> So newline() seems like a property to you more than 'start a new line'? I suppose I can see that, but consider if you were used to a system where properties *prohibited* parentheses, and functions *required* them. It becomes less about interpretation of English vocabulary and more about compiler-enforced interface. I like that system better.
>
> But I'm still puzzled by what being a property means in opposition as if it was a function.
>
> The thing is that the compiler just can't guaranty anything about properties: it's really just another syntax for calling a function, a function the author has classified as a property by some subjective standard, a standard which will often differ between authors. Properties are often touted as an indicator for low-cost functions -- whatever "low-cost" means --, but even this fuzzy standard somewhat hinder the often seeked goal of separating interface and implementation.
>
> Without aggreement on a formal definition for properties and compiler enforcability, I find it very difficult to justify a formal syntax for properties.
Interesting post. My first thought is what is the formal definition for what should be a struct and what should be a class. That's not a cut-and-dried clear decision either. Either one will generally work. I may think X should be a struct and my users may think it should have been a class. We can both be right. Seems a pretty similar situation.
--bb
|
October 02, 2008 Re: Revised RFC on range design for D2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | On 2008-10-02 01:25:34 -0400, "Bill Baxter" <wbaxter@gmail.com> said: > Interesting post. My first thought is what is the formal definition > for what should be a struct and what should be a class. That's not a > cut-and-dried clear decision either. Either one will generally work. > I may think X should be a struct and my users may think it should have > been a class. We can both be right. Seems a pretty similar > situation. Yes, indeed, often both can be right in many situations. That's a very interesting observation in this context. If this were C++, I'd agree that we'd be better with just one of the two because in C++ the *only* difference between a struct and a class is syntaxic (if not to say cosmetic): it's the default protection attribute which you generally override explicity anyway. I sometime find myself want to forward-declare a class from some library (to avoid extra includes in the header file) only to have the compiler tell me it's a struct, or vice-versa, with an error I could live without. In C++, I don't think the addition of the "class" keyword was justified: it doesn't add anything useful beside perhaps marketing advantages -- because "class" sounds more object-oriented than "struct". But we are talking about D, where the situation is different. D classes are well suited for inheritance hierarchies, they can only be passed by reference and are always allocated on the heap[^1]. They are also easy to synchronize with due to their built-in monitor. D structs don't have implicit hidden members (monitor, classinfo pointer) so you can use them to represent any fixed-length memory layout. Structs are easily copied and passed by value too, unlike classes, thanks to the lack of inheritance. Basically, what we have here is two different tools each with different attributes. Sometime, they're easily interchangeable, sometime not and that's why we need both. But each time you have to choose, your choice will (or should) go down to the performance, memory, and flexibility implications of each. Choosing what's best will probably involve evaluating which approach better fits your needs, and this may even be measurable. Compare this with properties which have exactly the same performance, memory, and flexibility implications as regular functions. The only difference between a property and a function is the meaning the author give to it, and that meaning vary between authors and contexts. Which means that from the API user point of view, something being a property or a function doesn't mean much... except of course that the user has to remember if Singleton.Instance is a property or a function before using it, or else suffer some useless compiler errors. [^1]: Except scope classes which are allocated on the stack. But allocating scope classes on the stack is a mere optimisation which happen to be possible when you create a scope object, it doesn't affect the semantics of the language at all. -- Michel Fortin michel.fortin@michelf.com http://michelf.com/ |
October 02, 2008 Re: Revised RFC on range design for D2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Agh, got busy in these last days, so I was missing the discussion. Andrei Alexandrescu wrote: > Bruno Medeiros wrote: >> Andrei Alexandrescu wrote: >>> Bruno Medeiros wrote: >>>> Andrei Alexandrescu wrote: >>>>> In wake of the many excellent comments and suggestions made here, I made one more pass through the draft proposal for ranges. >>>>> >>>>> http://ssli.ee.washington.edu/~aalexand/d/tmp/std_range.html >>>>> >>>>> There are some comments in red illustrating some uncertainties (not all), and the names of the primitives have been updated. Bicycle shed galore! But don't forget to comment on the reactor as well :o). >>>>> >>>>> >>>>> Andrei >>>> >>>> """ >>>> All ranges satisfy certain invariants outlined below. (r is an object of a range type R.) >>>> """ >>>> >>>> By "object" you actually mean struct no? Struct instance to be even more precise. >>>> >>>> >>>> Also, some more on important bike shed issues: >>>> for (; !src.done; src.next) >>>> { >>>> tgt.put(src.head); >>>> } >>>> >>>> As a matter of coding style conventions, I would say that using the implicit property function call feature on a function that changes state is *bad* style, and surely hope the community would agree on that. >>> >>> I sure hope they won't agree to an unsupported assertion. >>> >> >> It's unsupported because it is not an assertion, but more of a subjective opinion, like most coding style conventions (indentation, bracing, etc.). I don't like seeing "src.next" if 'next' isn't either a field, or a function which doesn't change any significant state. > > I also don't like broccoli, but I eat it because there are reasons to do so. Would you agree that given reason, you'd use it even if you subjectively disliked it? > Yes, if there where good reasons, I'd use it. But what are those reasons? >>>> So "src.next" would be must better as "src.next()" as "src.next" really just makes me cringe. >>> >>> With me it's the opposite, particularly after I've written and stared at a few hundreds of "()"s due to a compiler bug. >>> >>> >>> Andrei >> >> I'm not imagining what that situation would be, could you explain a bit more? > > I phrased things poorly. The compiler bug is that parens for array functions in the postfix notation are required in some places and not in others. So I was forced to write much more parens than were strictly necessary, and all over the place. It gets really jarring. I've always thought required parens were a big annoyance in C++, and I can't believe people want to bring that back in D. > > > Andrei What I was trying to understand here, is that if the consistent usage of '()' for function calling, instead of omitting them, had lead you to bugs. (bugs in your code, not bugs in the compiler) In other words, were you presenting a reason for not consistently using parenthesis for function calling? The only reasons I've so far seen you present in favor of omitting parenthesis where this ones: """ I _believe_ a language should obey the principles 1 and 2 (economy of syntax and giving syntactic priority to frequent use cases). Based on that belief, I _think_ D should drop the trailing parens. I agree that somebody could _believe_ in some other principles that replace or override mine and then _think_ that keeping trailing parens is a good thing. Sergey did just that by showing us some very good examples when absence of trailing parens leads to ambiguity. Then there is room for meaningful discussion. It is also possible that somebody simply _believes_ the trailing parens should be kept because they make code clearer to them. That's fair too, as long as there is understanding that that belief comes to a certain extent at odds with principles 1 and 2 (which anyone is free to simply not believe). The only place that needs work is when the connection between belief and thought is unclear, or when the belief is simply wrong. """ I will reply in that respective post. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D |
October 02, 2008 Re: Revised RFC on range design for D2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | On 2008-10-02 01:25:34 -0400, "Bill Baxter" <wbaxter@gmail.com> said: > My first thought is what is the formal definition > for what should be a struct and what should be a class. Hum, I think I forgot to answer that part. The reason I say we need a formal definition is so we can actually imply things from something being a property. Pure and nothrow functions are (or will) be compile-time checked against a definition of what they should be: these offer garanties, which in turn add value to the user who know what it does. If we can't imply anything from them, properties offer no real value over mere functions since authors will decide what is a property based on the expectations they expect their users to have. To be frank, I don't expect we can agree on a formal definition. If we try and that is indeed the conclusion, it'll prove my point that you just can't imply anything from something being a property except the vague idea that the author thought it should be one according to his own definition. -- Michel Fortin michel.fortin@michelf.com http://michelf.com/ |
October 02, 2008 Re: Revised RFC on range design for D2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu wrote: > Benji Smith wrote: >> Andrei Alexandrescu wrote: >>> I stated two principles of language design. They could be true or false. They are up there for debate. They are subjective, because aside from some basics, language design is subjective. >>> >>> The principles are: >>> >>> 1) A language should minimize the number of syntactic constructs that are semantically and/or pragmatically meaningless. >>> >>> 2) The more frequently-used constructs should be given syntactic priority over the less-used constructs, particularly when the latter are also at risk of breaking the first principle. >> >> I'd like to propose another principle of language design: >> >> 3) Consistency -- The expression of a semantic construct should always use the same syntax. Likewise, multiple uses of the same syntactic constructs should always result in the same semantics. > > Consistency is good, but that's not consistency. > > http://www.merriam-webster.com/dictionary/consistency > > agreement or harmony of parts or features to one another or a whole : > correspondence ; specifically : ability to be asserted together without > contradiction > The concept of "consistency" has a more specialized meaning when applied to language design. (just has it has in other fields, like mathematics) So I agree with benji that not having "The expression of a semantic construct should always use the same syntax" is not being consistent. (There are of course other situations where things can be inconsistent.) If you don't agree with this definition of "consistency", I'm not gonna argue with that , just substitute it with "conzistency" or "foobar", or whatever and proceed. > An example of consistency is that user-defined operators have the same > syntax and precedence as built-in operators. > >> Based on that principle, I'd argue that function-calling should either always use parentheses, or it should never use parentheses. > > Yah I'd like that too. It's economy of syntax. > Then why are you not suggesting, or campaigning for, such change? >> Requiring parentheses for some function calls, but not for others violates the principle of consistency. > > No. It violates economy of syntax. There are many syntaxes for the same > semantics. It violates consistency, as defined above. It may violate economy of syntax as well (or it may be the same thing). Whatever. What I ask is, what would you suggest to fix it? Should all function calling not use parenthesis? And how would that syntax be? -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D |
October 02, 2008 Re: Revised RFC on range design for D2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | On Thu, Oct 2, 2008 at 8:26 PM, Michel Fortin <michel.fortin@michelf.com> wrote:
>
> Compare this with properties which have exactly the same performance, memory, and flexibility implications as regular functions. The only difference between a property and a function is the meaning the author give to it, and that meaning vary between authors and contexts. Which means that from the API user point of view, something being a property or a function doesn't mean much... except of course that the user has to remember if Singleton.Instance is a property or a function before using it, or else suffer some useless compiler errors.
Good points.
I think this discussion is diverging a little far from the real raison d'etre for property syntax, though. They are there in the first place not to save the typing of a few () here and there, but to allow a library designer to start with a plain field when that suffices and transition to a function later if that becomes necessary, without breaking client code. And there's where we can invoke a grand principle of software design as Andrei would have us do:
* Changing implementation details should not affect client code.
Ok I guess that's a software design principle, not language design but I guess I can say the underlying language principle is that the a good language should facilitate good software design.
This one has to trump principles about economy of syntax and such, because the point of having a language in the first place is to make writing software easier/better/faster.
More specifically this is a case of where we want syntax to facilitate making the transition from a simple field to something with some logic too. So what can we hope to get from the language to support this in the best way possible. These two conclusions seem pretty obvious to me:
1) The "fake" field's behavior should be indistinguishable from real
field behavior in as many circumstances as possible. This prevents
client code from having to change. This is why things like += on a
property should be transformed by the compiler.
2) In situations where behavior does differ from that of a real field,
a compiler error should occur at the point of usage. This prevents
nasty surprises where code silently starts behaving incorrectly. This
suggests that something like attempting to take the address of the
field should be a syntax error if the field is turned into a property
function. (This probably already happens in most cases since a
function pointer won't usually be interchangeable with an int pointer
or whatever it was before)
Anyway, the point I want to make is that while it's neat that you can save typing a few parentheses, there are more important things, like being able to refactor code locally and knowing with reasonable certainty that all client code will either still work correctly or fail to compile.
Going by these principles could lead to some interesting conclusions like for instance an argument that you shouldn't be able to take the address of a property function, or do anything else to it that exposes the fact that it is not, in fact, a field.
--bb
|
October 02, 2008 Re: Revised RFC on range design for D2 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu wrote: > > I _believe_ a language should obey the principles 1 and 2 (economy of syntax and giving syntactic priority to frequent use cases). Based on that belief, I _think_ D should drop the trailing parens. > > I agree that somebody could _believe_ in some other principles that replace or override mine and then _think_ that keeping trailing parens is a good thing. Sergey did just that by showing us some very good examples when absence of trailing parens leads to ambiguity. Then there is room for meaningful discussion. > > It is also possible that somebody simply _believes_ the trailing parens should be kept because they make code clearer to them. That's fair too, as long as there is understanding that that belief comes to a certain extent at odds with principles 1 and 2 (which anyone is free to simply not believe). > > The only place that needs work is when the connection between belief and thought is unclear, or when the belief is simply wrong. > > > Andrei Good post. Sergey's argument (which is much more objective than subjective) is not strictly against omitting parenthesis, but rather against ambiguity (the dual possible ways to call zero-args functions), which as has been shown, creates various possibilities for bugs when you mix functions that return delegates. This ambiguity problem would also be resolved if omitting parenthesis would be *the only way* of calling functions with zero-args. Anyways, I also agree with principles 1 and 2. But I also agree with some other principles that sometimes conflict with those first ones (which is what is happening here). And in each such scenario I would have to weight in to see which principle I would give priority. These other principles are: 3 - Consistency of syntax - The same language feature should use the same syntax, with as little variations as possible. This principle fails here because when you have functions with parameters you have to use parenthesis, and only when you don't have arguments you omit the parenthesis. But the zero-args case should not be different from the n-args case. Of course, this could be solved by having a syntax for the n-args case that also doesn't use parenthesis (see my OP after Benji's thread) But most importantly: 4 - Common ground with other programming languages. There are several things that are common with many, if not all, of the mainstream programming languages (Java, C#, C/C++, Ruby, Python, etc.). One of them is using parenthesis for calling functions! (See KennyTM's post with the table describing function calling for several languages.) Using parenthesis comes from math. And of that list, only VB 6, Pascal and Perl, have the possibility of omitting parenthesis. And frankly, VB6 and Pascal don't matter since they are pretty much obsolete. And Perl is language with a hack-ish nature, IMO. Even Lisp uses parenthesis for function calling! (even if in a different position, and even if it's pretty much the only syntax it has). This is a subjective principle, I can't tell you to want to like having common ground with other languages, but c'mon... "writeln;"? Seriously?? That's just hideous. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D |
Copyright © 1999-2021 by the D Language Foundation