Re: Overload str.replace to take a Map?

2018-05-20 Thread Bob Myers
I'm not a huge fan of this idea, but just as a reference point, here is a
routine to convert a string to using smart quotes:

```js
// Change straight quotes to curly and double hyphens to em-dashes etc.
export function smarten(a: string) {
  if (!a) return a;

  a = a.replace(/(^|[-\u2014\s(\["])'/g, "$1\u2018"); // opening singles
  a = a.replace(/'/g, "\u2019"); // closing singles & apostrophes
  a = a.replace(/(^|[-\u2014/\[(\u2018\s])"/g, "$1\u201c"); // opening
doubles
  a = a.replace(/"/g, "\u201d"); // closing doubles
  a = a.replace(/\s*--\s*/g, "\u2014"); // em-dashes
  a = a.replace(/\.\.\./g, "\u2026"); // ellipsis
  a = a.replace(/ - /g, "\u2013"); // en-dashes
  a = a.replace(/\s+\?/g, "?"); // Remove Indian-style spaces before
question mark
  a = a.replace(/\s+\/\s+/, "/"); // Spaces around slashes.

  return a;
}
```

On Mon, May 21, 2018 at 10:19 AM Isiah Meadows 
wrote:

> I was using HTML primitive escaping as a concrete example, but there's
> others. Most use cases in my experience are essentially escaping for
> various reasons, but it's also useful for simple extensible templating
> where you control the expansion, but not the source. Here's a concrete
> example of what this could do:
>
> ```js
> // Old
> export function format(message, args, prettify = inspect) {
> return message.replace(/\{(.+?)\}/g, (m, prop) =>
> hasOwn.call(args, prop) ? prettify(args[prop], {depth: 5}) : m
> )
> }
>
> // New
> export function format(message, args, prettify = inspect) {
> return message.replace(Object.keys(args).reduce((acc, k) => ({
>   ...acc, [`{${k}}`]: prettify(args[k], {depth: 5})
> }), {})
> }
> ```
>
> (I presume you're aware that this does have some language precedent in
> Ruby's `String#gsub(regex, hash)`.)
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Proposal: Phase-Invariant Einno Soliton Templates

2018-05-20 Thread Abdul Shabazz
I am not an academic troll: i am actually underemployed at the monent; i
enjoy the labor very much, as well as the people i work with.
-- 
Abdul S.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Overload str.replace to take a Map?

2018-05-20 Thread Isiah Meadows
I was using HTML primitive escaping as a concrete example, but there's
others. Most use cases in my experience are essentially escaping for
various reasons, but it's also useful for simple extensible templating
where you control the expansion, but not the source. Here's a concrete
example of what this could do:

```js
// Old
export function format(message, args, prettify = inspect) {
return message.replace(/\{(.+?)\}/g, (m, prop) =>
hasOwn.call(args, prop) ? prettify(args[prop], {depth: 5}) : m
)
}

// New
export function format(message, args, prettify = inspect) {
return message.replace(Object.keys(args).reduce((acc, k) => ({
  ...acc, [`{${k}}`]: prettify(args[k], {depth: 5})
}), {})
}
```

(I presume you're aware that this does have some language precedent in
Ruby's `String#gsub(regex, hash)`.)


-

Isiah Meadows
m...@isiahmeadows.com
www.isiahmeadows.com

On Sun, May 20, 2018 at 11:57 PM, Jordan Harband  wrote:

> Something that escapes HTML wouldn't belong in the language, it would
> belong in browsers (the HTML spec, probably). This list is for
> language-level proposals, so I don't think this is the right list to
> suggest it.
>
> Are there use cases for things in this thread that aren't browser-specific?
>
> On Sun, May 20, 2018 at 8:49 PM, Isiah Meadows 
> wrote:
>
>> Next challenge: how does it compare to these two?
>>
>> ```js
>> // Simplified version
>> function simpleEscape(text) {
>>   return text.replace(/<(?:\/?script)?||>||/gu, m => {
>> switch (m) {
>> case '<': return '[lt]',
>> case '': return '[lt]',
>> case '>': return '[gt]',
>> case '': return '[gt]',
>> case '> case '> default: return ''
>> }
>>   });
>> }
>>
>> // Direct proposal equivalent
>> var replacements = {
>>   '<': '[lt]',
>>   '': '[lt]',
>>   '>': '[gt]',
>>   '': '[gt]',
>>   '>   '>   '': ''
>> }
>> function objectEscape(text) {
>>   return text.replace(/<(?:\/?script)?|&[lg]t;|>|/gu, m =>
>> replacements[m]);
>> }
>> ```
>>
>> Oh, and with my proposal, your glue code could be simplified to this:
>>
>> ```js
>> var text = 

Re: Overload str.replace to take a Map?

2018-05-20 Thread Jordan Harband
Something that escapes HTML wouldn't belong in the language, it would
belong in browsers (the HTML spec, probably). This list is for
language-level proposals, so I don't think this is the right list to
suggest it.

Are there use cases for things in this thread that aren't browser-specific?

On Sun, May 20, 2018 at 8:49 PM, Isiah Meadows 
wrote:

> Next challenge: how does it compare to these two?
>
> ```js
> // Simplified version
> function simpleEscape(text) {
>   return text.replace(/<(?:\/?script)?||>||/gu, m => {
> switch (m) {
> case '<': return '[lt]',
> case '': return '[lt]',
> case '>': return '[gt]',
> case '': return '[gt]',
> case ' case ' default: return ''
> }
>   });
> }
>
> // Direct proposal equivalent
> var replacements = {
>   '<': '[lt]',
>   '': '[lt]',
>   '>': '[gt]',
>   '': '[gt]',
>   '   '   '': ''
> }
> function objectEscape(text) {
>   return text.replace(/<(?:\/?script)?|&[lg]t;|>|/gu, m =>
> replacements[m]);
> }
> ```
>
> Oh, and with my proposal, your glue code could be simplified to this:
>
> ```js
> var text = 

Re: Overload str.replace to take a Map?

2018-05-20 Thread Isiah Meadows
Next challenge: how does it compare to these two?

```js
// Simplified version
function simpleEscape(text) {
  return text.replace(/<(?:\/?script)?||>||/gu, m => {
switch (m) {
case '<': return '[lt]',
case '': return '[lt]',
case '>': return '[gt]',
case '': return '[gt]',
case ' replacements[m]);
}
```

Oh, and with my proposal, your glue code could be simplified to this:

```js
var text = 

Re: Proposal: Phase-Invariant Einno Soliton Templates

2018-05-20 Thread Michael Luder-Rosefield
I've been suspecting along similar lines, but was reticent to make any
outright accusations.

On Mon, 21 May 2018, 00:41 Sanford Whiteman, <
swhitemanlistens-softw...@figureone.com> wrote:

> > I personally would prefer that these proposals are specified in terms
> > of *what's actually being proposed*
>
> I think what's actually being proposed is that we fall for a troll.
>
> Possibly an academic troll who will later ridicule its victims, viz.
> the Social Text scandal (https://en.wikipedia.org/wiki/Sokal_affair).
>
> A pity, since I love receiving this list to graze over your and
> others' intelligent and serious comments on the future of the
> language.
>
> —— Sandy
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Phase-Invariant Einno Soliton Templates

2018-05-20 Thread Sanford Whiteman
> I personally would prefer that these proposals are specified in terms
> of *what's actually being proposed*

I think what's actually being proposed is that we fall for a troll.

Possibly an academic troll who will later ridicule its victims, viz.
the Social Text scandal (https://en.wikipedia.org/wiki/Sokal_affair).

A pity, since I love receiving this list to graze over your and
others' intelligent and serious comments on the future of the
language.

—— Sandy

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: Phase-Invariant Einno Soliton Templates

2018-05-20 Thread Isiah Meadows
I personally would prefer that these proposals are specified in terms
of *what's actually being proposed*, rather than in terms of some very
elaborate analogy. Symbolic analogies to other tangentially related
fields work for teaching existing concepts to intuitive people, but
not for drafting and explaining a proposal to a technical audience who
already likely at least grasps some of the concepts (and when they
don't, they could easily Google it for most things).

And this is also why I've started ignoring these emails. My knee-jerk
reaction is to just filter them to the trash, because they're
explained too abstractly and intuitively to really describe what's
going on, what's really being proposed. I can get them *somewhat*,
after spending 15 minutes disecting what is being said, and that's
just not an effective use of time.

-

Isiah Meadows
m...@isiahmeadows.com
www.isiahmeadows.com


On Sun, May 20, 2018 at 11:34 AM, Michael Luder-Rosefield
 wrote:
> At this point I fully expect Abdul to describe the Norse, Greek and Hindu
> pantheons in terms of turbulence physics and give a few pseudocode JS
> snippets indicating that they can also be used to handle REST requests.  And
> all in 3 short sentences.
>
> On Sun, 20 May 2018 at 02:49 kdex  wrote:
>>
>> To me, what you're actually seeking to discuss looks less related to
>> physics
>> and more like an extension to ECMAScript's `import` syntax.
>>
>> Would you please describe it a little more? A good conversation starter,
>> preferably without any domain-specific context (i.e. physics), would
>> entail:
>>
>> - the set of generalized (= non-domain-specific) problems it solves
>> - the desugaring you have in mind
>> - how a solution to your problem might look without introducing new syntax
>> (ideally also the reasoning why you consider new syntax to be justified)
>>
>> On Sunday, May 20, 2018 3:12:34 AM CEST Abdul Shabazz wrote:
>> > Of the five (5) known forms of matter:
>> >
>> >
>> >
>> >1. Solid (well-structured arrangement of tightly bound atoms, found
>> > in
>> >ice)
>> >2. Liquid (unstructured arrangement of tightly-bound atoms)
>> >3. Gas (loose arrangement of atoms)
>> >4. Plasma (Properties of liquid, electricity, and magnetism found @
>> > the
>> >core of our sun)
>> >5. Bose-Einstein condensates (Properties of gas and phase-invariant
>> >liquid, ie. a superfluid)
>> >
>> >
>> > ...Another sixth (6th) form of matter was uncovered six weeks ago at UT
>> > Dallas: the "Superfluid Quasicrystal" -- which has the properties of
>> > both
>> > quasicrystals and superfluids, wherein Quasi crystals have atoms that
>> > are
>> > arranged in a highly ordered, periodic pattern that is unchanged when
>> > you
>> > rotate or repeat it, eg. in table salts)
>> >
>> >
>> > This sixth (6th) form of matter exhibits properties of a Soliton: A
>> > Soliton
>> > or Einno Soliton Tsunami is a gathering phase-invariant wave that
>> > maintains
>> > its shape and velocity as it travels through any phase of matter.
>> >
>> >
>> > An example implementation perhaps in javascript would be:
>> >
>> >
>> > // file1.jsol
>> >
>> >
>> > ${0} = (lhs,rhs) => { return (lhs ${1} rhs) }
>> >
>> >
>> > // file2.js
>> >
>> >
>> > import file1.["add",Symbol.operator.addition] as bar
>> >
>> > let foo = bar.add(4,2) // returns 6
>> >
>> >
>> > // file3.js
>> >
>> >
>> > import file1.["mul",Symbol.operator.multiplication] as bar
>> >
>> > let foo = bar.mul(4,2) // returns
>> > 8___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Overload str.replace to take a Map?

2018-05-20 Thread kai zhu
hi mathias, i see...  here's some simple, throwaway glue-code that does what i 
think you want.

```js
/*jslint
node: true
*/
'use strict';
var text;
text = 

Re: Overload str.replace to take a Map?

2018-05-20 Thread Mathias Bynens
This particular `escapeHtml` implementation is limited to replacing single
characters, but if you wanted to escape any characters that can be
represented using a named character reference, you’re gonna need something
more generic, as some named character references expand to multiple
characters. That‘s what I was referring to earlier.

On Sun, May 20, 2018 at 12:27 PM, kai zhu  wrote:

> sorry, there was a bug in the standalone-solution i last posted. here’s
> corrected version ^^;;;
>
> also highlighted in blue, the escapeHTML part of code relevant to this
> discussion.  and honestly, replacing those 6 blue-lines-of-code in this
> real-world example, with the proposed map-replace doesn’t make much of a
> difference in terms of overall readability/maintainability.
>
> ```js
> /*
>  * example.js
>  *
>  * this zero-dependency, standalone program will render mustache-based
> html-templates,
>  * with the given dictionary, and print it to stdout
>  * code derived from https://github.com/kaizhu256/
> node-utility2/blob/2018.1.13/lib.utility2.js#L5922
>
>
>
>  * example usage:
> $ node example.js  
> $ node example.js '
> JSON.stringify("hello world!".toUpperCase()))=
> {{hello.world toUpperCase jsonStringify}}
> 
>
> 
> {{#each myList}}
> {{#if href}}
> 
> 
> {{#if description}}
> {{description notHtmlSafe}}
> {{#unless description}}
> no description
> {{/if description}}
> 
> 
> {{/if href}}
> {{/each myList}}
> ' '{
> "hello": {
> "world": "hello world!"
> },
> "myList": [
> null,
> {
> "href": "https://www.example.com/1;,
> "description": "click here!"
> },
> {
> "href": "https://www.example.com/2;
> }
> ]
> }'
>
>
>
>  * example output:
> 
> JSON.stringify("hello world!".toUpperCase()))=
> BHELLO WORLD!/B
> 
>
> 
>
> 
> https://www.example.com/1;>
>
> click here!
>
> 
> 
>
> 
> https://www.example.com/2;>
>
> no description
>
> 
> 
>
> 
>  */
>
>
>
>
>
>
>
> /*jslint
> node: true,
> regexp: true
> */
> 'use strict';
> var templateRender;
> templateRender = function (template, dict, options) {
> /*
>  * this function will render the template with the given dict
>  */
> var argList, getValue, match, renderPartial, rgx, tryCatch, skip,
> value;
> dict = dict || {};
> options = options || {};
> getValue = function (key) {
> argList = key.split(' ');
> value = dict;
> if (argList[0] === '#this/') {
> return;
> }
> // iteratively lookup nested values in the dict
> argList[0].split('.').forEach(function (key) {
> value = value && value[key];
> });
> return value;
> };
> renderPartial = function (match0, helper, key, partial) {
> switch (helper) {
> case 'each':
> case 'eachTrimRightComma':
> value = getValue(key);
> value = Array.isArray(value)
> ? value.map(function (dict) {
> // recurse with partial
> return templateRender(partial, dict, options);
> }).join('')
> : '';
> // remove trailing-comma from last element
> if (helper === 'eachTrimRightComma') {
> value = value.trimRight().replace((/,$/), '');
> }
> return value;
> case 'if':
> partial = partial.split('{{#unless ' + key + '}}');
> partial = getValue(key)
> ? partial[0]
> // handle 'unless' case
> : partial.slice(1).join('{{#unless ' + key + '}}');
> // recurse with partial
> return templateRender(partial, dict, options);
> case 'unless':
> return getValue(key)
> ? ''
> // recurse with partial
> : templateRender(partial, dict, options);
> default:
> // recurse with partial
> return match0[0] + templateRender(match0.slice(1), dict,
> options);
> }
> };
> tryCatch = function (fnc, message) {
> /*
>  * this function will prepend the message to errorCaught
>  */
> try {
> return fnc();
> } catch (errorCaught) {
> errorCaught.message = message + errorCaught.message;
> throw errorCaught;
> }
> };
> // render partials
> rgx = (/\{\{#(\w+) ([^}]+?)\}\}/g);
> template = template || '';
> for (match = rgx.exec(template); match; match = rgx.exec(template)) {
> rgx.lastIndex += 1 - match[0].length;
> template = template.replace(
> new RegExp('\\{\\{#(' + match[1] + ') (' + match[2] +
> ')\\}\\}([\\S\\s]*?)\\{\\{/' + match[1] + ' ' + match[2] +
> '\\}\\}'),
> renderPartial
> );
> }
> // 

Re: Overload str.replace to take a Map?

2018-05-20 Thread kai zhu
sorry, there was a bug in the standalone-solution i last posted. here’s 
corrected version ^^;;;

also highlighted in blue, the escapeHTML part of code relevant to this 
discussion.  and honestly, replacing those 6 blue-lines-of-code in this 
real-world example, with the proposed map-replace doesn’t make much of a 
difference in terms of overall readability/maintainability.

```js
/*
 * example.js
 *
 * this zero-dependency, standalone program will render mustache-based 
html-templates,
 * with the given dictionary, and print it to stdout
 * code derived from 
https://github.com/kaizhu256/node-utility2/blob/2018.1.13/lib.utility2.js#L5922



 * example usage:
$ node example.js  
$ node example.js '
JSON.stringify("hello world!".toUpperCase()))=
{{hello.world toUpperCase jsonStringify}}



{{#each myList}}
{{#if href}}


{{#if description}}
{{description notHtmlSafe}}
{{#unless description}}
no description
{{/if description}}


{{/if href}}
{{/each myList}}
' '{
"hello": {
"world": "hello world!"
},
"myList": [
null,
{
"href": "https://www.example.com/1;,
"description": "click here!"
},
{
"href": "https://www.example.com/2;
}
]
}'



 * example output:

JSON.stringify("hello world!".toUpperCase()))=
BHELLO WORLD!/B





https://www.example.com/1;>

click here!





https://www.example.com/2;>

no description





 */







/*jslint
node: true,
regexp: true
*/
'use strict';
var templateRender;
templateRender = function (template, dict, options) {
/*
 * this function will render the template with the given dict
 */
var argList, getValue, match, renderPartial, rgx, tryCatch, skip, value;
dict = dict || {};
options = options || {};
getValue = function (key) {
argList = key.split(' ');
value = dict;
if (argList[0] === '#this/') {
return;
}
// iteratively lookup nested values in the dict
argList[0].split('.').forEach(function (key) {
value = value && value[key];
});
return value;
};
renderPartial = function (match0, helper, key, partial) {
switch (helper) {
case 'each':
case 'eachTrimRightComma':
value = getValue(key);
value = Array.isArray(value)
? value.map(function (dict) {
// recurse with partial
return templateRender(partial, dict, options);
}).join('')
: '';
// remove trailing-comma from last element
if (helper === 'eachTrimRightComma') {
value = value.trimRight().replace((/,$/), '');
}
return value;
case 'if':
partial = partial.split('{{#unless ' + key + '}}');
partial = getValue(key)
? partial[0]
// handle 'unless' case
: partial.slice(1).join('{{#unless ' + key + '}}');
// recurse with partial
return templateRender(partial, dict, options);
case 'unless':
return getValue(key)
? ''
// recurse with partial
: templateRender(partial, dict, options);
default:
// recurse with partial
return match0[0] + templateRender(match0.slice(1), dict, options);
}
};
tryCatch = function (fnc, message) {
/*
 * this function will prepend the message to errorCaught
 */
try {
return fnc();
} catch (errorCaught) {
errorCaught.message = message + errorCaught.message;
throw errorCaught;
}
};
// render partials
rgx = (/\{\{#(\w+) ([^}]+?)\}\}/g);
template = template || '';
for (match = rgx.exec(template); match; match = rgx.exec(template)) {
rgx.lastIndex += 1 - match[0].length;
template = template.replace(
new RegExp('\\{\\{#(' + match[1] + ') (' + match[2] +
')\\}\\}([\\S\\s]*?)\\{\\{/' + match[1] + ' ' + match[2] +
'\\}\\}'),
renderPartial
);
}
// search for keys in the template
return template.replace((/\{\{[^}]+?\}\}/g), function (match0) {
var notHtmlSafe;
notHtmlSafe = options.notHtmlSafe;
return tryCatch(function () {
getValue(match0.slice(2, -2));
if (value === undefined) {
return match0;
}
argList.slice(1).forEach(function (arg0, ii, list) {
switch (arg0) {
case 'alphanumeric':
value = value.replace((/\W/g), '_');
break;
case 'decodeURIComponent':
value = decodeURIComponent(value);
break;
case 'encodeURIComponent':
   

Re: Proposal: Phase-Invariant Einno Soliton Templates

2018-05-20 Thread Michael Luder-Rosefield
At this point I fully expect Abdul to describe the Norse, Greek and Hindu
pantheons in terms of turbulence physics and give a few pseudocode JS
snippets indicating that they can also be used to handle REST requests.
And all in 3 short sentences.

On Sun, 20 May 2018 at 02:49 kdex  wrote:

> To me, what you're actually seeking to discuss looks less related to
> physics
> and more like an extension to ECMAScript's `import` syntax.
>
> Would you please describe it a little more? A good conversation starter,
> preferably without any domain-specific context (i.e. physics), would
> entail:
>
> - the set of generalized (= non-domain-specific) problems it solves
> - the desugaring you have in mind
> - how a solution to your problem might look without introducing new syntax
> (ideally also the reasoning why you consider new syntax to be justified)
>
> On Sunday, May 20, 2018 3:12:34 AM CEST Abdul Shabazz wrote:
> > Of the five (5) known forms of matter:
> >
> >
> >
> >1. Solid (well-structured arrangement of tightly bound atoms, found in
> >ice)
> >2. Liquid (unstructured arrangement of tightly-bound atoms)
> >3. Gas (loose arrangement of atoms)
> >4. Plasma (Properties of liquid, electricity, and magnetism found @
> the
> >core of our sun)
> >5. Bose-Einstein condensates (Properties of gas and phase-invariant
> >liquid, ie. a superfluid)
> >
> >
> > ...Another sixth (6th) form of matter was uncovered six weeks ago at UT
> > Dallas: the "Superfluid Quasicrystal" -- which has the properties of both
> > quasicrystals and superfluids, wherein Quasi crystals have atoms that are
> > arranged in a highly ordered, periodic pattern that is unchanged when you
> > rotate or repeat it, eg. in table salts)
> >
> >
> > This sixth (6th) form of matter exhibits properties of a Soliton: A
> Soliton
> > or Einno Soliton Tsunami is a gathering phase-invariant wave that
> maintains
> > its shape and velocity as it travels through any phase of matter.
> >
> >
> > An example implementation perhaps in javascript would be:
> >
> >
> > // file1.jsol
> >
> >
> > ${0} = (lhs,rhs) => { return (lhs ${1} rhs) }
> >
> >
> > // file2.js
> >
> >
> > import file1.["add",Symbol.operator.addition] as bar
> >
> > let foo = bar.add(4,2) // returns 6
> >
> >
> > // file3.js
> >
> >
> > import file1.["mul",Symbol.operator.multiplication] as bar
> >
> > let foo = bar.mul(4,2) // returns
> 8___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: "Stupid" JSON Number Serialization Question

2018-05-20 Thread Richard Gibson
That seems like a question best addressed by something like JSON Schema.
ECMAScript is not unique in lacking sufficient native machinery to process
JSON numbers that have no IEEE 754 64-bit representation, and similar
issues exist for binary data and complex types like date/time values.

On Sunday, May 20, 2018, Anders Rundgren 
wrote:
>
> My question was really how non-ES systems preferable should "talk numbers"
> to ES when using JSON:
> https://mail.mozilla.org/pipermail/es-discuss/2018-May/050889.html
>
> Anders
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Overload str.replace to take a Map?

2018-05-20 Thread Isiah Meadows
@Mathias

My partcular `escapeHTML` example *could* be written like that (and it *is*
somewhat in the prose). But you're right that in the prose, I did bring up
the potential for things like `str.replace({cheese: "cake", ham: "eggs"})`.

@Kai

Have you ever tried writing an HTML template system on the front end? This
*will* almost inevitably come up, and most of my use cases for this is on
the front end itself handling various scenarios.

@Cyril

And every single one of those patterns is going to need compiled and
executed, and compiling and interpreting regular expressions is definitely
not quick, especially when you can nest Kleene stars. (See:
https://en.wikipedia.org/wiki/Regular_expression#Implementations_and_running_times)
That's why I'm against it - we don't need to complicate this proposal with
that mess.

-

Isiah Meadows
m...@isiahmeadows.com
www.isiahmeadows.com

On Sat, May 19, 2018 at 7:04 PM, Mathias Bynens  wrote:

> Hey Kai, you’re oversimplifying. Your solution works for a single Unicode
> symbol (corresponding to a single code point) but falls apart as soon as
> you need to match multiple symbols of possibly varying length, like in the
> `escapeHtml` example.
>
> On Sat, May 19, 2018 at 8:43 AM, kai zhu  wrote:
>
>> again, you backend-engineers are making something more complicated than
>> needs be, when simple, throwaway glue-code will suffice.  agree with
>> jordan, this feature is a needless cross-cut of String.prototype.replace.
>>
>> ```
>> /*jslint
>> node: true
>> */
>> 'use strict';
>> var dict;
>> dict = {
>> '$': '^',
>> '1': '2',
>> '<': '',
>> '': '',
>> '-': '_',
>> ']': '@'
>> };
>> // output: "test_^^[22@ foo>"
>> console.log('test-$$[11] '.replace((/[\S\s]/gu), function
>> (character) {
>> return dict.hasOwnProperty(character)
>> ? dict[character]
>> : character;
>> }));
>> ```
>>
>> kai zhu
>> kaizhu...@gmail.com
>>
>>
>>
>> On 19 May 2018, at 4:08 PM, Cyril Auburtin 
>> wrote:
>>
>> You can also have a
>>
>> ```js
>> var replacer = replacements => {
>>   const re = new RegExp(replacements.map(([k,_,escaped=k]) =>
>> escaped).join('|'), 'gu');
>>   const replaceMap = new Map(replacements);
>>   return s => s.replace(re, w => replaceMap.get(w));
>> }
>> var replace = replacer([['$', '^', String.raw`\$`], ['1', '2'], ['<',
>> ''], ['', ''], ['-', '_'], [']', '@', String.raw`\]`]]);
>> replace('test-$$[11] ') // "test_^^[22@ foo>"
>> ```
>> but it's quickly messy to work with escaping
>>
>> Le sam. 19 mai 2018 à 08:17, Isiah Meadows  a
>> écrit :
>>
>>> Here's what I'd prefer instead: overload `String.prototype.replace` to
>>> take non-callable objects, as sugar for this:
>>>
>>> ```js
>>> const old = Function.call.bind(Function.call, String.prototype.replace)
>>> String.prototype.replace = function (regexp, object) {
>>> if (object == null && regexp != null && typeof regexp === "object") {
>>> const re = new RegExp(
>>> Object.keys(regexp)
>>> .map(key => `${old(key, /[\\^$*+?.()|[\]{}]/g, '\\$&')}`)
>>> .join("|")
>>> )
>>> return old(this, re, m => object[m])
>>> } else {
>>> return old(this, regexp, object)
>>> }
>>> }
>>> ```
>>>
>>> This would cover about 99% of my use for something like this, with
>>> less runtime overhead (that of not needing to check for and
>>> potentially match multiple regular expressions at runtime) and better
>>> static analyzability (you only need to check it's an object literal or
>>> constant frozen object, not that it's argument is the result of the
>>> built-in `Map` call). It's exceptionally difficult to optimize for
>>> this unless you know everything's a string, but most cases where I had
>>> to pass a callback that wasn't super complex looked a lot like this:
>>>
>>> ```js
>>> // What I use:
>>> function escapeHTML(str) {
>>> return str.replace(/["'&<>]/g, m => {
>>> switch (m) {
>>> case '"': return ""
>>> case "'": return ""
>>> case "&": return ""
>>> case "<": return ""
>>> case ">": return ""
>>> default: throw new TypeError("unreachable")
>>> }
>>> })
>>> }
>>>
>>> // What it could be
>>> function escapeHTML(str) {
>>> return str.replace({
>>> '"': "",
>>> "'": "",
>>> "&": "",
>>> "<": "",
>>> ">": "",
>>> })
>>> }
>>> ```
>>>
>>> And yes, this enables optimizations engines couldn't easily produce
>>> otherwise. In this instance, an engine could find that the object is
>>> static with only single-character entries, and it could replace the
>>> call to a fast-path one that relies on a cheap lookup table instead
>>> (Unicode replacement would be similar, except you'd need an extra
>>> layer of indirection with astrals to avoid blowing up memory when
>>> generating these tables):
>>>