Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add _.startsWith and _.endsWith #668

Closed
wants to merge 1 commit into from
Closed

Add _.startsWith and _.endsWith #668

wants to merge 1 commit into from

Conversation

ianb
Copy link

@ianb ianb commented Jul 11, 2012

This adds _.startsWith and _.endsWith. These work with both strings and arrays.

Both methods are proposed on strings in Harmony: http://wiki.ecmascript.org/doku.php?id=harmony:string_extras – extending them to also work on arrays seems natural.

This makes specific tests for arrays, because it only makes sense for ordered collections. _.isArray seems crude and maybe wrong (e.g., why shouldn't it work with childNodes or something array-like), but I'm not sure how better to detect indexable ordered collections.

Also if the types don't work out it returns false. Should it throw an error? And there's implicit string coercion, which maybe is okay or maybe not.

@ianb
Copy link
Author

ianb commented Jul 11, 2012

The coercion issue is the same as here: #667 – and the two should probably be consistent.

@davidchambers
Copy link
Contributor

Should these accept an arbitrary number of arguments? For example:

_.startsWith(url, 'http:', 'https:')

Equivalent to:

url.indexOf('http:') == 0 || url.indexOf('https:') == 0

What about regular expressions?

_.startsWith(url, /https?:/)

Equivalent to:

/^https?:/.test(url)

If we ignore regular expressions, this evaluates as true:

_.startsWith('/@+/123', /@+/)

String::replace handles regular expressions intelligently; I believe that startsWith and endsWith should too.

Related: Underscore.string

@paulmillr
Copy link

In my opinion it should do only es6 stuff and fallback to native version.

@davidchambers
Copy link
Contributor

I don't disagree. I'm suggesting that ES6, too, treat regular expressions as patterns in this context. (I should bring this up in a more appropriate forum.)

@ianb
Copy link
Author

ianb commented Jul 11, 2012

Ouch, coercing a regex to a string leads to something quite unexpected it seems. It would seem unusual to reject a regex entirely, which would make me inclined to think it should handle a regex intelligently.

In Python you can do a_string.startswith(('http:', 'https:')) – i.e., there is a particular test for a tuple. For the most part developers seem unable to remember this, so while it's a seemingly useful feature I've never seen it used in the wild. Doing that kind of type test in Javascript seems more error-prone as well.

I looked at the Underscore.string implementations but did not find them particularly inspiring.

@davidchambers
Copy link
Contributor

These String extensions may be worth a look, Ian.

@jashkenas
Copy link
Owner

For what it's worth, our general policy has always been to leave string methods out of Underscore, as there are a large number of useful ones, and folks rarely agree on which. See many previous tickets.

I'd bet if you worked on making a complete "string function" library using your best judgement, you might end up with something that approaches the size of Underscore in the first place. That's one fine way to go...

... I think the only circumstance under which we should merge string functions in would be:

  • If you make a reasonably thorough study of the common string helper functions in JavaScript.
  • If the patch is complete, providing a set of functions we can stand behind as all the ones you'll really need for most apps.
  • If the patch doesn't add too much to the minified size of the library. (Too much being more than an additional 25-50%).

@ianb
Copy link
Author

ianb commented Jul 11, 2012

The reason I chose these two functions (and extending _.contains) are:

  • They all represent functionality proposed as future methods on String
  • The semantics are relatively clear, and the implementation can be finalized (of course there's questions raised in this thread, but I'd like to think that's more about thoroughness than natural complexity)
  • The common practice for doing these things is hard to read and easy to get wrong

Instead of proposing a complete list of functions I thought instead I'd start with the approach of proposing what I think are the least controversial functions and see how far it goes. _.escape() does provide at least a little bit of precedence.

If I was making a longer list I'd probably add:

  • trim, trimLeft, trimRight – if we're interested in adding compatibility for environments where these methods aren't available (they are added to String in ES5)
  • Something to do a limited number of splits. Underscore.str's _.str.strRight and family are one possibility. Python has str.split(sep, limit) (and rsplit) which I think is somewhat more general, though I find it awkward in some failure situations. Python's str.partition is probably better.
  • Maybe something like _.str.lines, though with the addition of Python's str.splitlines(True) that maintains line endings (so `lines(aString, True).join('') == aString).

At least that's what I get from looking at Underscore.string, the CoffeeScript helpers that were linked to, MooTools String. But a selection depends some on the criteria – for instance, I am personally biased against language-related functions like capitalize or camelCase.

@ianb
Copy link
Author

ianb commented Jul 11, 2012

RegExp issues noted here: https://bugs.ecmascript.org/show_bug.cgi?id=498

@jashkenas
Copy link
Owner

I think we're going to stick with tradition here, and leave string helpers to the domain of other libraries, or Underscore plugins. I don't feel like just adding:

  • startsWith
  • endsWith
  • contains
  • trim (left/right)
  • split

... would make for a very satisfactory set of functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants