Function constants for Identity and No-op
Eli Perelman
eli at eliperelman.com
Wed Aug 10 14:25:55 UTC 2016
I can understand the sentiment of wanting brevity and avoiding unnecessary
abstraction, but in some cases I think it comes at the cost of readability
or good practice. This is why variables exist at all: to store commonly
used values either for reuse or to cut down on unnecessary allocation.
Sure, I could write code to ensure my numbers did go over a certain limit
with `Math.min(userInput, 9007199254740991)`, but readability and
abstraction give me something without having to keep this knowledge
internally and create my own allocation, e.g. `Math.min(userInput,
Math.MAX_SAFE_INTEGER`.
Now obviously it would be trivial for me to declare these constants in
userland code like I already do, e.g. `const NOOP = () => {}`, but in
projects where it's needed in several files, I'll have to put that in a
module or re-declare everywhere. This is not a huge inconvenience but
something that could easily allocated for in the language.
> The semantics of the named forms can be guessed rather well from the
names, but one cannot be sure without looking up or remembering their
definitions.
This is true of anything; you know what you know, and are unsure of what
you are unsure of. Those that understand what a no-ops and identity
functions are will not need to look it up, and those that do not will look
it up until they know it. Just like my personal enemies `Array#shift` and
`Array#unshift`, I have to look those up every single time, and just
because I can't remember which is which or their individual case doesn't
mean they don't have value or that I resort to other tricks to avoid their
usage. All that to say, I don't think lack of knowledge is a valid argument
for these constants' non-inclusion. :)
> Only pay these costs when the potential benefits are real.
I think my allusion to potential benefits is avoidance of re-declaration
(DRY) and allocation.
Just my thoughts. :)
Eli Perelman
On Wed, Aug 10, 2016 at 9:08 AM Mark S. Miller <erights at google.com> wrote:
> On Wed, Aug 10, 2016 at 2:10 AM, Isiah Meadows <isiahmeadows at gmail.com>
> wrote:
>
>> I'll note that it's longer than just typing them out manually (and close
>> if they're aliased):
>>
>> ```js
>> Function.IDENTITY
>> IDENTITY
>> x => x
>>
>> Function.NOOP
>> NOOP
>> () => {}
>> ```
>>
>> Not sure if it adds anything.
>>
>
> Even aside from brevity, `x => x` and `() => {}` are more readable than
> `Function.IDENTITY` and `Function.NOOP` for a very simple reason. The
> semantics of the shorter forms are obvious and clear, give knowledge only
> of the core language. The semantics of the named forms can be guessed
> rather well from the names, but one cannot be sure without looking up or
> remembering their definitions. As we all know, abstraction has tremendous
> potential benefits. But it also has these costs -- the need to learn the
> meaning of new definitions. Only pay these costs when the potential
> benefits are real.
>
> Also, other things being equal, a briefer form is easier to read. In this
> case, other things are not equal but both considerations point in the same
> direction.
>
>
>> On Tue, Aug 9, 2016, 14:44 Eli Perelman <eli at eliperelman.com> wrote:
>>
>>> I'm not sure if something like this has been proposed before, but I
>>> often find myself declaring constants for the identity function and the
>>> no-op function. I think it would be useful to have constants available on
>>> Function containing these values. For example `Function.IDENTITY` and
>>> `Function.NOOP`. Essentially these constants would map to:
>>>
>>> ```js
>>> Function.IDENTITY = (a) => a;
>>> Function.NOOP = () => null; // or:
>>> Function.NOOP = () => {};
>>> ```
>>>
>>> These could then be used in places where non-user-controlled APIs need
>>> default functions need to be executed, or as placeholders for default
>>> values that may be executed before a function has been supplied. For
>>> example:
>>>
>>> ```js
>>> // third-party API requires a callback or throws, but no functionality
>>> really needs to done:
>>> thirdParty.action(Function.NOOP);
>>>
>>> // Function needs a default which *may* execute prior to having a
>>> different one specified (contrived):
>>> const action = (handler = Function.IDENTITY, value = 10) =>
>>> handler(value);
>>> ```
>>>
>>> Thoughts? Seems like something simple with positive value. Thanks!
>>>
>>> Eli Perelman
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
>
> --
> Cheers,
> --MarkM
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20160810/49e1a99b/attachment-0001.html>
More information about the es-discuss
mailing list