I spent a couple of minutes thinking of a good example of search. Google? No more by a long shot, Amazon also a cesspool. Finder finds too many irrelevant files (no matter what I type it returns a huge list of node_modules matches), this one might be on me. Search on Windows I haven't bothered in years.
The only search tools that actually give me great value are history shell with fzf on the terminal, and grep (and similar like ag or ripgrep) in combination with a fuzzy search frontend (similar to piping grep to fzf).
I don't know where I'm going with this. I guess searching just sucks now.
I completely disagree, complaining about the patent system is a good thing to do, that doesn't preclude doing something else too. I also don't see why the amount of money extorted matter.
I can think of no instances where I need to press a key and a modifier, a key, and then another key, in any program. If I had any bindings like that in vim I remapped them.
I'm definitely not made for emacs, specially not its pinky :)
I have secrets, but if someone were to leak them nobody would seriously employ the term "whisteblower".
Implying that because someone doesn't want to stay quiet when he sees unethical/unlawful things they can't be trusted on a personal level is a dehumanizing thing to say.
I might be breaking a rule here, but this comment could probably be found verbatim in some company's playbook to discourage whiteblowing.
Imagine someone blows the whistle on you liking K-Pop. By the way, I don't like it at all. But just imagine if you were to like it and someone was to blow the whistle. I seriously haven't listened to K-Pop at all, I know it's just an embarrassing thing people do.
Imagine hanging out with Snowden, you both have done a few rounds of pints. Suddenly you slip up about your music preferences. Next thing you know, tomorrow you see a tweet on Snowden's Twitter account and thousands of comments laughing at you.
I can't blame you for thinking it was a GPT reply these days. Anyway I'm also not GGP but he's right, it is Hot Module Replacement.
You don't really need specific tools for HMR in clojure, it's kind of baked in the language thanks to:
- immutability (not impossible but hard to do HMR without it)
- REPL workflow
When developing on clojure, there's a long-lived clojure process and you continually send expressions to be evaluated there.
Let's say you start a server, you make a change to one of the functions that handle a route, just after making the change you will evaluate that function (from your editor) and the update will be "live" in the running server.
It's honestly hard to describe and it doesn't help that we call that "repl-based workflow" when in fact we are not using the REPL directly, but rather through plugins available for various editors. People might think it's the same as using nodejs or python repl, when it's nothing like that. If you're interested, you could check "Parens of the Death" or look for "Clojure CALVA" (VSCode's clojure plugin) videos on youtube.
Edit: It is also not limited to development. Nothing prevents you from hooking into the clojure process in your prod server from your editor, editing a function and evaluating it.
You just monkey-patched a live server to fix a time-critical bug with roughly the same workflow as editing your code locally. Or brought production down, 50/50, but what's life without some risks eh?
I have a lot more experience with common lisp, but currently doing AOC with Clojure right now to try and position myself better for my dream job where I can work with any kind of lisp. Thought I could maybe ask a quick question I have been having trouble answering? I find that with emacs/cider any evaluation is blocking. I am a little spoiled on SLIME/SLY, where it has the nice baked-in feature that any evaluation you do interactively becomes its own process and you can carry on evaluating other things if the process is long running. Is there any way I can replicate this in clojure? Is it just a matter of using `future` explicitly? Or is there something I am missing with cider?
I don't think you are missing anything, I am not aware of anything that would automatically launch new threads when evaluating something.
That does seem like an interesting, although in practice I rarely have to evaluate something that would take more than a a couple of seconds, so manually wrapping it in a future seems acceptable.
On a semi-related note, sometimes I mistakenly evaluate something that will take a long time, or there's a bug and I'm stuck in an infinite loop. CIDER has a command to interrupt the on-going evaluation but I'm my experience it only works about half the time. In those cases having it wrapped in a future would certainly be helpful.
Just for the record, in Java (JVM) this is done (routinely circa first 'bean containers' of ancient history) via interfaces and class loaders. Using Java I can have n distinct versions of a class each implementing the same interface in the same process as long it is the interface reference that is passed around.
> immutability
Make a case for immutability being so critical to HMR. How does an immutable data allow for swapping of code.
AFAIK, Java's native HMR is not built on dynamic classloaders, but using a separate technology built into the JVMs debugger support, called HotSwap. You can only replace (certain) function bodies with it. To get around these restrictions, more elaborate HMR can be achieved with classloader magic, such as OSGi, but you subscribe to a world of ClassCastException-pain with it.
It is still a very good system, and you can get quite a far away with only method-swaps, I love to use them in case of Spring apps, where changing a backend controller and doing another api call is a very fast REPL cycle basically.
But objects don’t give themselves very easily to hot reloading, there are a bunch of edge cases that are not well-defined in a semi-swapped state (e.g. this new field always gets a value in the constructor, but was no just added. Should you rerun the constructor, or have it be in an inconsistent state?)
Immutable/FP concepts are a much better fit, especially if the building blocks are as small as they are in case of Clojure.
My limited understanding of Clojure's HMR is that there aren't n distinct versions of a class/function. It's actually removing the old ones from memory and replacing them.
Also, it is worth noting that everything is immutable, not just data. Functions/protocols/records/etc are also immutable.
Functions/classes being immutable makes it much, much easier to reason about the dependencies of that function/class. E.g. check out this Python code:
Now imagine that this isn't our `main`, this is some library that's a transitive dependency of something we're importing.
Trying to hot-swap this would be awful. The big issues related to mutations are that a) there's no indication in someotherpackage that it's behavior depends on this package, and b) because mutations are allowed, the order that things are reloaded in matters, and c) some mutations are time-bounded.
If I change MyLogger and the VM/interpreter wants to hot-swap MyLogger, it has to recognize that it can't just re-load the instances of MyLogger with the same state. It has to re-load those instances, then re-mutate them, then re-mutate someotherpackage, and finally re-mutate the print function. It might also need to do the stuff that's delayed by that thread. Maybe. Depends on a couple of random integers that probably got GCed a while ago.
If you want to add an extreme layer of annoying, consider that this package could be a late import and only happens if a plugin is enabled, so the earlier code might rely on `print` actually being `print` or on someotherpackage.logger behavior that changes over time.
None of that applies in an immutable world. Nothing can mutate the someotherpackage package nor the `print` function, ergo nothing can depend on an earlier or different version of them. Dependencies are easy to track because the only way to introduce them is to import/directly reference them, or have them passed as parameters.
I don't know that it even needs any dependency tracking, though (provided they're using a pointer to a pointer, or maybe something smarter than that I can't think of). Immutability means that a) everything can be passed as pointers safely, b) those pointers can't be modified by the code, and c) there is never a reason to have more than one copy of a pointer to the bytecode for a function.
Each function gets a pointer to its bytecode, let's call that p1. Every reference to that function is a pointer to p1, which we'll call p2.
When you want to hot-swap code the language pauses the VM/interpreter, recompiles any function with a diff (easy with an AST), puts the new functions in memory somewhere new, changes p1 to point to the new bytecode, then marks the old bytecode for GC.
If you tried something that simple in Python for the code I wrote above, it would explode. It's an infinitely harder problem.
> Using Java I can have n distinct versions of a class each implementing the same interface in the same process as long it is the interface reference that is passed around.
It's been a while since I worked with those app containers, but from my recollection it shares virtually nothing with hot reloading. E.g. is state preserved between those? If I'm caching stuff in RAM, and I change that class out, does it keep the cache? HMR does, as I recall.
My understanding is that app containers basically just run N versions of your app/class and allow you to choose which one you route execution to.
App containers are more similar to blue-green deployments with a load balancer. Each instance is totally separate, and the load balancer lets you choose which one you route to. App containers just do that process inside the JVM.
That's not bad, but it's also not as good as being able to repeatedly tweak a function without ever clearing caches or re-connect to downstreams or etc.
> My limited understanding of Clojure's HMR is that there aren't n distinct versions of a class/function. It's actually removing the old ones from memory and replacing them.
It is almost both. Clojure creates n distinct versions of the function (which are in fact objects and subject to garbage collection). The symbol of the function is rebound (technically this language is wrong) to point to the most recent one. Then, usually, the Java garbage collector deletes the old object.
So it is possible (likely under some code styles) that old versions of a function can hang around in a REPL environment if they ended up embedded in a data structure. However, if you make the call by resolving the function's symbol then that will reliably call the most recently def-ed version.
I'm general I feel icky about people telling employees how they should spend their free time.
I'm keeping an open mind, that's my initial reaction but if what follows is interesting then it has value nonetheless. In this case it's just 2 generalities that don't really help anyone, akin to me saying that to live a better life you should have a good work-life balance.
Everybody knows that, I'm not bringing anything that they can reflect about or act upon.
Yeah, I’m also quite conflicted on this. I don’t like the way the industry expects this to some extent. At the same time most of my learning comes from tinkering outside of work and some larger initiatives have started from me hacking around on parts of a work codebase or open source dependency on the weekend or after work.
A neat trick would be for a company to say “you work 40 hours but 5 of those can be anytime you want 24/7 - and you can tinker. That would be a perk. some people can just do the normal 5 days but others might do stuff at the weekend because it is when they want to do it. I believe tinkering is essential for productivity not Jirafying evey minute of paid time. Software is non-linear. A tinker could lead to an entire team-quarter of work saved.
The Ayns will say do those 5 in addition you lazy bastard to which I say OK then I will do them for my own IP/ideas.
Advice on being a better professional from a colleague and an employer dictating my free time usage are entirely different things. This thread is very clearly about the former.
> Behind every marker crash there's people's lives changing forever.
Absolutely.
My reply was directed towards bitcoin as a technology.
The market volatility but more important the constant manipulators and bad actors really have a negative impact in people's lifes.
But most often we see this happening to people that are invested in crypto but not users of it. Because they keep their money on exchanges, they are not taking advantage to the security and self sovereignty that comes with crypto.
There is no evidence that bitcoin will die or wouldn't recover from market dumps.
However there's plenty examples of exchanges going under or stealing people's assets forever.
Nobody knows how much Satoshi mined. And a rational actor would not "dump" coins on the market for giggles, but for profit, hence avoid a market crash. Besides, bitcoin currently has a trading volume of around 10 billion per day, hard to crash that.
An Allianz OneTrip Premiere trip insurance covers $2000 for loss or theft of baggage and personal effects. They reported the loss to airport security. Getting a written notice of that report ought to be enough to file a claim.
If you later recover an item that you've successfully claimed an insurance claim against, you would just have to hand over the item to your insurance company (who might not even want it at that point). And you should have been able to successfully claim the laptop since at the airport, it was most definitely lost and/or stolen.
Also, how can you even assess that the laptop has no physical damage? They can't boot into the OS and can't see that the laptop is in fact completely physically intact. What if the other party broke the webcam or one of the USB ports?
This entirely misses the point. Using travel insurance for "loss or theft" of something when something is actually, well, lost. The guy has possession of his property, how has anything been "lost"?
I really, really doubt a travel insurance company would pay out on this one.
The computer was “lost” for a whole month before being found and 2 months before being returned. You should claim losses immediately anyway so probably he could have gotten the refund before even knowing it was found.
The only search tools that actually give me great value are history shell with fzf on the terminal, and grep (and similar like ag or ripgrep) in combination with a fuzzy search frontend (similar to piping grep to fzf).
I don't know where I'm going with this. I guess searching just sucks now.