Adding .map() directly to String prototype

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

Adding .map() directly to String prototype

Ben Fletcher
Consider adding the array .map() implementation directly to the String prototype.

Here is a possible polyfill:

    String.prototype.map = function (fn) {
      return Array.prototype.map
        .call(this, fn)
        .join('');
    }

This replaces the common pattern of splitting, mapping, joining strings for processing.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

Rodrigo Carranza
In fact there should be a common interface that iterables should implement. I think this could have been proposed before. This way there would be not more common methods proposals.
On may. 17 2018, at 10:16 am, Ben Fletcher <[hidden email]> wrote:

Consider adding the array .map() implementation directly to the String prototype.

Here is a possible polyfill:

String.prototype.map = function (fn) {
return Array.prototype.map
.call(this, fn)
.join('');
}

This replaces the common pattern of splitting, mapping, joining strings for processing.
_______________________________________________
es-discuss mailing list
https://mail.mozilla.org/listinfo/es-discuss

Libre de virus. www.avast.com

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

kdex
In reply to this post by Ben Fletcher
This idea comes from a rather ASCII-centric perspective upon strings and will
definitely break multi-byte characters. And even if it wouldn't, your intent
might have been to do just that.

Long story short, it's debatable what exactly you want to iterate in a string,
hence such a method would lead to pretty bad practice and should therefore not
be added to the language.

On Thursday, May 17, 2018 5:16:03 PM CEST Ben Fletcher wrote:

> Consider adding the array .map() implementation directly to the String
> prototype.
>
> Here is a possible polyfill:
>
>     String.prototype.map = function (fn) {
>       return Array.prototype.map
> .call(this, fn)
> .join('');
>     }
>
> This replaces the common pattern of splitting, mapping, joining strings for
> processing. _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

devlato
In reply to this post by Ben Fletcher
I think makes sense to have String.prototype.reduce too then.

17.05.2018, 17:16, "Ben Fletcher" <[hidden email]>:

> Consider adding the array .map() implementation directly to the String prototype.
>
> Here is a possible polyfill:
>
>     String.prototype.map = function (fn) {
>       return Array.prototype.map
>         .call(this, fn)
>         .join('');
>     }
>
> This replaces the common pattern of splitting, mapping, joining strings for processing.
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

T.J. Crowder-2
In reply to this post by kdex
On Thu, May 17, 2018 at 4:24 PM, kdex <[hidden email]> wrote:
> This idea comes from a rather ASCII-centric perspective upon strings and will
> definitely break multi-byte characters.

No. One of the improvements to JavaScript since ES5 (you know, those things you keep objecting to) is that strings are now iterable, and the iteration visits *characters* (codepoints), not code units. (Example: https://jsfiddle.net/03tLpbrv/) (Also worth noting that JavaScript strings were never ASCII-centric. They were UTF16-centric [with invalid surrogate pairs tolerance].)

If there were a `.map` added, it would presumably visit characters, not code units, as well; it would be the only reasonable thing to do, both in light of how strings iterate and just general utility/appropriateness.

-- T.J. Crowder

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

T.J. Crowder-2
In reply to this post by Ben Fletcher
On Thu, May 17, 2018 at 4:16 PM, Ben Fletcher <[hidden email]> wrote:
> Consider adding the array .map() implementation directly to the String prototype.
>
> Here is a possible polyfill:
>
>     String.prototype.map = function (fn) {
>       return Array.prototype.map
>         .call(this, fn)
>         .join('');

Recommend something using the string's iterator instead, since the version above will visit code units, not codepoints (characters). Crude unoptimized version (https://jsfiddle.net/dkty51ys/):

```js
Object.defineProperty(String.prototype, "map", {
    value: function(fn, thisArg = undefined) {
        let result = "";
        for (const ch of this) {
            result += fn.call(thisArg, ch);
        }
        return result;
    }
});
```

or via conversion to array and back (https://jsfiddle.net/r0uqgx65/):

```js
Object.defineProperty(String.prototype, "map", {
    value: function(fn, thisArg = undefined) {
        return [...this].map(fn, thisArg).join("");
    }
});
```

> This replaces the common pattern of splitting, mapping, joining
> strings for processing.

Is it really that common? If so, the footgun available (iterating code units rather than codepoints), could be an argument in favor...

-- T.J. Crowder

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

T.J. Crowder-2
In reply to this post by T.J. Crowder-2
Combining marks will continue to be an issue (as they are with iteration), but I'd expect that code dealing with languages for which combining marks are a significant thing wouldn't be doing this sort of mapping in the first place, or will have language-specific rules for handling mapping with combining marks. If it's a pain point for someone, they can always propose a locale-specific mapping function standard, perhaps for ECMA-402...

-- T.J. Crowder

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

Scott Sauyet
In reply to this post by Ben Fletcher
On Thu, May 17, 2018 at 11:16 AM, Ben Fletcher <[hidden email]> wrote:

> Consider adding the array .map() implementation directly to the String prototype.

There is a big difference between mapping over an array and mapping
over a string.  Arrays can hold *anything*.  Strings hold only
characters.  So for a function that takes something of type A and
returns something of type B, `map`ping it over an array takes an array
of As and returns an array of Bs.

```js
['a', 'b', 'c'].map(c => c.charCodeAt(0)) //=> [97, 98, 99]
```
But since a String only holds characters, we can't make it properly
hold the results of `c => c.charCodeAt(0)`:


```js
'abc'.map(c => c.charCodeAt(0)) //=> "979899"
```

`reduce` would be a bit different, as it can accumulate to any type.

I think `map` would be a bad idea here.


  -- Scott
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

kdex
In reply to this post by T.J. Crowder-2
Yeah; I am aware that ES2015 added measures that make it possible iterate over
codepoints, but that was not quite my point. The problem that I see is that in
some scenarios it makes sense to think of a string as an array of bytes, and
sometimes you need to iterate over a string in terms of its codepoints. Some
might even want to iterate in terms of visible glyphs, taking combining marks
into account.

This ambiguity makes `String.prototype.map` moot, as it remains questionable
what exactly should be iterated. Bytes? Codepoints? Entire glyphs?

On Thursday, May 17, 2018 5:41:32 PM CEST you wrote:
> Yeah; I am aware that ES2015 added measures that make it possible iterate
> over codepoints, but that was not quite my point. The problem that I see is
> that in some scenarios it makes sense to think of a string as an array of
> bytes, and sometimes you need to iterate over a string in terms of its
> codepoints. Some might even want to iterate in terms of visible glyphs,
> taking combining marks into account.
>
> This ambiguity makes `String.prototype.map` moot, as it remains questionable
> what exactly should be iterated. Bytes? Codepoints? Entire glyphs?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

Jordan Harband
What's the use case where you'd want to map over every (character / code point / grapheme / whatever) in a string, and apply the same callback logic to each one?

On Thu, May 17, 2018 at 9:21 AM, kdex <[hidden email]> wrote:
Yeah; I am aware that ES2015 added measures that make it possible iterate over
codepoints, but that was not quite my point. The problem that I see is that in
some scenarios it makes sense to think of a string as an array of bytes, and
sometimes you need to iterate over a string in terms of its codepoints. Some
might even want to iterate in terms of visible glyphs, taking combining marks
into account.

This ambiguity makes `String.prototype.map` moot, as it remains questionable
what exactly should be iterated. Bytes? Codepoints? Entire glyphs?

On Thursday, May 17, 2018 5:41:32 PM CEST you wrote:
> Yeah; I am aware that ES2015 added measures that make it possible iterate
> over codepoints, but that was not quite my point. The problem that I see is
> that in some scenarios it makes sense to think of a string as an array of
> bytes, and sometimes you need to iterate over a string in terms of its
> codepoints. Some might even want to iterate in terms of visible glyphs,
> taking combining marks into account.
>
> This ambiguity makes `String.prototype.map` moot, as it remains questionable
> what exactly should be iterated. Bytes? Codepoints? Entire glyphs?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

Braden Anderson
We do this on our front end where we replace certain emojis with our custom brand icons.

I don’t support this suggestion, though.

On Thu, May 17, 2018 at 10:12 AM Jordan Harband <[hidden email]> wrote:
What's the use case where you'd want to map over every (character / code point / grapheme / whatever) in a string, and apply the same callback logic to each one?

On Thu, May 17, 2018 at 9:21 AM, kdex <[hidden email]> wrote:
Yeah; I am aware that ES2015 added measures that make it possible iterate over
codepoints, but that was not quite my point. The problem that I see is that in
some scenarios it makes sense to think of a string as an array of bytes, and
sometimes you need to iterate over a string in terms of its codepoints. Some
might even want to iterate in terms of visible glyphs, taking combining marks
into account.

This ambiguity makes `String.prototype.map` moot, as it remains questionable
what exactly should be iterated. Bytes? Codepoints? Entire glyphs?

On Thursday, May 17, 2018 5:41:32 PM CEST you wrote:
> Yeah; I am aware that ES2015 added measures that make it possible iterate
> over codepoints, but that was not quite my point. The problem that I see is
> that in some scenarios it makes sense to think of a string as an array of
> bytes, and sometimes you need to iterate over a string in terms of its
> codepoints. Some might even want to iterate in terms of visible glyphs,
> taking combining marks into account.
>
> This ambiguity makes `String.prototype.map` moot, as it remains questionable
> what exactly should be iterated. Bytes? Codepoints? Entire glyphs?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

Andrea Giammarchi-2
In reply to this post by Jordan Harband
I agree map is not really a good fit for strings but this looks like yet another use case for `::` operator

```js
const map = [].map;

str::map(codeUnits);
[...str]::map(codePoints);
```

Why didn't that proposal made it again? It would make *every* request to add prototypal methods redundant!

Regards


On Thu, May 17, 2018 at 7:12 PM, Jordan Harband <[hidden email]> wrote:
What's the use case where you'd want to map over every (character / code point / grapheme / whatever) in a string, and apply the same callback logic to each one?

On Thu, May 17, 2018 at 9:21 AM, kdex <[hidden email]> wrote:
Yeah; I am aware that ES2015 added measures that make it possible iterate over
codepoints, but that was not quite my point. The problem that I see is that in
some scenarios it makes sense to think of a string as an array of bytes, and
sometimes you need to iterate over a string in terms of its codepoints. Some
might even want to iterate in terms of visible glyphs, taking combining marks
into account.

This ambiguity makes `String.prototype.map` moot, as it remains questionable
what exactly should be iterated. Bytes? Codepoints? Entire glyphs?

On Thursday, May 17, 2018 5:41:32 PM CEST you wrote:
> Yeah; I am aware that ES2015 added measures that make it possible iterate
> over codepoints, but that was not quite my point. The problem that I see is
> that in some scenarios it makes sense to think of a string as an array of
> bytes, and sometimes you need to iterate over a string in terms of its
> codepoints. Some might even want to iterate in terms of visible glyphs,
> taking combining marks into account.
>
> This ambiguity makes `String.prototype.map` moot, as it remains questionable
> what exactly should be iterated. Bytes? Codepoints? Entire glyphs?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

Jordan Harband
We do this on our front end where we replace certain emojis with our custom brand icons.

Seems like something `.replace` can already do for you?

On Thu, May 17, 2018 at 11:44 AM, Andrea Giammarchi <[hidden email]> wrote:
I agree map is not really a good fit for strings but this looks like yet another use case for `::` operator

```js
const map = [].map;

str::map(codeUnits);
[...str]::map(codePoints);
```

Why didn't that proposal made it again? It would make *every* request to add prototypal methods redundant!

Regards


On Thu, May 17, 2018 at 7:12 PM, Jordan Harband <[hidden email]> wrote:
What's the use case where you'd want to map over every (character / code point / grapheme / whatever) in a string, and apply the same callback logic to each one?

On Thu, May 17, 2018 at 9:21 AM, kdex <[hidden email]> wrote:
Yeah; I am aware that ES2015 added measures that make it possible iterate over
codepoints, but that was not quite my point. The problem that I see is that in
some scenarios it makes sense to think of a string as an array of bytes, and
sometimes you need to iterate over a string in terms of its codepoints. Some
might even want to iterate in terms of visible glyphs, taking combining marks
into account.

This ambiguity makes `String.prototype.map` moot, as it remains questionable
what exactly should be iterated. Bytes? Codepoints? Entire glyphs?

On Thursday, May 17, 2018 5:41:32 PM CEST you wrote:
> Yeah; I am aware that ES2015 added measures that make it possible iterate
> over codepoints, but that was not quite my point. The problem that I see is
> that in some scenarios it makes sense to think of a string as an array of
> bytes, and sometimes you need to iterate over a string in terms of its
> codepoints. Some might even want to iterate in terms of visible glyphs,
> taking combining marks into account.
>
> This ambiguity makes `String.prototype.map` moot, as it remains questionable
> what exactly should be iterated. Bytes? Codepoints? Entire glyphs?
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Adding .map() directly to String prototype

Isiah Meadows-2
And to my understanding, `.replace` can be better optimized for that
use case - it can limit graph copying when it builds the new string,
among other things.

If they actually need something like the `.map` as proposed here, they
could just as easily do `str.replace(/./gsu, m => ...)`, or if they're
stuck with non-transpiled ES2015, `str.replace(/[^]/gu, m => ...)`.
-----

Isiah Meadows
[hidden email]
www.isiahmeadows.com


On Thu, May 17, 2018 at 2:56 PM, Jordan Harband <[hidden email]> wrote:

>> We do this on our front end where we replace certain emojis with our
>> custom brand icons.
>
> Seems like something `.replace` can already do for you?
>
> On Thu, May 17, 2018 at 11:44 AM, Andrea Giammarchi
> <[hidden email]> wrote:
>>
>> I agree map is not really a good fit for strings but this looks like yet
>> another use case for `::` operator
>>
>> ```js
>> const map = [].map;
>>
>> str::map(codeUnits);
>> [...str]::map(codePoints);
>> ```
>>
>> Why didn't that proposal made it again? It would make *every* request to
>> add prototypal methods redundant!
>>
>> Regards
>>
>>
>> On Thu, May 17, 2018 at 7:12 PM, Jordan Harband <[hidden email]> wrote:
>>>
>>> What's the use case where you'd want to map over every (character / code
>>> point / grapheme / whatever) in a string, and apply the same callback logic
>>> to each one?
>>>
>>> On Thu, May 17, 2018 at 9:21 AM, kdex <[hidden email]> wrote:
>>>>
>>>> Yeah; I am aware that ES2015 added measures that make it possible
>>>> iterate over
>>>> codepoints, but that was not quite my point. The problem that I see is
>>>> that in
>>>> some scenarios it makes sense to think of a string as an array of bytes,
>>>> and
>>>> sometimes you need to iterate over a string in terms of its codepoints.
>>>> Some
>>>> might even want to iterate in terms of visible glyphs, taking combining
>>>> marks
>>>> into account.
>>>>
>>>> This ambiguity makes `String.prototype.map` moot, as it remains
>>>> questionable
>>>> what exactly should be iterated. Bytes? Codepoints? Entire glyphs?
>>>>
>>>> On Thursday, May 17, 2018 5:41:32 PM CEST you wrote:
>>>> > Yeah; I am aware that ES2015 added measures that make it possible
>>>> > iterate
>>>> > over codepoints, but that was not quite my point. The problem that I
>>>> > see is
>>>> > that in some scenarios it makes sense to think of a string as an array
>>>> > of
>>>> > bytes, and sometimes you need to iterate over a string in terms of its
>>>> > codepoints. Some might even want to iterate in terms of visible
>>>> > glyphs,
>>>> > taking combining marks into account.
>>>> >
>>>> > This ambiguity makes `String.prototype.map` moot, as it remains
>>>> > questionable
>>>> > what exactly should be iterated. Bytes? Codepoints? Entire glyphs?
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> [hidden email]
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>
>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> [hidden email]
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss