----- Forwarded Message -----From: Steve Schveighoffer <[email protected]> To: Robert Jacques <[email protected]> Cc: Sent: Monday, April 25, 2011 7:57 AM Subject: Re: [phobos] Time to get ready for the next releaseFrom: Robert Jacques <[email protected]> To: Steve Schveighoffer <[email protected]>; Discuss the phoboslibrary for D <[email protected]>Sent: Saturday, April 23, 2011 1:03 PM Subject: Re: [phobos] Time to get ready for the next releaseOn Fri, 22 Apr 2011 13:22:31 -0400, Steve Schveighoffer<[email protected]> wrote:in the first place (noun/verb distinctions, etc), and the associative criticismsFrom: Robert Jacques <[email protected]>[snip]Third, came criticisms of naming a factory method 'seconds'of fixing a bad design via a proverbial sledgehammer.changing the time code in Tango, and one of the criticisms was that the factoryThe goal was to have something short. At the time, I was fighting formethod names were too long (don't remember what I originally had). Code like Socket.select(5.0) was going to be replaced withSocket.select(TimeSpan.seconds(5)). This was sort of a compromise. Ironically,we had to change it to something more verbose because of this problem.me be a bit more verbose. Conciseness and clarity are probably the two most atI understand. But I think you side-stepped my actually thought a bit, so letodds aspects of any API design. The general conventions are variables/fields/'property's should be names and functions/methods should be verbs. I have seen many a post in the 'property' discussionsregarding how verb = value or noun(value) is Evil(TM). Personally, I take it as a rule of thumb and not as a hard and fast rule. Anyways, any designer who uses a noun for an action, should be aware that they are actively courting the very confusion in this bug report. So, from an API design perspective, the author sacrificed too much clarity for consciousness. And this criticism remains true even with @property, enabled. Users are still going to try compile s.seconds =5, because the API design of 'seconds' differs from the design of its class, its module, its library and general expectations. They arejust going to get a compiler error, instead of a do nothing expression. And while we deal with non-standard designs all the time, in the form of DSLs,mini-DSLs and 'by convention' frameworks, a single, non-standardfunction generally only increases a programmer's cognitive load, without any additional benefits. And proposing the creation/justification of a language level features in order to mitigate (not fix) a minor issue with an API, whichexists solely due to the API's poor design (which violates its class's design guides), is like taking a sledge hammer to kill a fly.I agree with all of this, actually. I don't love the interface, but it wasa compromise, and as far as intuitiveness goes, it's pretty low on thescale. However, you have to pick your battles, and having a much better time API in tango was better than having the code refused over somewhat bikeshedissues. I think this was half a victim of D's flawed property design, and half avictim of being able to call static functions using an instance for namespace.Fix the latter problem in the compiler, and the function can only be called with the struct name as the namespace. However, it does not remove the propertyissue:TimeSpan.seconds(5); // looks ok to me, not great, but not misleading either.It looks like a constructor, which it actually is.
This looks unnatural to me, both as a reviewer and as a coder. The reviewer sorts the meaning quickly enough, after a little inference. But a coder will not naturally write this the first time, assuming they haven't read the manual recently.
TimeSpan.seconds = 5; // absolutely misleading.
And _looks_ absolutely natural ( therefore is absolutely misleading to both coder and reviewer :) ). By the way, a 'bug' like this is a good indication that the user wants a way to set a TimeSpan's span(?) outside of the factory methods (i.e. an additional API feature).
So I think even though it's somewhat of a combination of issues, the property issue is not invalid.The issue is more prevalent when talking about ambiguous words, especially ones that can be both nouns/adjectives and verbs. The issue I have with not being able to require parentheses is, lack of parentheses evoke an expectation of a field, either setting or getting that field. Parentheses evoke more of an action than a field, but that's not as strong, because you can easily make afunction that is a property.
Yes, parentheses evoke actions more that data, and I would expect the average coder to use them in a natural (for them) way. Generally, coders do not try to make their code unnatural, except in sport. And differences in 'natural' coding styles (i.e. ambiguities) are perfectly expected. To combat this (among other things), the designer writes documentation. Therefore confusion and misuse should only occur if the user a) hasn't fully read the docs or b) it has been some time since they did read the docs, and they've forgotten pertinent information. And if a user has forgotten what 'seconds' does, they've probably also forgotten whether it's const, or immutable, or pure or @property. Mandating parentheses doesn't help the user remember how to call/use a function, because we Humans remember names extremely well, purpose/behavior decently well and arbitrary tags poorly.
If you just require @properties to be called without parentheses, it doesn't solve the largest problem with D's property system -- that is, being able toomit parentheses for things that should clearly be viewed as actions.
:) If it's clearly an action, then shouldn't it have a nice actiony name? :)
Here is an artificial, but not so improbable example: stream.read = buf;what does this mean? Does it mean, set the read buffer to buf? Does it meanread buf into the stream? I have no idea.
Really? I know it supposed to be a synthetic example, but read's a verb. It does stuff. If it was the read buffer, it would be named readBuffer; a noun.
But this is completely clear: stream.read(buf); it means, read the stream data into buf. However, D treats them both equivalently, and throws no error on the super-confusing usage.
You are aware that the 'stream.read = buf;' is logically correct? And that for whoever that wrote it that way, it had to be natural and non-confusing.
I understand that *most* people won't use it thatway, but as a library designer, I want to patch all the holes, and make the APIas tight as possible.
But a hole isn't _always_ generated by 'unapproved' syntactic usage. A hole only occurs when the syntactic usage causes the code to become meaningless or invalid; and we can patch most (all?) of those.
I want code that uses the library to read as naturally as possible. So I might rename the function "readTo" to ensure the verb status of "read." To me, this is a sucky compromise that feels artificially created by the compiler.
Improving the clarity of your library is a 'sucky compromise'?
You might have different design goals, and different opinions, but the reality is, we have to choose one way or the other, we can't have both. Well, wecould have both, if we could annotate both styles, but then the questionbecomes, is it worth complicating the language to have one style over the other.D should either adopt @property as a strict enforcement, or not have it at all.Having it half-ass reflects poorly on the language design.
Thank you for your opinion. _______________________________________________ phobos mailing list [email protected] http://lists.puremagic.com/mailman/listinfo/phobos
