String.substitute

# Edwin Reynoso (9 years ago)

Could we make the following possible, I can't seem to think of a way to do it, since template literals are evaluated with the current scope, also tried with eval but shouldn't even use that at all:

String.substitute( { year: 2015 }, `This year is ${year}` ); // Returns
"This year is 2015"

Yes I'm aware I could do the following:

var obj = { year:2015 }

`This year is ${obj.year}`

The point is to get rid of the part where I reference obj all the time.

I could just use destructuring:

var { year } = { year: 2015 }

`This year is ${year}`

So yes destructuring takes care of most of this just fine, but the point is to have a template literal evaluate as a pass reference and not right away.

You can't make your own function and pass in a template literal that's not evaluated when passed as a reference, I'm not sure if anyone will actually want this but me. Please let me know.

# Claude Pache (9 years ago)

Le 12 août 2015 à 15:41, Edwin Reynoso <eorroe at gmail.com> a écrit :

Could we make the following possible, I can't seem to think of a way to do it, since template literals are evaluated with the current scope, also tried with eval but shouldn't even use that at all:

String.substitute( { year: 2015 }, `This year is ${year}` ); // Returns "This year is 2015"

Yes I'm aware I could do the following:

var obj = { year:2015 }

`This year is ${obj.year}`

The point is to get rid of the part where I reference obj all the time.

I could just use destructuring:

var { year } = { year: 2015 }

`This year is ${year}`

So yes destructuring takes care of most of this just fine, but the point is to have a template literal evaluate as a pass reference and not right away.

You can't make your own function and pass in a template literal that's not evaluated when passed as a reference, I'm not sure if anyone will actually want this but me. Please let me know. Thanks

There is a general trick for deferring evaluation (of a template literal or of anything else): enclosing it in a function.

const myTemplate = ({ year }) => `This year is ${year}`

myTemplate({ year: 2015 })
# Edwin Reynoso (9 years ago)

Yes of course, still requires 1.Destructuring, and making a function for each type of string to return. Defeats the purpose.

I'd have to make different functions for each template:

const yearTemplate = ({ year }) => `This year is ${year}`;

const ageTemplate = ({ age}) => `I'm ${age} yrs old`;

Compare to:

let yearSentence = String.substitute({ year: 2015}, `This year is ${year}`);
let ageSentence = String.substitute({ age:100 }, `I'm ${age} yrs old`);
# Nathaniel Higgins (9 years ago)

Am I being naive or could this just be written in user space?

Sent from my iPhone

# Elie Rotenberg (9 years ago)
function substitute(obj, str) {
  return str.replace(/\${([^}]*)}/g, (m, p) => obj[p]);
}

substitute({ year: 2015 }, 'This is year ${year}'); // === 'This is year
2015'
# Edwin Reynoso (9 years ago)

With String.substitute() you'd still be able to evaluate expressions, it's kind of like changing scope, or passing an object to use for scoped variables, which is not possible:

substitute({ year: 2015 }, 'Last year was year ${year-1}'); // Will throw
an error

You can't evaluate with your function

With String.substitute() you would be able to:

String.substitute({ year: 2015}, `Last year was ${year-1}`);

You also miss New Lines which is another thing template literals solved, so yes you could just add \n but that's the point of why template literals take care of that for you

# Logan Smyth (9 years ago)

Template literals evaluate to simple strings, there is no way to pass a reference to an un-evaluated template literal. The function method is the only way. Programmatically

String.substitute({ year: 2015}, `Last year was ${year-1}`);

is identical to

var str = `Last year was ${year-1}`
String.substitute({ year: 2015}, str);

How would it ever know that it was supposed to skip evaluating the template string first before calling the function?

# Tab Atkins Jr. (9 years ago)

On Wed, Aug 12, 2015 at 7:31 AM, Edwin Reynoso <eorroe at gmail.com> wrote:

Yes of course, still requires 1.Destructuring, and making a function for each type of string to return. Defeats the purpose.

I'd have to make different functions for each template:

const yearTemplate = ({ year }) => `This year is ${year}`;

const ageTemplate = ({ age}) => `I'm ${age} yrs old`;

Compare to:

let yearSentence = String.substitute({ year: 2015}, `This year is ${year}`);
let ageSentence = String.substitute({ age:100 }, `I'm ${age} yrs old`);

let yearSentence = ({year:2015}=>This year is ${year})();

should work, or

let yearSentence = (year=>This year is ${year})(2015);

You don't have to save the templates in variables. You can just call them immediately.

# Kevin Smith (9 years ago)

let yearSentence = ({year:2015}=>This year is ${year})();

Enclosing the template string inside of a function is the way to go. Let's call this one done.

# Edwin Reynoso (9 years ago)

@logan that's an interesting thought, which is why I posted this for discussion, Thinking of that, I'm kind of doubting most will like the function to only be able to take the literal instead as a variable because that's just messing with the way Javascript itself.

Could be possible to pass a string with "" instead of ``

String.substitute({year: 2015}, "This year is ${year}");

Which is giving javascript a way to allow writing a Template Literal without evaluating by using "" instead of ``

@Tab atkin

Your still making a function yourself. You may ask what's wrong with that?

Well then I'd say what's the point of ES6 having "Hi".includes("H") when we could of just did:

function includes(str, included) {
  return str.indexOf(included) > -1;
}
# Claude Pache (9 years ago)

Le 12 août 2015 à 15:41, Edwin Reynoso <eorroe at gmail.com> a écrit :

Could we make the following possible, I can't seem to think of a way to do it, since template literals are evaluated with the current scope, also tried with eval but shouldn't even use that at all:

String.substitute( { year: 2015 }, `This year is ${year}` ); // Returns "This year is 2015"

If you look closely, String.substitute is just the with statement resurrected:

with ({ year: 2015 }) { 
    `This year is ${year}` 
}

At first glance, the with statement looked like a great idea, but in fact, it makes static analysis difficult for both human and machines: In short: What do you expect from:

let shift = 1; 
String.substitute( obj, `This year is ${year + shift}` );

when you don’t know a priori whether obj has a year property, and whether it has a shift property?

# Logan Smyth (9 years ago)

Could be possible to pass a string with "" instead of ``

At that point, you are implementing a templating language that happens to match up syntactically with template literals. You'd also then be moving parsing of the template to runtime instead of compile time, which will slow things down. It would also only be possible to implement using eval.

You can certainly do that, but it doesn't seem like something that should be included in the language. It's no different from using Handlebars or Mustache at that point. The primary benefit of template literals is that they have access to variables in-scope, which seems to be what you are trying to avoid.

# Edwin Reynoso (9 years ago)

Yes I'm aware @claude that its kind of like the with statement

@Logan instead it would allow a way for a developer to parse the template on call.

What's wrong with that?

And also will allow me to not use Handlebars or Mustache

I don't see anything wrong with having a method to do this and this discussion led me to know that this could allow a way to interact with the parser on call, which IMO could be useful.

# Claude Pache (9 years ago)

Le 12 août 2015 à 17:35, Edwin Reynoso <eorroe at gmail.com> a écrit :

(...) and this discussion led me to know that this could allow a way to interact with the parser on call, which IMO could be useful.

JavaScript has already a built-in feature for interacting with the parser at runtime: It’s called eval. (And note that, since placeholders in template literals can contain arbitrary code, you do need the full power of eval.)