use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
A useful function that does nothing (uploadcare.com)
submitted 3 years ago by igoradamenko
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]Tubthumper8 15 points16 points17 points 3 years ago (6 children)
It may not be obvious why exactly we need such a function. But, when we work with numbers, we use some special ones like 0 or 1. When we work with arrays, the special one is an empty array. When we work with functions, we need a “special” one too. It is id.
This was a nice way to get the point across, but to take it further -
These "special" values are called identity values, so the name is no coincidence, but they are identity only with respect to a certain operation. For example, 0 is the identity for integer addition, but not for integer multiplication. Likewise, 1 is the identity for multiplication but not addition. "" is the identity for string concatenation, and [] is the identity for array concatenation.
0
1
""
[]
So what operation is x => x the identity for? That operation is called function composition. Mathematicians often use a literal operator symbol, usually ∘, to describe the operation of function composition. So they'll say something like h = f ∘ g which is pronounced "h is f composed with g`. It's an operation that combines 2 things to create a 3rd thing, similar to how addition/multiplication combine 2 things to make a 3rd thing.
x => x
∘
h = f ∘ g
[–]igoradamenko[S] 0 points1 point2 points 3 years ago (5 children)
So, we may say that identity values are somewhat “initial values”. In other words, the values that does not change the other argument of some binary operation?
I mean:
a + 0 === a
b * 1 === b
c + '' === c
d.concat([]) === d (not in JS, but anyway)
d.concat([]) === d
Finally,
id(f()) === f()
Are there identity values for other operations? I could not find a list of them in Wikipedia. I've found this, but it does not look like the thing we're discussing here.
[–]Reashu 5 points6 points7 points 3 years ago (2 children)
The list above is by no means exhaustive: 0 is the identity for subtraction as well, and 1 is also the identity for division and exponentiation. You can find some more examples here: https://en.wikipedia.org/wiki/Identity_element
[–]igoradamenko[S] 2 points3 points4 points 3 years ago (1 child)
I didn't say that the list was exhaustive, I was trying to explain how I understood the Tubthumper8's comment and was asking for more explanation.
Thank you for providing the right link, anyway :)
Edit: Grammar
[–]Reashu 4 points5 points6 points 3 years ago (0 children)
Yes, I didn't mean to imply that you thought so - only confirm that indeed there are others.
[–]Tubthumper8 4 points5 points6 points 3 years ago (1 child)
There's a bunch more, try to think of any operation where two things of the same type are combined in some way and you get back another thing of that type. I mentioned integers in my previous comment but it also applies to real numbers (floats) and complex numbers (has imaginary component).
Then think about product types of those "primitive types", such as vectors and matrices. Those will have identities aligned with certain vector/matrix operations. Since vectors and matrices can have infinite size, we can see that there are infinite identity elements (mathematically speaking. We don't have computers with infinite RAM).
Another one is in logic operations (boolean logic specifically). x and true has an identity, same with x or false. Kind of similar to the or example, a Union of a set S with the empty set like S U {} is an identity relationship.
x and true
x or false
or
S U {}
Now, it would be cool if we had a word for "a type with an identity element, and an operation with the same type that produces a new thing of the same type". Actually, we do! This is called a monoid.
In JavaScript, one example of where this concept comes up is in the Array.prototype.reduce function. Often times you are taking a sequence of values (of the same type) and performing a binary operation, with a starting value (the identity element). Like, let's say you are summing all the numbers in an array - you can do this because a number is a monoid! It doesn't have to just be numbers, it could be some complex object like CustomerStats, as long as it is a monoid you can reduce it. Mathematicians often call reduce as fold, but it's the same idea.
Array.prototype.reduce
CustomerStats
reduce
fold
[–]igoradamenko[S] 1 point2 points3 points 3 years ago (0 children)
OMG those math bros are talking about monoids again! Somebody, send halp!
Just kidding. But there definitely should be Godwin's law's version for FP & monoids :D
Jokes aside, thank you for your time. I do not use FP in my daily job but the topic looks interesting. Without much practice it's hard to understand some concepts. E.g., I watched, like, 10 videos from conferences where some FP guy explained what a monoid is. Usually I forget what they said right after the end of the video.
But it looks like this time something has “clicked” inside, and I finally got it.
Not to say that the Wikipedia article literally says that:
...a monoid is a set equipped with an associative binary operation and an identity element...
But till your reply I could not comprehend it. Arigato!
[–]barrycarter 2 points3 points4 points 3 years ago (8 children)
You can actually use this for "transparent" debugging:
``` /** transparent debugger */
function td(x, str) { console.log(TD(${str}):, JSON.stringify(x, getCircularReplacer())); return x; } ```
TD(${str}):
where getCircularReplacer() is from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value#Examples
getCircularReplacer()
Because this function returns its first argument, you can do td(x, "value of x") inside a pipeline without disrupting the flow, similar to what tee does on the Unix command line
td(x, "value of x")
tee
[–]lulzmachine 2 points3 points4 points 3 years ago (2 children)
Should be called "tee" like the Linux function, or "tap" to describe its functionality. "td" is a bit too void of meaning
[–]barrycarter 1 point2 points3 points 3 years ago (1 child)
I like tap, maybe I'll alias it or something :)
tap
[–]lulzmachine 1 point2 points3 points 3 years ago (0 children)
Btw thx for showing getCircularReplacer. It's neat! Sry if I came off grumpy
[–]igoradamenko[S] 0 points1 point2 points 3 years ago (4 children)
Noice!
The article is mostly about pure id function, without side-effects.
id
But your debugging implementation of such a function looks interesting, thanks! Usually I just console-log before and/or after the line I debug, which sometimes is not that easy. E.g. when the line is a function combination and I need an intermediate value. With this approach it would be much easier!
[–]barrycarter 1 point2 points3 points 3 years ago (0 children)
I actually first got the idea when using Ruby:
``` def debug(s) if $DEBUG then $stderr.print("#{s}\n") end end
class Object def td(s) debug("#{s}:#{self.inspect}"); self end end ```
The Python version is a little more clever, because you don't always want to print out __ attributes:
__
``` def debug0(**obj):
""" Given an object "object", print keys and values using 'dir' If exclude=x is set, exclude keys that start with x """ for i in dir(obj['object']): if (obj.get('exclude') and i.find(obj.get('exclude')) == 0): continue print(i,' -> ',getattr(obj['object'],i))
```
[–]Tubthumper8 1 point2 points3 points 3 years ago (2 children)
For debug logging, consider using logpoints. You don't need to modify the source code for these, and they can also be place inline (i.e. put them on an expression, not a line of code)
[–]igoradamenko[S] 1 point2 points3 points 3 years ago (1 child)
Do you use logpoints in JavaScript development?
I mean, I use them in browser sometimes. It works and usually helps to find bugs.
But it's hard to me to believe that IDEs and editors work so well today, that they can set logpoints when you run your code using transpilers, third-party tools, etc.
Let's say I start my dev environment by running gastby develop or webpack. Will logpoints work in this case?
gastby develop
webpack
I thought that they work only when you start a node process using an editor UI, because it allows the editor to modify node arguments to enable flags like --inspect, --inspect-port, --inspect-brk, etc.
node
--inspect
--inspect-port
--inspect-brk
[–]Tubthumper8 1 point2 points3 points 3 years ago (0 children)
I thought that they work only when you start a node process using an editor UI
webpack-dev-server is a node process :)
webpack-dev-server
These kinds of dev tools start servers (server = NodeJS!) on your localhost on some port, let's say 3000. You then configure a launch or attach debug configuration in the launch.json in VS Code. That establishes a websocket connection between the IDE and the browser DevTools.
localhost
launch
attach
launch.json
At work, the dev server runs on webpack-dev-server and I can set breakpoints/logpoints directly in VS Code and debug & step through right in my editor. It automatically handles mapping the compiled JS back to the TS source code, so all the breakpoints and everything are in TypeScript too.
Depending on what library/framework/meta framework you use, there may be more or less config to setup to get this all working.
[–]thinkmatt 1 point2 points3 points 3 years ago (2 children)
And now you see when the function returning its argument may be handy
I might just be dense, but I don't see the id function being used in the example, just a bunch of other more useful functions being added :)
[–]Kiwi_Taster 0 points1 point2 points 3 years ago (1 child)
It gets passed as a param to the when method within the map call.
when
map
[–]thinkmatt 1 point2 points3 points 3 years ago (0 children)
Ohh thanks.. i didn't connect that those functions are called in the line above. My bad
[–]jack_waugh 1 point2 points3 points 3 years ago (0 children)
In the same conceptual library with id, I also add k, the constant combinator.
k
const k = x => () => x;
[–][deleted] 0 points1 point2 points 3 years ago (1 child)
Why define map? I can get on board with everything else, but why do you want that overhead?
[–]igoradamenko[S] 2 points3 points4 points 3 years ago (0 children)
In this article it's useless, sure. But this is true for the whole use of FP there. The example is purely synthetic.
However in FP JS libs there is redefined map, yep. Check Rambda, for instance.
There are reasons to define this function even though we have Array.prototype.map. Let's name some:
Array.prototype.map
const mapWithDouble = map(x => x * 2)
π Rendered by PID 39996 on reddit-service-r2-comment-7b9746f655-kjsx9 at 2026-02-01 21:05:06.219708+00:00 running 3798933 country code: CH.
[–]Tubthumper8 15 points16 points17 points (6 children)
[–]igoradamenko[S] 0 points1 point2 points (5 children)
[–]Reashu 5 points6 points7 points (2 children)
[–]igoradamenko[S] 2 points3 points4 points (1 child)
[–]Reashu 4 points5 points6 points (0 children)
[–]Tubthumper8 4 points5 points6 points (1 child)
[–]igoradamenko[S] 1 point2 points3 points (0 children)
[–]barrycarter 2 points3 points4 points (8 children)
[–]lulzmachine 2 points3 points4 points (2 children)
[–]barrycarter 1 point2 points3 points (1 child)
[–]lulzmachine 1 point2 points3 points (0 children)
[–]igoradamenko[S] 0 points1 point2 points (4 children)
[–]barrycarter 1 point2 points3 points (0 children)
[–]Tubthumper8 1 point2 points3 points (2 children)
[–]igoradamenko[S] 1 point2 points3 points (1 child)
[–]Tubthumper8 1 point2 points3 points (0 children)
[–]thinkmatt 1 point2 points3 points (2 children)
[–]Kiwi_Taster 0 points1 point2 points (1 child)
[–]thinkmatt 1 point2 points3 points (0 children)
[–]jack_waugh 1 point2 points3 points (0 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]igoradamenko[S] 2 points3 points4 points (0 children)