digitalmars.D - Design of intuitive interfaces
- Norbert Nemec (59/59) Feb 20 2010 Hi there,
- Michel Fortin (27/41) Feb 21 2010 I that's a not so bad solution, applicable to almost any word. There
- bearophile (8/11) Feb 21 2010 Good.
- Michel Fortin (10/23) Feb 21 2010 Note that Ruby only accept this as a suffix, but yeah it's part of the
- bearophile (6/9) Feb 21 2010 OK, sorry for saying silly things again :-)
- Bill Baxter (4/6) Feb 21 2010 I would think that was a shorthand for some kind of "sorted queue"
- Adam D. Ruppe (6/8) Feb 21 2010 Or the lisp convention of -p? sorted_p()
- Ary Borenszweig (9/32) Feb 21 2010 But ruby has the ternary operator "?:", it just gives the "?" in the
- KennyTM~ (7/39) Feb 21 2010 enum foo = false;
- Ary Borenszweig (2/50) Feb 21 2010 Cases are known at compile-time.
- KennyTM~ (3/53) Feb 22 2010 The program is changed when you recompile. (The foo? function can be CTF...
- Jacob Carlborg (2/13) Feb 21 2010 I never liked that with ruby, I would prefer Michel Fortin's suggestion.
- Nick Sabalausky (7/25) Feb 21 2010 I'm surprised to hear that. I always thought it was very clean and more
- Jacob Carlborg (6/32) Feb 21 2010 Maybe it's because typing a ? or ! doesn't fit as good in my hands
- Walter Bright (4/12) Feb 21 2010 "split" - to split in place
- Andrei Alexandrescu (4/17) Feb 21 2010 Just to clarify: there is some point being missed here. It's not about
- Steven Schveighoffer (5/20) Feb 22 2010 By copy he means it doesn't affect the original. Retro returns a
- Lars T. Kyllingstad (5/27) Feb 22 2010 But it's a valid point. There are three degrees of freedom here, which
- Steven Schveighoffer (12/37) Feb 22 2010 As far as English terms go, how do you distinguish between a lazy and
Hi there, lately, there was some heated discussion about the naming of functions in the standard libraries. Rather than chiming in, I'd like to share some very general thoughts about this. Writing *intuitive* interfaces, be it for libraries or applications, is a very different issue than writing *correct* or *efficient* software. The most important difference is, how to react to to user feedback. In terms of correctness or efficiency, each single feedback is either right or wrong, so you can easily argue about its validity. Feedback about the intuitiveness of an interface, on the other hand, is by definition always right. After all it is a message from a user: "I had the following experience." Of course, there is still plenty of room to discuss it (wouldn't it be boring if there was nothing to talk about?) but it cannot be argued away. For one person speaking up, there are often many others experiencing the same thing and keeping silent. As for function naming: intuitive names are an essential aspect of the quality of a library. Of course, one could use a Russian library without understanding any of the names, but it would be a painful experience. Good function names should give a rough idea of their meaning and, more important, they should me memorable after reading the docs once. Commercial software design spends lots of time and money on field studies, doing statistics (yes, statistics!) on user feedback. Not having these resources, we have to make assumptions on our target user's background. Every interface has to be designed towards an audience. If it fails to address this audience, it will fail. Trying to imagine a "typical" user of the D library, I see a 21st century person with reasonable knowledge of the English language and some background other mainstream programming languages. Seeing the word "retro" that person will think "old style" rather than picking up the dictionary and looking up the original meaning. Seeing "iota", the person will think "???". No matter how good the explanation for any library name is, the fact that you have to give the explanation indicates that it is not intuitive. Now, of course, intuitivity is not everything. Conciseness is very important. Sometimes, introducing a new word is a good solution. Think of it as introducing a new technical term in writing an article or a book. Introducing a term that you cannot assume to be known by the audience, you first have to give an explanation. Doing so, you have to consider: is it worth introducing this term? Is it really more concise than using something known? OK, now, before this whole post begins to sound constipated, I'd rather finish by giving my own user feedback about the function names that were discussed. The name "retro" feels awkward to me as well. As this is a matter of in-place vs. input-preserving, I would suggest the solution in Python/NumPy: "sort" gives the command to sort data in-place "sorted" returns a sorted data, preserving the input similarly, I would suggest "reverse" to sort in-place "reversed" to return a modified copy The name "iota" seems confusing to me as well. Very few greek letters do indeed have a conventional meaning (e.g. lambda-calculus, delta for a difference or epsilon for a really small value). Calling a function by a meaningless name is not a good idea. Don't have a better idea right now, though... But as I said, usability really is about the "average" member of the audience, so this is really just one voice out of many. Greetings, Norbert
Feb 20 2010
On 2010-02-21 02:15:23 -0500, Norbert Nemec <Norbert Nemec-online.de> said:I would suggest the solution in Python/NumPy: "sort" gives the command to sort data in-place "sorted" returns a sorted data, preserving the input similarly, I would suggest "reverse" to sort in-place "reversed" to return a modified copyI that's a not so bad solution, applicable to almost any word. There are cases where it doesn't work ('split'), but probably not too much. The remaining problem with this is that it can easily be confused with a boolean property. Does "array.sorted" return true or false depending on whether the array is sorted, or does it return a sorted array? Perhaps this is where a property would be useful: array.sort() // sort in place array.sorted() // create sorted copy array.sorted // tell if the array is sorted but it doesn't scale when you need an argument. So I suggest that functions for evaluating a boolean characteristic start with the "is" prefix: array.sort(predicate) // sort in place using predicate array.sorted(predicate) // create sorted copy using predicate array.isSorted(predicate) // tell if the array is sorted using predicate I updated the D Programming Guidelines I wrote a while ago on Wiki4D to match this. <http://www.wikiservice.at/d/wiki.cgi?DProgrammingGuidelines>The name "iota" seems confusing to me as well. Very few greek letters do indeed have a conventional meaning (e.g. lambda-calculus, delta for a difference or epsilon for a really small value). Calling a function by a meaningless name is not a good idea. Don't have a better idea right now, though...Perhaps "interval"? After all, iota(1, 10) is the same concept as 1..10 which denotes an interval. Ideally we could reuse the ".." operator to create an interval, but it seems we can't. The next good solution is to use the same terminology. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 21 2010
Michel Fortin:array.sort(predicate) // sort in place using predicate array.sorted(predicate) // create sorted copy using predicate array.isSorted(predicate) // tell if the array is sorted using predicateGood. Another possibility is to let D2 accept ? and ! too inside variable names, so they can become (as in Ruby I think, and something similar is common in Lisp-like languages too): array.sort(predicate) array.sort!(predicate); // void function array.sorted?(predicate) Bye, bearophile
Feb 21 2010
On 2010-02-21 10:19:06 -0500, bearophile <bearophileHUGS lycos.com> said:Michel Fortin:Note that Ruby only accept this as a suffix, but yeah it's part of the identifier. And I'd love this, but the ! suffix is totally ambiguous with the template instantiation syntax, and the ? suffix would be ambiguous in the ternary operator "?:". -- Michel Fortin michel.fortin michelf.com http://michelf.com/array.sort(predicate) // sort in place using predicate array.sorted(predicate) // create sorted copy using predicate array.isSorted(predicate) // tell if the array is sorted using predicateGood. Another possibility is to let D2 accept ? and ! too inside variable names, so they can become (as in Ruby I think, and something similar is common in Lisp-like languages too): array.sort(predicate) array.sort!(predicate); // void function array.sorted?(predicate)
Feb 21 2010
Michel Fortin:the ! suffix is totally ambiguous with the template instantiation syntax, and the ? suffix would be ambiguous in the ternary operator "?:".OK, sorry for saying silly things again :-) I sometimes have used an upper case Q for the ? (it stands for Question mark): sortedQ() Bye, bearophile
Feb 21 2010
On Sun, Feb 21, 2010 at 7:36 AM, bearophile <bearophileHUGS lycos.com> wrote:I sometimes have used an upper case Q for the ? (it stands for Question mark): sortedQ()I would think that was a shorthand for some kind of "sorted queue" thing if I ran into it in the wild. --bb
Feb 21 2010
On Sun, Feb 21, 2010 at 10:36:53AM -0500, bearophile wrote:I sometimes have used an upper case Q for the ? (it stands for Question mark): sortedQ()Or the lisp convention of -p? sorted_p() Bah, I'd just say go with isSorted. sorted? is just bizarre anyway. -- Adam D. Ruppe http://arsdnet.net
Feb 21 2010
Michel Fortin wrote:On 2010-02-21 10:19:06 -0500, bearophile <bearophileHUGS lycos.com> said:But ruby has the ternary operator "?:", it just gives the "?" in the identifier more precedence. So there's just the backwards compatibility problem, but if you had: foo? something : something_else then now it won't compile ("foo?" can't be found) and you'll have to change it to foo ? something : something_else so it's a safe backwards incompatible change.Michel Fortin:Note that Ruby only accept this as a suffix, but yeah it's part of the identifier. And I'd love this, but the ! suffix is totally ambiguous with the template instantiation syntax, and the ? suffix would be ambiguous in the ternary operator "?:".array.sort(predicate) // sort in place using predicate array.sorted(predicate) // create sorted copy using predicate array.isSorted(predicate) // tell if the array is sorted using predicateGood. Another possibility is to let D2 accept ? and ! too inside variable names, so they can become (as in Ruby I think, and something similar is common in Lisp-like languages too): array.sort(predicate) array.sort!(predicate); // void function array.sorted?(predicate)
Feb 21 2010
On Feb 22, 10 06:07, Ary Borenszweig wrote:Michel Fortin wrote:enum foo = false; enum bar = 2; ... case foo?(1):bar: break; Suddenly, if "foo?" is defined, the value of the case completely changed and you've got a "bar" label.On 2010-02-21 10:19:06 -0500, bearophile <bearophileHUGS lycos.com> said:But ruby has the ternary operator "?:", it just gives the "?" in the identifier more precedence. So there's just the backwards compatibility problem, but if you had: foo? something : something_else then now it won't compile ("foo?" can't be found) and you'll have to change it to foo ? something : something_else so it's a safe backwards incompatible change.Michel Fortin:Note that Ruby only accept this as a suffix, but yeah it's part of the identifier. And I'd love this, but the ! suffix is totally ambiguous with the template instantiation syntax, and the ? suffix would be ambiguous in the ternary operator "?:".array.sort(predicate) // sort in place using predicate array.sorted(predicate) // create sorted copy using predicate array.isSorted(predicate) // tell if the array is sorted using predicateGood. Another possibility is to let D2 accept ? and ! too inside variable names, so they can become (as in Ruby I think, and something similar is common in Lisp-like languages too): array.sort(predicate) array.sort!(predicate); // void function array.sorted?(predicate)
Feb 21 2010
KennyTM~ wrote:On Feb 22, 10 06:07, Ary Borenszweig wrote:Cases are known at compile-time.Michel Fortin wrote:enum foo = false; enum bar = 2; ... case foo?(1):bar: break; Suddenly, if "foo?" is defined, the value of the case completely changed and you've got a "bar" label.On 2010-02-21 10:19:06 -0500, bearophile <bearophileHUGS lycos.com> said:But ruby has the ternary operator "?:", it just gives the "?" in the identifier more precedence. So there's just the backwards compatibility problem, but if you had: foo? something : something_else then now it won't compile ("foo?" can't be found) and you'll have to change it to foo ? something : something_else so it's a safe backwards incompatible change.Michel Fortin:Note that Ruby only accept this as a suffix, but yeah it's part of the identifier. And I'd love this, but the ! suffix is totally ambiguous with the template instantiation syntax, and the ? suffix would be ambiguous in the ternary operator "?:".array.sort(predicate) // sort in place using predicate array.sorted(predicate) // create sorted copy using predicate array.isSorted(predicate) // tell if the array is sorted using predicateGood. Another possibility is to let D2 accept ? and ! too inside variable names, so they can become (as in Ruby I think, and something similar is common in Lisp-like languages too): array.sort(predicate) array.sort!(predicate); // void function array.sorted?(predicate)
Feb 21 2010
On Feb 22, 10 07:29, Ary Borenszweig wrote:KennyTM~ wrote:The program is changed when you recompile. (The foo? function can be CTFE). The point is it is an unsafe backward incompatible change.On Feb 22, 10 06:07, Ary Borenszweig wrote:Cases are known at compile-time.Michel Fortin wrote:enum foo = false; enum bar = 2; ... case foo?(1):bar: break; Suddenly, if "foo?" is defined, the value of the case completely changed and you've got a "bar" label.On 2010-02-21 10:19:06 -0500, bearophile <bearophileHUGS lycos.com> said:But ruby has the ternary operator "?:", it just gives the "?" in the identifier more precedence. So there's just the backwards compatibility problem, but if you had: foo? something : something_else then now it won't compile ("foo?" can't be found) and you'll have to change it to foo ? something : something_else so it's a safe backwards incompatible change.Michel Fortin:Note that Ruby only accept this as a suffix, but yeah it's part of the identifier. And I'd love this, but the ! suffix is totally ambiguous with the template instantiation syntax, and the ? suffix would be ambiguous in the ternary operator "?:".array.sort(predicate) // sort in place using predicate array.sorted(predicate) // create sorted copy using predicate array.isSorted(predicate) // tell if the array is sorted using predicateGood. Another possibility is to let D2 accept ? and ! too inside variable names, so they can become (as in Ruby I think, and something similar is common in Lisp-like languages too): array.sort(predicate) array.sort!(predicate); // void function array.sorted?(predicate)
Feb 22 2010
On 2/21/10 16:19, bearophile wrote:Michel Fortin:I never liked that with ruby, I would prefer Michel Fortin's suggestion.array.sort(predicate) // sort in place using predicate array.sorted(predicate) // create sorted copy using predicate array.isSorted(predicate) // tell if the array is sorted using predicateGood. Another possibility is to let D2 accept ? and ! too inside variable names, so they can become (as in Ruby I think, and something similar is common in Lisp-like languages too): array.sort(predicate) array.sort!(predicate); // void function array.sorted?(predicate) Bye, bearophile
Feb 21 2010
"Jacob Carlborg" <doob me.com> wrote in message news:hlrk2c$2kq7$2 digitalmars.com...On 2/21/10 16:19, bearophile wrote:I'm surprised to hear that. I always thought it was very clean and more generally-useful than things like isBlah (I've frequently run into cases where the isBlah couldn't be used as it would have resulted in a gibberish variable name). Only problem I ever saw with it is that it's not a realistic possibility in D due to ambiguities with other parts of D's syntax.Michel Fortin:I never liked that with ruby, I would prefer Michel Fortin's suggestion.array.sort(predicate) // sort in place using predicate array.sorted(predicate) // create sorted copy using predicate array.isSorted(predicate) // tell if the array is sorted using predicateGood. Another possibility is to let D2 accept ? and ! too inside variable names, so they can become (as in Ruby I think, and something similar is common in Lisp-like languages too): array.sort(predicate) array.sort!(predicate); // void function array.sorted?(predicate) Bye, bearophile
Feb 21 2010
On 2010-02-21 21.06, Nick Sabalausky wrote:"Jacob Carlborg"<doob me.com> wrote in message news:hlrk2c$2kq7$2 digitalmars.com...Maybe it's because typing a ? or ! doesn't fit as good in my hands compared to other characters, this is using a swedish which requires two keys to be pressed. I think using the "is" prefix makes it more like english if you read it, for example, I read "if(array.isSorted)" as "if array is sorted".On 2/21/10 16:19, bearophile wrote:I'm surprised to hear that. I always thought it was very clean and more generally-useful than things like isBlah (I've frequently run into cases where the isBlah couldn't be used as it would have resulted in a gibberish variable name). Only problem I ever saw with it is that it's not a realistic possibility in D due to ambiguities with other parts of D's syntax.Michel Fortin:I never liked that with ruby, I would prefer Michel Fortin's suggestion.array.sort(predicate) // sort in place using predicate array.sorted(predicate) // create sorted copy using predicate array.isSorted(predicate) // tell if the array is sorted using predicateGood. Another possibility is to let D2 accept ? and ! too inside variable names, so they can become (as in Ruby I think, and something similar is common in Lisp-like languages too): array.sort(predicate) array.sort!(predicate); // void function array.sorted?(predicate) Bye, bearophile
Feb 21 2010
Michel Fortin wrote:On 2010-02-21 02:15:23 -0500, Norbert Nemec <Norbert Nemec-online.de> said:"split" - to split in place "splat" - to return a modified copy <g>similarly, I would suggest "reverse" to sort in-place "reversed" to return a modified copyI that's a not so bad solution, applicable to almost any word. There are cases where it doesn't work ('split'), but probably not too much.
Feb 21 2010
Walter Bright wrote:Michel Fortin wrote:Just to clarify: there is some point being missed here. It's not about in-place vs. copy. Please check retro's documentation. AndreiOn 2010-02-21 02:15:23 -0500, Norbert Nemec <Norbert Nemec-online.de> said:"split" - to split in place "splat" - to return a modified copysimilarly, I would suggest "reverse" to sort in-place "reversed" to return a modified copyI that's a not so bad solution, applicable to almost any word. There are cases where it doesn't work ('split'), but probably not too much.
Feb 21 2010
On Sun, 21 Feb 2010 16:21:29 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Walter Bright wrote:By copy he means it doesn't affect the original. Retro returns a "virtual" copy :) -SteveMichel Fortin wrote:Just to clarify: there is some point being missed here. It's not about in-place vs. copy. Please check retro's documentation.On 2010-02-21 02:15:23 -0500, Norbert Nemec <Norbert Nemec-online.de> said:"split" - to split in place "splat" - to return a modified copysimilarly, I would suggest "reverse" to sort in-place "reversed" to return a modified copyI that's a not so bad solution, applicable to almost any word. There are cases where it doesn't work ('split'), but probably not too much.
Feb 22 2010
Steven Schveighoffer wrote:On Sun, 21 Feb 2010 16:21:29 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:But it's a valid point. There are three degrees of freedom here, which ideally should be reflected in the API: in-place, copy and view (or virtual copy if you like). -LarsWalter Bright wrote:By copy he means it doesn't affect the original. Retro returns a "virtual" copy :)Michel Fortin wrote:Just to clarify: there is some point being missed here. It's not about in-place vs. copy. Please check retro's documentation.On 2010-02-21 02:15:23 -0500, Norbert Nemec <Norbert Nemec-online.de> said:"split" - to split in place "splat" - to return a modified copysimilarly, I would suggest "reverse" to sort in-place "reversed" to return a modified copyI that's a not so bad solution, applicable to almost any word. There are cases where it doesn't work ('split'), but probably not too much.
Feb 22 2010
On Mon, 22 Feb 2010 08:24:18 -0500, Lars T. Kyllingstad <public kyllingen.nospamnet> wrote:Steven Schveighoffer wrote:As far as English terms go, how do you distinguish between a lazy and eager copy? There are actually even more subtle possibilities. For example, split could return an array of slices -- which is not a copy of the data, but is a unique copy of the split points. I think it's not possible to have a rule to encompass all possibilities, but a rule to cover 80% of the most useful representations is good enough. Also, I would think one would prefer a view whenever possible, because you can always make a hard copy from the view, but you can't do it the other way around. -SteveOn Sun, 21 Feb 2010 16:21:29 -0500, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:But it's a valid point. There are three degrees of freedom here, which ideally should be reflected in the API: in-place, copy and view (or virtual copy if you like).Walter Bright wrote:By copy he means it doesn't affect the original. Retro returns a "virtual" copy :)Michel Fortin wrote:Just to clarify: there is some point being missed here. It's not about in-place vs. copy. Please check retro's documentation.On 2010-02-21 02:15:23 -0500, Norbert Nemec <Norbert Nemec-online.de> said:"split" - to split in place "splat" - to return a modified copysimilarly, I would suggest "reverse" to sort in-place "reversed" to return a modified copyI that's a not so bad solution, applicable to almost any word. There are cases where it doesn't work ('split'), but probably not too much.
Feb 22 2010