www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - "Consume", "Skip", "Eat", "Munch", "Bite", or...?

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
To focus the discussion about naming conventions, let's discuss one 
particular aspect. Right now we have in std.algorithm:

=======================
/**
If the range $(D doesThisStart) starts with $(I any) of the $(D
withOneOfThese) ranges or elements, returns 1 if it starts with $(D
withOneOfThese[0]), 2 if it starts with $(D withOneOfThese[1]), and so
on. If no match, returns 0.

Example:
----
assert(startsWith("abc", ""));
assert(startsWith("abc", "a"));
assert(!startsWith("abc", "b"));
assert(startsWith("abc", 'a', "b") == 1);
assert(startsWith("abc", "b", "a") == 2);
assert(startsWith("abc", "a", "a") == 1);
assert(startsWith("abc", "x", "a", "b") == 2);
assert(startsWith("abc", "x", "aa", "ab") == 3);
assert(startsWith("abc", "x", "aaa", "sab") == 0);
assert(startsWith("abc", "x", "aaa", 'a', "sab") == 3);
----
  */
uint startsWith(alias pred = "a == b", Range, Ranges...)
(Range doesThisStart, Ranges withOneOfThese);
=======================

I also defined recently:

=======================
/**
If $(D startsWith(r1, r2)), consume the corresponding elements off $(D
r1) and return $(D true). Otherwise, leave $(D r1) unchanged and
return $(D false).
  */
bool startsWithConsume(R1, R2)(ref R1 r1, R2 r2);
=======================

There are a few other functions like that: one version takes a range by 
value, the other takes it by reference and alters it.

The question is, what is a good naming convention for expressing that? 
Other examples: findConsume, consumeFind.


Andrei
Feb 20 2010
next sibling parent div0 <div0 users.sourceforge.net> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Andrei Alexandrescu wrote:
 There are a few other functions like that: one version takes a range by
 value, the other takes it by reference and alters it.
 
 The question is, what is a good naming convention for expressing that?
 Other examples: findConsume, consumeFind.
 
 
 Andrei

chomp? consume is probably best; it's very clear. - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFLgFubT9LetA9XoXwRArf2AKDHBXyi7hHoxZFLN0yS8HZiOPiFKwCeIbpK qNmv5S4We3wdkuRDVLAXmsg= =01Ac -----END PGP SIGNATURE-----
Feb 20 2010
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2010-02-20 15:48:10 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 To focus the discussion about naming conventions, let's discuss one 
 particular aspect. Right now we have in std.algorithm:
 
 =======================
 /**
 If the range $(D doesThisStart) starts with $(I any) of the $(D
 withOneOfThese) ranges or elements, returns 1 if it starts with $(D
 withOneOfThese[0]), 2 if it starts with $(D withOneOfThese[1]), and so
 on. If no match, returns 0.
 
 Example:
 ----
 assert(startsWith("abc", ""));
 assert(startsWith("abc", "a"));
 assert(!startsWith("abc", "b"));
 assert(startsWith("abc", 'a', "b") == 1);
 assert(startsWith("abc", "b", "a") == 2);
 assert(startsWith("abc", "a", "a") == 1);
 assert(startsWith("abc", "x", "a", "b") == 2);
 assert(startsWith("abc", "x", "aa", "ab") == 3);
 assert(startsWith("abc", "x", "aaa", "sab") == 0);
 assert(startsWith("abc", "x", "aaa", 'a', "sab") == 3);
 ----
   */
 uint startsWith(alias pred = "a == b", Range, Ranges...)
 (Range doesThisStart, Ranges withOneOfThese);
 =======================
 
 I also defined recently:
 
 =======================
 /**
 If $(D startsWith(r1, r2)), consume the corresponding elements off $(D
 r1) and return $(D true). Otherwise, leave $(D r1) unchanged and
 return $(D false).
   */
 bool startsWithConsume(R1, R2)(ref R1 r1, R2 r2);
 =======================
 
 There are a few other functions like that: one version takes a range by 
 value, the other takes it by reference and alters it.
 
 The question is, what is a good naming convention for expressing that? 
 Other examples: findConsume, consumeFind.

Instead of "startsWithConsume" you could use "consumePrefix" which sounds better. You could change "startsWith" to "hasPrefix" too to keep things consistent, even though "startsWith" isn't a bad name in itself. The small string parsing module I made has "consumeUntil" that consumes until a predicate tells it to stop. In fact, all my consuming primitives advancing over the string and returning a boolean starts with "consume", this makes their role very clear. I also have a "read" family of function that uses consumers as predicate to extract consumed strings return them. So I can write fun things like this: alias isChar!(' ') isSpace; alias isNotChar!(' ') isNotSpace; alias consumeOneWhile!(isNotSpace) consumeWord; alias consumeOneWhile!(isSpace) consumeSpaces; alias read!(consumeWord) readWord; string a = "hello world of fear ! "; string[] result = readSplit!(readWord, consumeSpaces)(a); assert(result == ["hello", "world", "of", "fear", "!"]); -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 20 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2010-02-20 15:48:10 -0500, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 To focus the discussion about naming conventions, let's discuss one 
 particular aspect. Right now we have in std.algorithm:

 =======================
 /**
 If the range $(D doesThisStart) starts with $(I any) of the $(D
 withOneOfThese) ranges or elements, returns 1 if it starts with $(D
 withOneOfThese[0]), 2 if it starts with $(D withOneOfThese[1]), and so
 on. If no match, returns 0.

 Example:
 ----
 assert(startsWith("abc", ""));
 assert(startsWith("abc", "a"));
 assert(!startsWith("abc", "b"));
 assert(startsWith("abc", 'a', "b") == 1);
 assert(startsWith("abc", "b", "a") == 2);
 assert(startsWith("abc", "a", "a") == 1);
 assert(startsWith("abc", "x", "a", "b") == 2);
 assert(startsWith("abc", "x", "aa", "ab") == 3);
 assert(startsWith("abc", "x", "aaa", "sab") == 0);
 assert(startsWith("abc", "x", "aaa", 'a', "sab") == 3);
 ----
   */
 uint startsWith(alias pred = "a == b", Range, Ranges...)
 (Range doesThisStart, Ranges withOneOfThese);
 =======================

 I also defined recently:

 =======================
 /**
 If $(D startsWith(r1, r2)), consume the corresponding elements off $(D
 r1) and return $(D true). Otherwise, leave $(D r1) unchanged and
 return $(D false).
   */
 bool startsWithConsume(R1, R2)(ref R1 r1, R2 r2);
 =======================

 There are a few other functions like that: one version takes a range 
 by value, the other takes it by reference and alters it.

 The question is, what is a good naming convention for expressing that? 
 Other examples: findConsume, consumeFind.

Instead of "startsWithConsume" you could use "consumePrefix" which sounds better. You could change "startsWith" to "hasPrefix" too to keep things consistent, even though "startsWith" isn't a bad name in itself.

But how about others? What is the overall convention? Also don't forget that many other languages have startsWith. I don't find hasPrefix terribly informative. a.hasAsPrefix(b) would be more like it, but then again Yigal's fantastic consistent naming scheme remains elusive. Andrei
Feb 20 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-02-20 19:12:21 -0500, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 But how about others? What is the overall convention?

In my module the convention was to always start the name with "consume". I had "consumeOneChar" with a predicate checking one character, "consumeOneString" for matching specific strings (same as your "startWith"), "consumeWhile" and "consumeUntil" taking a character predicate, "consumeCount" for repeating consuming something, etc. Through the module, "consume" is implying I am reading from the front of the string and consuming from there.
 Also don't forget that many other languages have startsWith. I don't 
 find hasPrefix terribly informative. a.hasAsPrefix(b) would be more 
 like it, but then again Yigal's fantastic consistent naming scheme 
 remains elusive.

Cocoa's NSString use hasPrefix (that's where I got the idea). To me both sound right. assert("exoplanet".hasPrefix("exo")). :-) I don't really have a problem with startWith, it just doesn't fit very well with "consume". But if like me you assume "from the front" to be implicitly part of the meaning of "consume", then you don't need the "startWith" part. :-) You could use "consumeFront" to make things absolutely clear. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 20 2010
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmail.com> writes:
Andrei Alexandrescu wrote:

 I also defined recently:
 
 =======================
 /**
 If $(D startsWith(r1, r2)), consume the corresponding elements off $(D
 r1) and return $(D true). Otherwise, leave $(D r1) unchanged and
 return $(D false).
   */
 bool startsWithConsume(R1, R2)(ref R1 r1, R2 r2);
 =======================
 
 There are a few other functions like that: one version takes a range by
 value, the other takes it by reference and alters it.
 
 The question is, what is a good naming convention for expressing that?
 Other examples: findConsume, consumeFind.
 
 
 Andrei

I thought that that was basically what chompPrefix did, and chompPrefix seems like a great name to me, but I guess that that's not entirely generalizable: chompFind or findChomp would be a bit weird. Consume seems like the best of the ones that you suggested. It is explicitly what you're doing. It's a bit long, but the others aren't as clear. Other suggestions might be erase or remove, since you appear to be erasing/removing elements from the range. Consume is probably better though. - Jonathan M Davis P.S. You could also go for startsWithFineDiningWithAFourCourseMeal. People would absolutely love _that_ function name. ;)
Feb 20 2010
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jonathan M Davis wrote:
 Andrei Alexandrescu wrote:
 
 I also defined recently:

 =======================
 /**
 If $(D startsWith(r1, r2)), consume the corresponding elements off $(D
 r1) and return $(D true). Otherwise, leave $(D r1) unchanged and
 return $(D false).
   */
 bool startsWithConsume(R1, R2)(ref R1 r1, R2 r2);
 =======================

 There are a few other functions like that: one version takes a range by
 value, the other takes it by reference and alters it.

 The question is, what is a good naming convention for expressing that?
 Other examples: findConsume, consumeFind.


 Andrei

I thought that that was basically what chompPrefix did, and chompPrefix seems like a great name to me, but I guess that that's not entirely generalizable: chompFind or findChomp would be a bit weird. Consume seems like the best of the ones that you suggested. It is explicitly what you're doing. It's a bit long, but the others aren't as clear. Other suggestions might be erase or remove, since you appear to be erasing/removing elements from the range. Consume is probably better though. - Jonathan M Davis P.S. You could also go for startsWithFineDiningWithAFourCourseMeal. People would absolutely love _that_ function name. ;)

Heh. Overall the problem of choosing names by consensus is that the intersection is withering real fast. I agree 80% with Kenny's and Michel's choices. Others also seem to agree about the same percentage. The problem is that nobody agrees on the _same_ 80%. The net intersection of several people's "obviously good" naming schemes and conventions quickly falls to zero as the size of the group increases. Andrei
Feb 20 2010
next sibling parent Jonathan M Davis <jmdavisProg gmail.com> writes:
 Heh.
 
 Overall the problem of choosing names by consensus is that the
 intersection is withering real fast. I agree 80% with Kenny's and
 Michel's choices. Others also seem to agree about the same percentage.
 The problem is that nobody agrees on the _same_ 80%. The net
 intersection of several people's "obviously good" naming schemes and
 conventions quickly falls to zero as the size of the group increases.
 
 Andrei

Well, then it's probably a case where you should find a naming scheme that you're happy with and is relatively clear to most people. There are always going to be people who don't like a particular name or think that one name is clearer than another. So, it seems like it would be a good idea to get some suggestions for names (like you're doing), pick what you like, verify that there not considered horrifically bad by the group (though that doesn't mean that the group agrees with them), and then just use them. As long as the names are fairly clear, I don't think that it matters all that much. I know that even if I were picking all of the names myself, there would be bound to be a few that I didn't like because they were too long or following a particular naming convention made some of the functions have poorer names than I'd like, so I certainly don't expect you to come up with names that I'd like perfectly if I can't. And, as you say, a naming scheme that I like perfectly would undoubtedly be disliked by others, even if you could find it. Find a naming scheme you like and go with it. I'd say that the most important things for the names are that they are relatively clear and consistent. When it comes down to it, it's what the functions actually do which matters most. Beyond that, we just need the names to clearly indicate that function. So, names are important, but don't kill yourself over them. You clearly can't please everyone. - Jonathan M Davis
Feb 20 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmail.com> writes:
Oh, and while some names seem odd at first, they can definitely grow on you. 
For instance, I thought that retro was quite odd at first, but I'm 
definitely starting to like it. I would have suggested reverse (which I 
guess was out due to arrays), or maybe rev, but retro is shorter than 
reverse and I think ultimately clearer than rev. retro is quite memorable, 
is short, isn't an abbreviation, and fits fairly well once you get past the 
initial bizarreness of it.

While there may be complaints about some weird function names now, people 
will get used to them and may even prefer them. Like many things in Computer 
"Science," picking functions names is definitely an art - and a very 
imprecise one at that.

- Jonathan M Davis
Feb 20 2010
prev sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Andrei Alexandrescu wrote:

 Jonathan M Davis wrote:
 Andrei Alexandrescu wrote:
 
 I also defined recently:

 =======================
 /**
 If $(D startsWith(r1, r2)), consume the corresponding elements off $(D
 r1) and return $(D true). Otherwise, leave $(D r1) unchanged and
 return $(D false).
   */
 bool startsWithConsume(R1, R2)(ref R1 r1, R2 r2);
 =======================

 There are a few other functions like that: one version takes a range by
 value, the other takes it by reference and alters it.

 The question is, what is a good naming convention for expressing that?
 Other examples: findConsume, consumeFind.


 Andrei

I thought that that was basically what chompPrefix did, and chompPrefix seems like a great name to me, but I guess that that's not entirely generalizable: chompFind or findChomp would be a bit weird. Consume seems like the best of the ones that you suggested. It is explicitly what you're doing. It's a bit long, but the others aren't as clear. Other suggestions might be erase or remove, since you appear to be erasing/removing elements from the range. Consume is probably better though. - Jonathan M Davis P.S. You could also go for startsWithFineDiningWithAFourCourseMeal. People would absolutely love _that_ function name. ;)

Heh. Overall the problem of choosing names by consensus is that the intersection is withering real fast. I agree 80% with Kenny's and Michel's choices. Others also seem to agree about the same percentage. The problem is that nobody agrees on the _same_ 80%. The net intersection of several people's "obviously good" naming schemes and conventions quickly falls to zero as the size of the group increases. Andrei

Yeah, but everybody does agree that consistency is the overriding concern. There is still consistency to be gained between std.file / std.string / std.algorithm etc. (more so than in std.algorithm itself). Consistency is hard though, because you have to make up rules for something that is connected to natural language, and a messy one too. Luckily english has a freaking huge vocabulary :) On a related note, thanks for reordering take's parameters.
Feb 22 2010
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sat, Feb 20, 2010 at 02:48:10PM -0600, Andrei Alexandrescu wrote:
 bool startsWithConsume(R1, R2)(ref R1 r1, R2 r2);

I rather like that. I didn't at first, but I tried think of alternatives and everything came up short. xxxxConsume() it a nice, short way of saying "if xxxx, consume xxxx". It rather reminds me of the convenience functions in ncurses - looks weird at first, but it is a very simple rule to learn. Another nice thing about putting it at the end, is my editor's autocomplete would kick right in. I type "startsWith", hit tab and see the various modifiers. Minor thing, but I'd like it. They start exactly the same. The more I think about it, the more I like it. -- Adam D. Ruppe http://arsdnet.net
Feb 20 2010
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--0015174c35aa670def04801c2321
Content-Type: text/plain; charset=ISO-8859-1

On Sat, Feb 20, 2010 at 21:48, Andrei Alexandrescu <
SeeWebsiteForEmail erdani.org> wrote:

 To focus the discussion about naming conventions, let's discuss one
 particular aspect. Right now we have in std.algorithm:

 There are a few other functions like that: one version takes a range by
 value, the other takes it by reference and alters it.

 The question is, what is a good naming convention for expressing that?
 Other examples: findConsume, consumeFind

Would using policies be a solution? enum ModificationPolicy { doesNotModify, Modifies}; That way, you can keep the same name throughout the module. And the same for eager or lazy versions of some algorithms. Map/Filter could be eager rather than lazy (though I like them lazy) and return an array. Would that be possible, with well-thought defaults? Philippe --0015174c35aa670def04801c2321 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable On Sat, Feb 20, 2010 at 21:48, Andrei Alexandrescu <span dir=3D"ltr">&lt;<a= href=3D"mailto:SeeWebsiteForEmail erdani.org">SeeWebsiteForEmail erdani.or= g</a>&gt;</span> wrote:<br><div class=3D"gmail_quote"><blockquote class=3D"= gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb= (204, 204, 204); padding-left: 1ex;"> To focus the discussion about naming conventions, let&#39;s discuss one par= ticular aspect. Right now we have in std.algorithm:<br></blockquote><div>(s= nip) <br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0= pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> There are a few other functions like that: one version takes a range by val= ue, the other takes it by reference and alters it.<br> <br> The question is, what is a good naming convention for expressing that? Othe= r examples: findConsume, consumeFind</blockquote><div><br>Would using polic= ies be a solution?<br><br>enum ModificationPolicy { doesNotModify, Modifies= };<br> <br>That way, you can keep the same name throughout the module.<br><br>And = the same for eager or lazy versions of some algorithms. Map/Filter could be= eager rather than lazy (though I like them lazy) and return an array.<br> <br>Would that be possible, with well-thought defaults?<br><br><br>=A0 Phil= ippe<br><br><br>=A0</div></div> --0015174c35aa670def04801c2321--
Feb 21 2010