nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
107.23k stars 29.41k forks source link

[Feature request] Enable templated require #20184

Closed ghost closed 6 years ago

ghost commented 6 years ago

Hi. I really like node.js and the concept behind it, but one thing that I find very disturbing is that require function doesn't allow templated arguments.

For example, how about

const util = require`util`;

instead of

const util = require('util');

All native functions* allow templated call. Of course, it is not a syntax error to templately call even require, but unfortunately require doesn't recognize the string properly. It throws assertion error (path must be a string).

Templated call not only to save 2 extra characters of typing effort, but it also makes the code more readable and it would make require consistent with other native functions which allow such call. Also, since the only argument of require is a string, therefore it is the one reason more to implement such call.

Of course, it is very easy to make a polyfill for it in JavaScript, but why not implement it natively, since I don't see a hindrance for it.

Any opinions? Thanks.


*every function where it makes sense (for example if it accepts only one argument which can only be a string or a number)

vsemozhetbyt commented 6 years ago

If I understand this correctly, tagged template call makes the first argument to be an array, so require`util` equals require(['util']) and this does break the API.

Can you give examples of native functions which equally support common and tagged template calls with the same result?

devsnek commented 6 years ago

i see literally no reason to support this

Templated call not only to save 2 extra characters of typing effort, but it also makes the code more readable

two extra characters isn't very much and i find that require() is much more readable...

aside from that, this is just like a weird thing to ask for. require isn't a template function because it isn't a template function because it takes a single string input because thats what the design is i don't understand this

ghost commented 6 years ago

@vsemozhetbyt

Thank you for the response. As answer to your question:

Can you give examples of native functions which equally support common and tagged template calls with the same result?

all native function which takes only one argument and when that argument may be only an integer, double, or string, it allows template calls. If you want, I can make a list of more than 500 native functions defined in browsers (according to WHATWG standard) and also a lot (probably more than 500) native functions defined in node.js. Here are just a few examples, but the list is really huge:

document.getElementsByTagName`body`[0]
'abc'.charCodeAt`1`
[7, 8].join`<br/>`
'abc de fgh'.split` `
process.exit`5`
// and so on .......

@devsnek

I appreciate your opinion. However, I disagree that this syntax is rarely used in real code.

devsnek commented 6 years ago

@90s-hacker Buffer.from`57` and Buffer.from('57') don't do the same thing... but you expected them to. i suppose thats another reason why this isn't a very good pattern

ghost commented 6 years ago

@devsnek

Ok, bad example... I updated it.

devsnek commented 6 years ago

@nodejs/v8 anyone know why calling native functions with template literals is somehow transparent to our code?

edit: i wasn't thinking through array coercion, see below

vsemozhetbyt commented 6 years ago

It seems all your examples use implicit conversion from one-element-array to string (String(['a']) === 'a'). I think this is not intended for template call support, just a coincidence.

devsnek commented 6 years ago

@vsemozhetbyt i suppose that explains it, thank you for explaining the madness i am seeing here 👍

vsemozhetbyt commented 6 years ago

@90s-hacker If you use a real template string there, you will have different results as implicit conversion is not transparent anymore:

> [7, 8].join`ab`
'7ab8'
> [7, 8].join`a${''}b`
'7a,b8'
ghost commented 6 years ago

Well, this is only my idea, others may agree or disagree. As I said, implementing polyfill is trivial, but I thought that others may find the general idea usefull.

"This is not intended for template call support, just a coincidence." - I don't believe any of the ES spec definitions are concidence. They perfectly crafted it and defined the best possible behavior for converting singleton arrays to strings. Maybe they predicted such behavior in order to make this syntax possible and, probably, allow engines like gecko or v8 to optimize such calls without even creating array on the fly.

Anyway, this is only my opinion (and opinion of some people I work with), but let the community decide is it generally a good idea or not. If nobody support this request, I will close it, but, as I said, let the community decide.

devsnek commented 6 years ago

allow engines like gecko or v8 to optimize such calls without even creating array on the fly.

@hashseed i defer to you on this one

Maybe they predicted such behavior in order to make this syntax possible

@ljharb i defer to you on this one as i can't find any agenda items or notes about the original template literal spec

ljharb commented 6 years ago

Template literals predate my committee involvement, but @90s-hacker i can assure you that tagged template literals were only designed to be used with functions that were intentionally and explicitly designed for their use (like String.raw), although obviously you can leverage the nature of JS to force a square peg into a round hole.

I believe the intention was to use template literals as a way to create DSLs, and not at all to provide a (weird and unattractive) alternative function call syntax.

Trott commented 6 years ago

If anything, I'd like Node.js to discourage this kind of thing rather than encourage it. It has significant potential for unintended consequences (as seen in above examples that didn't work the way one might expect on casual inspection). Strong -1.

ghost commented 6 years ago

Ok, closing then. Thank you all for your opinions.