Sorry, I keep forgetting to change the reply to address to phobos. grrrrr....
-Steve ----- 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 release > > > > >> ________________________________ >> From: Robert Jacques <[email protected]> >> To: Steve Schveighoffer <[email protected]>; Discuss the phobos > library for D <[email protected]> >> Sent: Saturday, April 23, 2011 1:03 PM >> Subject: Re: [phobos] Time to get ready for the next release >> >> On Fri, 22 Apr 2011 13:22:31 -0400, Steve Schveighoffer > <[email protected]> wrote: >>>> From: Robert Jacques <[email protected]> >> [snip] >>>> Third, came criticisms of naming a factory method 'seconds' > in the first place (noun/verb distinctions, etc), and the associative > criticisms > of fixing a bad design via a proverbial sledgehammer. >>> >>> The goal was to have something short. At the time, I was fighting for > changing the time code in Tango, and one of the criticisms was that the > factory > method names were too long (don't remember what I originally had). Code > like Socket.select(5.0) was going to be replaced with > Socket.select(TimeSpan.seconds(5)). This was sort of a compromise. > Ironically, > we had to change it to something more verbose because of this problem. >> >> I understand. But I think you side-stepped my actually thought a bit, so let > me be a bit more verbose. Conciseness and clarity are probably the two most > at > odds 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' discussions > regarding 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 are > just 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-standard > function 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, > which > exists 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 was > a compromise, and as far as intuitiveness goes, it's pretty low on the > scale. 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 bikeshed > issues. > > > I think this was half a victim of D's flawed property design, and half a > victim 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 property > issue: > > TimeSpan.seconds(5); // looks ok to me, not great, but not misleading > either. > It looks like a constructor, which it actually is. > > > TimeSpan.seconds = 5; // absolutely misleading. > > 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 a > function that is a property. > > 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 to > omit parentheses for things that should clearly be viewed as actions. > > 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 mean > read buf into the stream? I have no idea. 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. I understand that *most* people won't use it that > way, but as a library designer, I want to patch all the holes, and make the > API > as tight as possible. 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. > > 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, we > could have both, if we could annotate both styles, but then the question > becomes, 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. > > >>>> Currently I'm pondering whether capitalized factory methods, in > order to mimic ctor syntax, would be an acceptable design. I doubt anyone > would > every have tried s.Seconds = 5, and thanks to auto, I also doubt anyone would > call TimeSpan.Seconds s. And unlike (an impure) s.seconds = 5, > TimeSpan.Seconds > s; simply doesn't compile. Plus, it self-documents the factory concept in > the name. >>> >>> If you used C# regularly, where everything is capitalized, you might > expect capitalized method names and properties. But in any case, why is > capitalization more of a distinguisher than parentheses or lack thereof? >> >> Capitalization in D and other languages is generally used for user defined > types (structs/classes)[1], while variable, field and method names use > camelCase > or under_scores (i.e. they start with a lower case). The primary exception to > this are constructors, which used the type name and therefore are > capitalized. > Since a factory method is conceptually identical to a constructor, > capitalizing > factory methods provides an innate understanding of what the method does, > what > it is used for and how you should call it, to both the corder and code > reviewer. > Mandated parenthesis, on the other hand, allows the code reviewer only to > understand that it is an action, not what type of action it is and the for > coder > to get a compiler error when they misunderstand, because the API is poorly > designed, what the method does, what it is used for and how you should call > it. >> >> [1] Of course, sometimes UDTs use lower case, like float3, to make them feel > more like built-in types. > > > C# is drastically different. Capitalization is used for all methods, all > custom > types, and properties. I can't say I like that style, but that's the > style. > > See here: http://msdn.microsoft.com/en-us/library/x2dbyw72%28v=vs.71%29.aspx > > > In neither C# nor D are these rules enforced by the compiler. BUT, the > decision > to capitalize or not is up to the library designer, *not* the caller, and the > compiler *does* enforce capitalization as decided by the library designer. > This > is a large difference from loose properties, where the caller gets to decide > the > semantics, not the library designer. All the library designer can do is try > and > pick names (which he can control) that make one syntax look utterly horrific. > > And that is my point, the library designer is forced to exclude some names > that > might be unconfusing (if the usage was enforced) in order to compensate for > the > possibility that the user uses the code the wrong way. > > It's like having a car with a switch that goes from two wheel drive to one > wheel drive. And then in order to persuade the driver to not use that > switch, > you make the car beep annoyingly if they engage the swtich to one-wheel > drive. > The better design is to not include the switch at all. > > -Steve > _______________________________________________ phobos mailing list [email protected] http://lists.puremagic.com/mailman/listinfo/phobos
