Click
clickclickclick.click
clickclickclick.click
let button = document.getElementsByClassName('button')[0]
Array(100000).fill(undefined).forEach(() => button.click())
In response, I got the following log message: > Such a smart subject.Array.from({ length: 10000 }, button.click);
But your approach makes perfect sense and is so much cleaner. Thank you!
If anyone is wondering why it works, it's because everything in JavaScript is an object. So, an array is an object with a length prop. Apparently Array.from just needs any object with a length prop to work
Similarly, when I pick up a feathered pen in real life I become a duck
Well, .duck isn't a TLD yet and it may not be publicly available...
[...new Array(1000)].map(something)
[...Array(1000)]
I think that is the least bits. Would love to be proven wrong :D
That's what I like in the elegance of Array.from({ length: 1000 }): it's a hack, but it reads naturally.
Guessing it's bc one-liners are easier to write than for loops in the console.
A for loop can implement a reduce, a reduce can implement a map, a map can implement a forEach, but not the inverse.
In [1]: def lred(function, iterable, initializer):
...: acc = initializer
...: def reductor(el):
...: nonlocal acc
...: acc = function(acc, el)
...: for n in map(reductor, iterable): pass
...: return acc
...:
In [2]: lred(lambda a,b: 10*a + b, [2,4,6,3,1], 40)
Out[2]: 4024631
What's stopping you from running these equivalencies in either direction?A map can run code per list element but the result must be injective (one-to-one).
Reduce can do all of the above, but must return a lower dimension result from its input.
And finally, a for loop is basically omnipotent.
acc = []
for el in values:
acc.append(f(el))
return acc
This hierarchy doesn't exist; you can pretty much implement any of them in terms of the others.To make that untrue, you need to define very strict limits on what else your language can do.
(Sure, we produce a transformed list here through the use of side effects. But note that the original example sparking the claim that forEach can't do what map can was this:
.forEach(() => button.click())
Side effects are clearly allowed.)You can implement any of them in terms of the others, but only if you break convention and introduce side effects. Follow convention and try to implement (for example) reduce with map and you'll find that it's not possible.
This can't be right. forEach has no effects other than side effects. A convention that says not to use side effects prevents you from using forEach at all.
But that would make claims about the place of forEach in a hierarchy into meaningless nonsense.
> The forEach isn't returning it in your example, the line after it is returning.
That depends on your point of view. C has numerous functions which accept pointer parameters and return values in those parameters. That's just the normal way to return multiple values in C.
And by that standard, the forEach itself is returning the transformed list; that's where the transformation occurs. The following `return` line is only necessary if this is a snippet within a function whose purpose is to execute a for statement; you would actually do this inline, by just writing the for statement without needing a following `return`.
And without side-effects, a map can't implement a forEach.
Yes, it can, because without side effects, forEach is a NOP. That's not difficult to implement. As long as you don't do anything with the return value from map, you're there.
What do you mean by this? You can accumulate just about anything into the resulting object, including a copy of the original array.
Of course, in fact you could hack anything in any of these, since you could be doing other work in the function called. But I think the general principle is sound.
Don't tell Common Lisp.
You might notice this problem above, where it's necessary to do
for n in map(reductor, iterable): pass
to realize the mapping.So can map. Ditto.
So can foreach. Ditto again.
for el in values:
if el == 3: pass
else:
do_something_with( el ) for el in values:
if el == 3: return
do_something_with( el )
For the other two, you still can, but you'll need to handle the control flow yourself, by doing something like goto or invoking a continuation.I take it you've never read any Python? That's a forEach. Python doesn't even have a for loop construct (though it does have while, which is equivalent).
> And depending on the language I'm pretty sure that return call would exit the parent scope.
Yes, that's the point, that's an illustration of terminating the forEach before you've processed each element.
If you have a C-style for-loop, you can and have to do everything yourself. That means you can skip elements or processer them twice, etc.
In a Python-style for-each loop, you can break out with break or return, but you have a harder time skipping or changing the order of processing. So they are weaker. And that's good.
(Your examples still process elements in the body of the loop. It's just that sometimes the body decides to do a no-op.)
Putting the no-op logic in the body of the loop, or in the function you pass to reduce is different than being able to short-cut evaluation.
You can see the difference most clearly, when trying to process (the start of) an infinite generator with reduce or a for-loop. Reduce will just hang.
Firefox has a pretty good multi-line editor now if anyone was looking for that
Maybe a contender to CookieClicker? 73% achievements atm
Open a console, and prep: xdotool click --delay 50 --repeat 1000 1
Move your mouse to the location and press enter.
for(i of Array(1000).keys()) { doSomething() }
or [...Array(1000)].forEach(() => doSomething())for(let i = 0; i < 1000; i++) button.click()
wouldn’t be surprised if Javascript has some weird optimization under the hood!
dotimes(n, () => button.click())
If anyone is in the habit of solving trivial constant space problems in linear space where n is expected to be over 100000, I don't know what to say to them. Are Javascript implementations pretty much guaranteed to optimise the array away?E.g.
// Get list of even squares of first 10 integers
Array.from({ length: 10 }).map((e,i)=>i*i).filter((i)=>i%2==0).forEach((i)=>console.log(i));
// Or more readable
Array.from({ length: 10 })
.map((e,i)=>i*i) // Get squares of each number
.filter((i)=>i%2==0) // filter for evens
.forEach((i)=>console.log(i)); // print
Want to filter or manipulate the values in a different way? Throw in another map or filter. Want to pass complex values between steps? You can pack them into an array or object in a map and unpack later.[1] Once you're used to doing stuff with lists, you can use some other interesting list operations like reduce(), some(), every(), etc.It's not really better (it's subjective), it's just different and a lot of people are used to it and prefer it (and it's fairly consistent in nomenclature across some languages, which is a bonus).
For loops are just clunky. They're not values, you can't pass them around or copy'n'paste them where the transformed value is needed.
[...Array(n)].map(something)
I was quite inexperienced - 1 year after graduating from art school - when I joined and started working on this project. The server went down 5x in a single day because of all the requests. We were using web sockets (simple node server with express + socketio and a react + rxjs frontend) and that put some strain on the server. And I made the rookie mistake of storing images directly into the database instead of in a S3 bucket. Also we chose CouchDB, which saves document revisions (I didn't know..) so at the end of the day the database took 100% disk space and I couldn't SSH into it anymore. There were something like 20M+ database writes within 24hrs of the launch because it went viral.
We span up larger DO droplets several times because of this issue which took a while to fix.
It was my first time setting up / working with a VPS and nginx + sockets as well, so I'm actually quite pleased with only 15-30mins downtime overall on launch day :)
I learned a lot during that time (it was made in 2016), especially with the help of HN. Projects are often developed by junior devs or people skilled in other areas. Some experience is useful when deploying scalable apps. Nowadays it's much more easy with services like Vercel/Cloudflare/Heroku/AWS/etc. We used SFTP to deploy the site. I think I moved it to a Docker container some time after that.
I'm still using DigitalOcean to this day for my personal stuff, only now I use Dokku + Cloudflare - which works like a charm.
Check out https://studiomoniker.com if you want to see more crazy projects! (They're my previous employer FYI).
Sorry about that! There may be an initiative to update it in the near future.
I do statically-render everything, so not doing that is the only reason I can think of for why so many sites might be going down when they get up on the front page. Many of these are blogs so could probably do much better, though I did see someone mention that this one uses websockets for something, so it would definitely be doing some logic on the server-side and wouldn't be able to go fully static.
I'm hosting 30+ apps (frontends / api's / cms's / other processes) on a single 5eu/mo DigitalOcean droplet. I believe Hertzner is the cheapest hosting provider with a 2,87eu/mo VPS.
Self-hosting is a lot of fun, and cheaper. Dokku has been around for several years, it's an open-source Heroku clone and I would recommend it to anyone looking into deploying web apps.
Edit: I see DigitalOcean has it available as a 1-click install. Do you get totally automatic updates/system management and everything with that?
Some config changes fixed it right up, but my point is that it's not just the capabilities of the instance, the default http server configs might need some tweaking too.
(Static sites should be fine, but many sites use dynamic CMS like wordpress, ghost or discourse, on very low-powered hosts, which really need a caching layer to hold up under non-trivial load)
Blog written in PHP but without database interaction
> Firefox can’t establish a connection to the server at wss://clickclickclick.click/socket.io/?EIO=3&transport=websocket&sid=... websocket.js:111
> The connection to wss://clickclickclick.click/socket.io/?EIO=3&transport=websocket&sid=... was interrupted while the page was loading.
Reading the comments, it sounds the site is supposed to log everything that I do? Perhaps Firefox is blocking it?
As is the plight of a firefox user, I'm headed to chrome to see if it works there :\
edit: looks like it there's a ton of audio files that may have failed to load.
Hmmmmm...
https://studiomoniker.com/projects/click-click-click
Getting to #1 on HN never easy for the robots. :-(
A demonstration of browser events used to monitor online behaviour - https://news.ycombinator.com/item?id=12985644 - Nov 2016 (165 comments)
There is no good answer to why, except to improve fingerprinting. Which is most of what this site shows, the amount of data a site, even open in the background, can use to continuously fingerprint you. Or maybe I misjudge what this is supposed to do.
Which machine do you think has the best performance for your app?
window.navigator.hardwareConcurrency
[edit: well this is more of a 'how' than a 'why']I helped make a timing attack[1] as justification for adding this API, and then presented this suggested API to each browser vendor along with the timing attack. The result was that every browser has adopted my suggestion.
If this API was not present, ads could get this data in a more resource-intensive manner anyways.
1. https://eligrey.com/blog/cpu-core-estimation-with-javascript...
Other types of programs don't have that problem. If you get some code from Github, you can review it yourself before the first time you run it. Then every time after that, it's still the same code so you only have to do it once. And you can have someone you trust do it for you, like a Debian package maintainer.
But with nobody reviewing the code, the machine has to do it, i.e. there have to be a bunch of technical constraints on tracking and malicious behavior.
It's a terrible rubbish fire that we don't have any kind of real application platform for real applications that runs the same on every system and doesn't have a monopolist dictating terms. We should fix that. But we could fix that, and be better off than by giving up and conceding the world to surveillance dystopia.
Well, they didn't. They do now, as you're expected to update everything continuously. A typical user of a PC or a smartphone has something downloading an update pretty much every day. Even a tech-savvy user can't hope to keep up with trying to track down all sneaky automatic updates and read a changelog before applying them (assuming there even is one, beyond "This update improves experience and fixes bugs" zero-information boilerplate).
At this point I'd be willing to pay for a service that would intercept all automatic updates on my devices and warn me about the ones that bring in telemetry, malware, performance degradation or other misfeatures. Unfortunately, such a service would require impossible feats of crowdsourcing to keep up with the deluge, and itself would be a huge privacy/security risk.
The reason mobile app stores are garbage is that the store is glued to the platform, making it high-friction to switch to another one if they do a bad job. Then they do a bad job by allowing things you don't want and prohibiting things you do want (and charging high fees etc.) and get away with it.
There is no reason for this to be centralized into a single approver. If you got 90% of your software through the Debian package manager but specifically need a newer version of Blender than they package, you could get that in particular directly from the Blender developers because you trust them not to intentionally distribute malicious code, while still relying on the package maintainers to do the work for all the other software you use.
That's possible right now on Linux. The problem is mostly that it's not possible right now on everything.
My wish came from the opposite end - I have all this software on my devices that's sourced from a lot of different places, and some of the software on my PC has built-in auto-update that's independent of the original installation method. What I want is a curation add-on - a single (at least per-device) component that would intercept all automatic updates of everything, coupled with a database (the service part) that could tell me roughly what the update contains, and flag anything problematic (telemetry, ads, feature removals, performance degradation, ...).
Your reply made me realize two things:
1. I used to hate default package sources on Debian for shipping a small selection of outdated software. I formed this impression back when I was young and naïve, and didn't question it since. But now I can see the value in having actual humans curate the software. I need to get out of the habit of adding random sources and PPAs just for the sake of having everything bleeding edge.
2. I'm really mostly pissed about this on behalf of other people. I've learned to manage my devices - mostly by being very selective about the software I run. Most people I know in the meatspace don't have the necessary experience and time, and helping everyone individually doesn't scale.
It tells you if it knows where your cursor is, what pages you've been to, what your computer is, etc.
It was intended to show that you, the user, give out a lot of data without even realizing it.
EDIT: I did a search on reddit and it looks like it actually is https://clickclickclick.click, but because the site hasn't been accessible I can't be sure.
Quite clever.
- it helps with fingerprinting
- there’s no reason to allow it
The logic was that, maybe you were logged to Telcel or to Movistar, or to Liverpool vs Sears (Mexican retailers). That could give us signal on the probability of default
window.history.length
would be my guess.It only counts the previous sites in the current browser tab if I remember correctly.
“Subject has clicked the button”
“Subject has scrolled down”
“Subject has resized the window”
etc.
So what?downdowndown.down
EDIT: Either firefox or edge the result is always the same:
"failed: WebSocket is closed before the connection is established."
Not sure why I got this message, which is not true.
YouTube does that, if you try to manipulate the dom it throws some error. I ended up injecting CSS instead.
[1]: https://www.bloodrizer.ru/games/kittens/ [2]: https://adarkroom.doublespeakgames.com/
Now there is nothing left in the universe besides:
> Paperclips: 30,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000