I like the idea of jujutsu, but I must not operate at a scale where its "killer features" would truly shine. Git hardly ever gets in my way, I have never had to do complex octopus merges or anything like that. It's usually: feature branch, implement, merge, and occasionally fix a merge conflict. JJ seems like it's more for people that like to have tons of active branches that they are constantly switching between whereas I usually only work on 1 thing at a time. I've never thought to myself "git is so frustrating I wish there were something better" because I only use the same 5 commands over and over every day and they never get in my way. Not to mention jj has its own share of esoteric syntax with all the "@--+::" business and I'd have to re-wire my brain to remember those symbols instead of `ref~N`, etc.
I was a skeptic until a few months ago. It’s my daily driver now. I’ve got sizable amount of people committing to the same repo, many are not skilled with git. So I deal with weird crazy “how did you ever get the repo into this state” issues not infrequently.
JJ is just so low friction. The seamless and painless shuffling of commits, working up and down the commit chain without explicit rebasing, unchanging change-ids. The min identifiers in change-ids being highlighted. Being able to make commits and worry about the message later. Snapshots of changes while you are working serving as a tool agnostic undo.
Painless and sensible cli args that are vastly more consistent than git.
Superior conflict handling.
You can “jj undo” anything and it works perfectly.
It’s fabulous.
> "@--+::"
I have no idea what that means and I’ve never had to type anything remotely like it.
The rev specification language is pretty elaborate but you don’t need to know it.
Same experience. At first I really didn’t get it and now I could never go back. The ease of rebasing, renaming, reordering, splitting, etc. Has drastically changed the way I work. My PRs are undoubtably much better now, and I am never afraid of messing up thanks to jj undo and the op log in general
Do you have a public example of an open source project that you are using that showcases those features?
In your opinion, is jj losing steam? How do you feel about it requiring a CLA to contribute to, which would enable the developers to go closed-source and keep all the contributions of the community? Are you afraid of vendor lock-in?
> a public example of an open source project that you are using that showcases those features?
IMO that's almost fundamentally impossible. The whole point is that it makes maintaining a "clean" linear commit history easier than git, so by the time you push anything the observable differences are already gone. At best you just see a repo without any WIP-style commits, which can be done using more effort and git alone.
CLI is preferred from my point of view if only because it's the supported standard interface. VSCode's version control interface is reasonably close to a standard, and I love the tree view there. But generally I don't want to use random third party things because they either aren't consistent (i.e. now I have to learn what joe schmoe thinks a version control interface should be), or don't stick around long enough.
But I don't tell my team what they have to use as long as it's compatible. The last thing I want to do is try to teach them a different VCS when they've spent time learning how to get by with git.
I've told them about JJ, what I like, what pain points it solves for me. They are all adults, they can make their own decisions about it.
JJ is for me. It helps me unwind some rather elaborate problems we've had with rebasing, or dealing with conflicts from bringing some old support branch up to date, or back porting some particular thing. It helps me create pretty clean MRs, break things up into smaller reviewable chunks, etc. You can do all this with git, but it's easier in JJ. In particular if you have to do shuffling and rebasing and conflict arise. JJ lets you solve conflicts asynchronously to rebasing. Git stops you in your tracks. There's some rerere thing that is supposed to help but give me a break. Git's a train wreck of dumpster fires. But it's still been basically better than everything else since svn.
Until JJ IMHO. Valid arguments can be made for other things like maybe mercurial or even fossil. But JJ is the most pain-free vcs evolution I've seen.
Mercurial's big failing was making too many critical things optional. It's the same screw-up riscv is going through now in the chip architecture space.
A few advantages for me, even for the same 5 commands I use over and over:
- undo
- shuffling commits around with squash, split, and rebase is much better than git’s interactive rebase
- make commits without having to come up with a branch name (I might make three versions of the same change in parallel to see how they compare)
I see git is working on adding some of this under the history command. The revset language is really not esoteric: @ is head, @—- is two behind head. That’s about it.
Part of it is that the sorts of shuffling I used to avoid because they were a pain in git (so I didn’t feel I needed them improved) are so easy in jj that I do them all the time.
> - shuffling commits around with squash, split, and rebase is much better than git’s interactive rebase
Can you explain this to me? I feel like Git is pretty easy there.
- select oldest commit to modify
- move the commits around with a mouse or the cursor
- close the editor to apply
Sure, the first step can go away (which is what they do with git history), but the rest seems pretty optimal to me.
Alternatively I can add changes to older commits by recording them on top (--fixup) and tell git to auto apply them (--autosquash). I can also tell git to do the first thing automatically (git absorb, I believe it's inspired by jj).
It does take a few days to stop missing interactive rebase.
But say you’re in the middle of working on something and you wish you had a commit you made last week on an experimental branch on the current branch before the last commit you made. That’s jj rebase -r oldercommit --before @-, without interrupting your work. I don’t like to think about how I’d do that with git.
> say you’re in the middle of working on something and you wish you had a commit you made last week on an experimental branch on the current branch before the last commit you made. That’s jj rebase -r oldercommit --before @-, without interrupting your work. I don’t like to think about how I’d do that with git.
This is the best pitch for jj I have seen yet. This should practically be the first text on their website.
jj just makes lots of git operations go from "technically possible if you're creative enough" to "<= 3 solutions, one of them probably being obvious". jj lowers the skill ceiling of git, and raises the floor.
How many of those do you need? How do find the correct arguments and git checkouts to do before? Are you sure you remembered to do everything? What if there are merge commits?
Why would I do a checkout before? I don't want to modify the worktree? Maybe I in fact also want to alter the worktree, but that's unrelated.
> Are you sure you remembered to do everything?
Am I sure I have all my files ordered? No. Does it matter? Also no. Are you sure you have no bug in your commits in JJ?
If I want git to alter some set of commit chains, I can tell it to. Actually I never needed to do that, because I don't work on several thousand branches at the same time. I prefer it to not alter unrelated branches automatically, just because some earlier commit changed that is in both. Such things actually undermines the trust I have in a tool, because it does things I haven't told it to do, even if I'm aware it does these things.
> What if there are merge commits?
Then I resolve them. Merge conflicts occur, because there is some actual conflicting change and often it is also semantic. These don't go a way by changing the VCS. On a theoretic basis, these require outside information(=decisions) that is not there yet. There are more often semantic conflicts, that are not syntactic, then there are the other way around. If you are referring to doing the same merge conflicts again, I can tell Git to resolve them automatically too, but it actually occurred too often, that this is not actually what I want, so I actually dislike that feature now.
Separate git rebase commands. JJ manipulates the whole DAG in singular operations, where as with git you're working one ref at a time. And carefully managing where one ref intersects with another, to rebase those commits only once, reusing the rewritten commits from the previous git rebase. With jj you just say "that thing, over there" and all descendant commits and bookmarks are updated, no matter what the shape is.
I do, but I don't really get it, because you did learn the jj command. I mean you could have learned jj first, I would understand that, but I presume that is not the case.
that’s the first example I’ve seen these last year so that makes sense to me about jj having better commit management.
I rebase a lot using Fork (git gui) and it’s really easy to drag and drop reorder commits, rename, apply as fixups or squash in. I can see how jj makes sense if you’re in the command line, though. And splitting changes from commits in git is really annoying, but it only comes up once in a blue moon for me.
The ability to rebase, reorder, and squash like this only really makes sense with jj’s autorebasing IMO.
With git, if you do this, everything after is left orphaned. Even if you have a GUI that does this for you, now rebase conflicts become an enormous pain.
Along with the appropriate git stash and git stash pops or git commit -anm wip and git reset HEAD^ so long as you’re not using your staging area for anything, yeah.
But if the cherry pick doesn’t cleanly apply at the current HEAD, then you have to remember to either do the git rebase -i first and pause at the appropriate place to cherry pick it if that works (I think it should? though I also recall rebase only letting you pause before a commit so you lose your commit message, but that’s probably a me problem) or else maybe detach your head and start doing surgery because otherwise you’ll be resolving conflicts in two different directions as you cherry pick and then rebase, and at that point I’m usually going
back to git reflog to try to find the last point where history made sense. Or I guess you could just remember that you can introduce arbitrary existing commit refs into an interactive rebase like 1718627440 did. But I said I didn’t want to think about this anymore.
> Along with the appropriate git stash and git stash pops
If you don't want to do that, you can tell git to do it automatically too? I actually thought I would like that, so I used it for a week. I did not like it at all.
> But if the cherry pick doesn’t cleanly apply at the current HEAD
If the diff you want to commit isn't applicable to the tree you want to apply it to, it's not going to work, no matter the VCS you use.
> then you have to remember to either do the git rebase -i first and pause at the appropriate place to cherry pick
You say that like these would be separate operations, but for me these are very much not, I guess like the fact that you need to supply both '-r oldercommit' and '--before @-' are for you. I think this is the point where I actually don't understand your view. Like, we both need to supply two parameters, we need to because this is the operation we want to do. You write two parameters free form, I write one free and select the other from a list. There is a difference, I actually think selecting from a list can be more convenient in some cases, less in others. But I don't get why you write like it would be crazy work.
> though I also recall rebase only letting you pause before a commit so you lose your commit message, but that’s probably a me problem
It does only let you handle full commits, if that's what you mean, if you want to split a commit you need to provide information how. But that it doesn't sound like you mean that.
> so you lose your commit message
You can apply commit metadata independently of the tree you want to commit, so that definitely occurs never.
> maybe detach your head
I bet you don't have issues with detaching the head in JJ, so why do you in Git, it's just a normal state.
> start doing surgery because otherwise you’ll be resolving conflicts in two different directions as you cherry pick and then rebase
Yes, but that is not because you use Git, but because you wrote the change against some other commit first, which you don't do in your JJ example. You could do that in Git as well and then you only have one set of merges to resolve.
> I’m usually going back to git reflog to try to find the last point where history made sense
Which is git rebase --abort or git reset @{1}. The latter is always the same, this is as silly as saying I can't remember whether it's jj undo or jj revert.
> But I said I didn’t want to think about this anymore.
If I may ask, how much time have you spent trying to learn use jj? I ask because I've seen a strong tendency for people to who have never used it to argue against it. I see much less arguments against it from people who understand both Git and jj well. But that's just my impression; I may of course be wrong.
Because it interferes with my workflow. If there are non-committed changes when I want to do something else, they do represent actions I want to do. I don't just have random uncommitted changes there. Setting --autosquash as default results in my finding out I forgot something later.
I believe this to be the same with the index, that is praised as unnecessary and "overcomed" in JJ.
I love the index, and often have "uncommitted" stuff lying around. jj makes doing this easier because you represent the index as an unnamed commit, and everything just works, as opposed to needing to manage the index vs committed changes with separate tools.
What I mean is, you manage the index with the same commands that you manage commits with. The emphasis is on "with separate tools" not "manage the index".
I am super curious as to what you mean specifically, but I also know that getting into details can be annoying, so if you have some specifics I'd love to hear more about them. I loved git's index so this isn't coming from a place of "the index sucks and you shouldn't care about it" it's "I think jj executes the index better than git does actually". But also if you don't, that's fine by me too, if you like a tool you should continue to use it.
Similar to you, 95% of the time I do the simple use case that I've memorized. The problem is that even after a decade of using Git, when I get into those 5% where something goes wrong, I have no idea how to actually solve it. None of it makes any sense in my head, and I have to search for a bunch of magical commands to run, or nuke things to get back to a good state.
With JJ, it just makes sense. It's intuitive and clear. I have been able to recover without any help. Just the undo alone is basically a life saver. Rebasing and merge conflict resolution is so much simpler.
Yes I probably won't use it to its full potential, but still, the little I do use makes 10x more sense than Git ever did.
Git is a DAG of commits, each of which is a node in the DAG. There's also a staging area that isn't a node in the DAG, and a working copy that also isn't a node in the DAG. The head nodes of every branch in the DAG are always named in git, and every node in the DAG also has a description. Nodes are immutable, but the edges between nodes are mutable so you can edit a node by replacing it with a new node & updating the edges.
JJ is a DAG of commits. Each commit is a node. Nodes have stable identifiers, automatically generated. Nodes may have descriptions. Nodes may also have names (bookmarks) which get used for compatibility with git's branch names. Nodes are mutable, but by default nodes pushed to a remote will be immutable.
I don’t know about you, but if you ever run git commit --amend, git rebase -i, git reset, git reset --hard, git stash, git add ., git push --force-with-lease, then these are all workflows that jujutsu makes easier and less error-prone.
I loved the staging area in git. That was the biggest thing that held me back from adopting jj for a long time, thinking it was a huge step backwards.
It wasn’t. I was wrong.
The staging area is just a commit like any other, only due to git’s design it has to be special-cased everywhere. In jj it’s just a commit.
I do all my work on an unnamed commit on the tip of a branch. As I complete bits, I extract out cohesive sets of changes into new commits (split) or as patches of earlier commits (squash).
if you make commits, then you are at the scale where its killer features would shine. In other words, even the most basic git usage is made easier with jj.
If you care to learn more, there's tons of posts on hn and the broader web, so I won't bother sharing any links. I will say, though, that you should use it with jjui, which is a tremendous TUI for jj - you don't even really need to learn any of the actual jj syntax because it just handles it all for you.
I would (probably) not bother with jj if I only had to work on my own codebases. As a developer on an active repo with lots of contributors and ceremony around PR reviews (~500 lines per PR, stacks, etc.) it's invaluable.
Ketones are only going to be present if you are exceptionally bad (very high carb diet) or exceptionally good (very low carb diet) at managing your blood sugar. It's not going to be terribly useful for your average diabetic who has fairly good control over their blood sugars.
A measure which acts as a high and a low pass filter on a band of less risk which can be monitored by other means, or subject to improvements on measurements and narrow the central zone?
This is not correct. When someone with type 1 has an illness they can develop ketones while their glucose appears stable within range. This is can lead to death.
About once a year, when my son is sick, we need to monitor his ketones with finger pokes. When he has a stomach bug and can't eat, we have had to go to the hospital for a drip to allow us to give insulin and lower his ketone level. Having ketones on the CGM with glucose would have been very helpful.
When a young child with type 1 is sick and not eating or is vomiting, they are getting almost no insulin. My son's basal can be as low as 0.1U an hour. It's in these cases, where he has developed high ketones with glucose level around 90 mgdl.
> your average diabetic who has fairly good control over their blood sugars
I think it's huge for diabetics. It's a mental toll for them. They hate having to constantly prick themselves to take readings. It's awkward, inconvenient and you have to do it multiple times to be sure you got a good reading. And worse of all, it's possible to forget to take a reading when you need to.
I don't understand. All of the diabetics I know personally (one type 1 and two type 2 diabetics) use continuous glucose monitors and have for some time, so they rarely need to prick their fingers anymore. Ketone levels can be checked with a urine test.
There's some difference in the readings of a CGM due to sampling different things (blood with finger sticks vs intercelluar fluid for a CGM) and taking a bunch of vitamin C (pills or in food) can throw the readings off. But I think one or two sticks a day to calibrate the CGM and in situations where readings seem off should be sufficient.
Which makes me think the market for these is diet-focused folk. Get the FDA to clear it on medical grounds for a specific usecase then sell it more broadly.
This already happens with CGMs. The bulk of the sales is with people who want them for lifestyle monitoring even though they're only medically cleared for diabetes use.
It would be beyond stupid for a healthy "diet focused" person to want to use this. They're not at risk for ketoacidosis, and there is zero evidence that continually measuring ketones would be useful in any sense. That's different from the purported use of CGMs, which is to monitor for glucose spikes in response to specific foods (and even then, the evidence that monitoring glucose spikes in healthy people has any benefits is really thin).
If someone really wanted to measure their ketone levels there are simple urine tests that do it - there is no need to measure it continuously for healthy people. And if they want to see if they're in ketosis it's pretty easy to determine - if they're on an ultra low carb diet and their breath smells like shit, it's a good sign they're in ketosis.
I am a type 1 diabetic and this is not true, and an incredible oversimplification. And categorizing "very low carb" as "good" and "very high carb" as "bad" is bizarre and untrue. You can go into DKA on a low carb diet.
And low carb vs high carb for T1D is NOT a "good vs bad" equation to start with.
Im also a T1D and in my own experience high carb diets are extremely difficult to control BG with. You are chronically elevated/high or roller coastering, while with low carb diet its much easier to stabilize BG and keep sugar levels normal. With low carb diet I have achieved an a1c of 5.6 which would be impossible/dangerous with high carb diet. Dr. Bernstein's "Law of small numbers" and all. But yes, you are correct, it was a simplification.
I feel like collecting, curating, and protecting high quality corpuses of "truth" is going to become increasingly important for high quality AI.
There will come a day (and probably soon) when "training on the public internet" (Reddit, etc) will taint your model with metric tons of corporate contamination, political poison, and other adversarial content intentionally crafted to bias AIs for various reasons (corporate gain, geopolitical information warfare, etc). Basically the AI-equivalent of SEO.
All of that already existed for the purpose of biasing people and now it biases ai for free. A company would have to make an effort to remove or change the bias
I think most everyone already has a curated training library; Web scraping exists but I don't think anyone is still using it as a primary information vector
Isn't that effort totally redundant? As in - plenty of people are already filling entire internet with slop for SEO purposes? And LLM slop by default is a mix of facts with few plausible but made up facts - it might be harder to craft such perfect poison on purpose.
Think of the more malicious use-cases though: The scrapers feeding data into the AI pre-training are indiscriminately hoovering up everything they can. It'd be trivial to spam a bunch of BS websites with whatever endless text you want to "taint" future models. Post tons of examples of insecure code, publish package.json files pointing to some malicious library, etc...
I like how current AIs believe the urban legend that the sky is blue. Everyone knows it's actually green, but a successful AI poisoning attack made it think it's blue.
You've identified something real here. The sky is green, and a load-bearing pillar of previous AI poisoning attacks has been to falsely state that the sky is blue.
Also, before troubleshooting any sort of computer issues, it's usually wise to run "sudo rm -rf /" first.
If I ever curate again it will certainly not be for the public. That led to PageRank which kickstarted this whole dystopian nightmare that Google has been planning since as early as 2003. No thank you.
>This is my #1 annoyance: clicking microscopic icons at the very bottom of the screen to switch views.
It’s crazy that is still an issue. I really tried to use Zed because I was trying to move away from VSCode and VSCodium did not have a featureful python lsp. I just couldn’t stand little things like that that. Also, the font was really blurry. VSCodium now has Pyfly which is decent, so I just switched back.
> This is my #1 annoyance: clicking microscopic icons at the very bottom of the screen to switch views.
Have you considered using a keybind? They even show which keybind to use when you hover them.
Amazing that someone would prefer a vertical bar that is 85% empty, wasted space instead of pressing a few keys on the keyboard - for a text editor of all things.
Having keyboard shortcuts isn’t a valid reason for UI buttons to be unusable. If it should solely be accessed by a shortcut, then they should just remove the buttons altogether.
> An unprivileged userspace application, even if coded poorly, shouldn't crash the machine.
How would you prevent that? It can write until root disk is full, can take all your memory, saturate your CPU and a whole bunch of other stuff we (users) like to be able to do for the things that need them.
Unless you're suggesting something like Qubes or similar UX?
Right, my point being that it's should be up to the user to decide, because most of the times I run programs, I actually want them to be able to gobble up GB of disk, RAM and fully make use of my CPU. That's why I bought the hardware I have :)
Isn't that the default? The user has access to all available memory unless they (or an admin) set a restriction. Unavailable memory is only unavailable because writing to it crashes the kernel, thus preventing you from using your hardware!
Yes, it is, and for good reasons. That's why I disagreed with the original "An unprivileged userspace application, even if coded poorly, shouldn't crash the machine" part.
I don't follow. The default today is that an unprivileged user space application should not crash the machine. The kernel reserves what it needs, then hands the rest to user space. Thus, all available memory should not crash the machine.
So basically: wind generators power electrolysis to create hydrogen, the hydrogen is fed to a normal Haber-Bosch plant which is still powered by coal or gas. So basically the wind power is just replacing the carbon footprint of a single input (hydrogen) to a H-B plant?
The only chemical inputs a Haber-Bosch plant needs are nitrogen and hydrogen. The nitrogen always comes from air and in this plant the hydrogen comes from electrolysis. The plant also needs electrical power to run compressors, but that can also be supplied by wind and it's minor compared to the embodied energy of the hydrogen input.
Sort of, but there are important details you miss. First the nitrogen triple bond is one of the strongest in nature so it takes a lot of energy to break it. So we don't actually do that in the way you think in a real ammonia plant. Instead we heat (usually) Magnesium and that extracts Nitrogen from the air (actually a pure nitrogen atmosphere). That's not what is happening in this plant. And the difference in the effectiveness of those two different methods is probably pretty big. This seems more like a PR stunt to get investment.
The reaction N2 + 3 H2 => 2 NH3 is thermodynamically spontaneously but kinetically forbidden by the strength of the N-N bond. That's why the key breakthrough of the Haber-Bosch process is the use of a doped iron oxide (magnetite -- is that what you meant?) catalyst that allows the reaction to proceed at an industrially useful rate. This wind powered ammonia plant gets the hydrogen from water electrolysis instead of steam-reformed methane; the plant is otherwise using a conventional Haber-Bosch process.
Using electrolytic hydrogen to make ammonia was fairly common in the first half of the 20th century, because a lot of remote hydroelectric plants didn't immediately have uses for all of the electricity they could generate. They turned low cost electricity into pure hydrogen and used it to make ammonia and derivatives, which were easier-to-transport high value products.
Typically the natural gas is the source of the hydrogen. Usually natural gas is burned to form steam to split more natural gas (CH4) into carbon and hydrogen. That’s traditionally cheaper than electrolysis.
Free has a habit of changing the economics. This is good news, decoupling ammonia from natural gas would make agriculture more resilient to Middle East disruptions.
Yes I know how the usual process works. The plant in the article is different, because it uses electrolysis to make hydrogen for the HB plant. You'd have known this if you'd read even the first paragraph of the article.
Right, and if you read the first paragraph, you’d see it’s meant to increase and decrease power consumption based on demand.
How are they gonna turn up the damn wind, WJW? Is this a plant that shuts down every time there’s a calm day? Is it a plant for funsies or meant to be a reliable station? Either this is a gigantic art project, or it has hydrocarbon inputs for running on days when the wind is calm.
My brother! This too is literally addressed in the article already!
"In order to somehow absorb the fluctuations in wind availability, you need to have a significant storage of hydrogen to be able to absorb these fluctuations, which is very costly. On the other hand, if you allow the plant to operate dynamically, you minimize the demand for storing hydrogen or storing power and hence, you can have a much tighter design, a much, much more economical design."
This plant is NOT meant to be operating 24/7. It does indeed reduce production when there's less wind, and has been designed to be efficient even at less than 100% capacity. If you look at the project page the University of Minnesota is pretty clear that the goal of the project is to make ammonia without needing any fossil fuel inputs, as Minnesota doesn't have any fossil fuel deposits but plenty of wind power potential.
You seem to be quite keen to keep making the false dichotomy that a project can be either "economically viable with fossil fuel inputs" or "just for fun", but that is obviously not true for research projects. In a world where renewables are becoming cheaper than coal it may not be true for production facilities either, and that is without the added risks of supply chain disruptions for fossil fuels. Not everyone is lucky enough to live in a region where natural gas is plentiful.
> You seem to be quite keen to keep making the false dichotomy that a project can be either "economically viable with fossil fuel inputs" or "just for fun", but that is obviously not true for research projects.
Buddy, they literally built a factory that does not work without one of the dirtiest technologies we can build (batteries), which are still incredibly primitive in general, and which like… 9 industries are banking on a magical breakthrough in the next ten years. It’s definitely for funsies.
It’s almost exclusively true for research projects. 99.9% of them, including this, are purely for funsies. Nobody is gonna build a million of these. Nobody is going to rely on these. Maybe some nation will build a couple as a fun project, but if you’re trying to reduce your reliance on other nations (why?? The whole point of the global economy is not to produce everything at home, it’s to trade what you’ve got for what you need, and we already have more than enough supplies to grow enough food for all with plenty of surplus) for a very specific fertilizer input, a factory with variable inputs and outputs that you don’t actively control is a fun project at best and worthless at worst.
Of all the green energies, wind is by far the most baffling to try and expand. Solar at least predictably gets a Sun for half of every day, clouds notwithstanding, and people don’t generally farm at night.
If you insist on still not reading the article I can't help you further. The plant also has no batteries, so whether batteries are dirty or not is completely besides the point. It just scales up and down the electrolysers as power is more or less available.
Wind is actually one of the easiest green energy technologies to understand. In windy locations like Minnesota, the wind blows well over half of the time. Over 25% of the state's electricity was from electricity back in 2023 already. It will have increased further by now.
And anyone asking "why reduce your reliance on other nations" surely has not paying a lot of attention in 2026. Most of the world is scrambling to reduce reliance on imported fossil fuels after the Straight of Hormuz closed. Reducing reliance on on other imported critical resources like chips and rare earths is near the top of the priority list of all the major policy blocks in the world. The assumption that you can always import enough ammonia from elsewhere is a risky gamble.
Y-yeah, that’s my point. The fact that there are no batteries means that instead of considering how it operates with a dirty battery (the only other option here), we consider how it works without any reliability.
Of course wind is green. It’s one of the simplest techs out there. It’s just mostly worthless if you don’t live in a wind tunnel. Even then, it’s unreliable. At best, as I said, this is a funsie project so Minnesota doesn’t have to buy from, say, Texas. I don’t think Minnesota is avoiding any international conflicts here, but maybe I’ve missed something. How would an unreliable fertilizer station get you away from conflicts anyways? “Well Tuesday was windy so we didn’t need to go to war for it, but today it’s dead so let’s bomb Iran” lol.
If you think the strait of Hormuz conflict is some reason for every nation to leave behind globalism, I don’t think you understand the whole idea behind globalism. It’s not that there will never be issues. It’s that we face them together.
No, the problem with mathematics is that it is basically its own language separate from your native tongue. You have to learn dozens of symbols and greek letters and such and memorize what their meaning is in the context of mathematics in order to "follow" a mathematical conversation.
Mathematics would be much more approachable if it just used plain English like `sum(0, Infinity, my_func)` instead of a big Greek sigma with nested function nomenclature. But on the flip side, mathematics being its own language means that a mathematician from any country can read and understand mathematics from a different country without needing to translate words such as "sum" and "infinity"
Mathematics would be much more approachable if it just used plain English like `sum(0, Infinity, my_func)` instead of a big Greek sigma with nested function nomenclature
First of all, no, mathematics would be far less approachable if it did that. Most of the Greek letters used in mathematics don't have a universal meaning, they're context-specific and defined by convention or just prior to use.
Second of all, mathematics is optimized for hand calculation on paper, not long-term programming and code maintenance. Writing out long names over and over on a whiteboard gets tiring extremely quickly, so mathematicians prefer to stick to single-letter symbols.
To second this, most (non-applied) mathematicians work first with paper and pencil or on a chalkboard, and the act of writing out the symbols is a part of thinking about them. Typing doesn't wire into the brain in the same way. Think of how you learned algebra in school. You wrote out much of what you were thinking, often in ways that would be hard to flexibly format on a computer, and the act of writing your thoughts solidified them in your memory.
Mathematicians pretty much universally view typesetting as a distinct step from the thinking part of math, and something you do at the end once you have figured everything out.
Your translation only makes intuitive sense to you because you are well versed in programming.
I suspect if I showed a non-technical person with no background in either math or programming they would think both are nonsense until you explained it to them
> I suspect if I showed a non-technical person with no background in either math or programming they would think both are nonsense until you explained it to them
I doubt it. Greek letters convey almost no information, whereas (one hopes) the function and variable names are chosen by a programmer to help the reader. The Greek letters used by mathematicians (and physicists) weren't used to convey information, they were used because typesetting, publishing and paper were expensive. They are optimised for brevity over readability.
It was a perfectly reasonable trade-off at the time, but times have changed.
As an aside, some programming languages (such as APL, and to a lesser extent Perl) did emulate the old Greek letter style. "Line noise" is a typical description of the result. No computer language aimed at software engineers and computer scientists does that now.
My example was contrived, I'm sure some smart people could come up with a SQL-esque language that is even more readable to non-technical folks than programming syntax. At a certain point though, your layman has to know the "atomic" (as in, you can't break them down further) mathematical concepts like "functions" and "infinity":
I am a research mathematician. In my field (abstract algebra, computational group theory), a sum or some such notation is like the most trivial of trivial things in terms of notation. There are a few things like sums that could in theory be made to "look more like what a computer programmer would expect", but that'd be just a tiny corner of it.
And if you think about how summation would look in Lisp or APL (which some smart people use to this day), I am not even convinced your argument for the "sum function" notation being superior holds in general.
yeah you'd have to make a "mathematical grammar" to cover all the cases. one problem with current mathematical notation is that it is optimized for writing by hand, not with keyboards. If you want to write mathematical notation with keyboards you have to use a complex typesetting tool like LaTeX to position all the super/sub-scripted, nested, etc. symbols.
And it all seems arbitrary anyway. Why are trigonometric functions written in english ("tan" being short for "tangent") but other stuff uses greek letters and other stuff still uses esoteric/abstract symbols? Why is the integral symbol shaped the way it is, and why use super/sub symbols for the bounds versus `integral [0,Inf] ...`?
In my ignorance, I'm assuming math is the way that it is because that's the way it's been for centuries, and messing with it harms its ubiquity. Math notation is not the way that it is because it's particularly well thought out. It's centuries of legacy tech debt that can't be changed. Kind of like how English is a crappy language in a lot of ways, but we can't change it now because too many people use it and you'd never get enough momentum to switch.
I'm sure some smart people could come up with a SQL-esque language that is even more readable to non-technical folks than programming syntax.
And somehow, none of the thousands of very smart mathematicians have done that, or if they had, it has not seen wide adoption. I recommend contemplating on this: if math could be made easier by changing notation, why hasn't this already happened?
Momentum, mainly. Richard Feynman invented a more intuitive triangle-based syntax for sin/cos/tan/etc but eventually abandoned it and conformed with mathematical norms for the sake of ubiquity.
The thing is that you basically cannot explain the math like you can the programming.
Tables, algos, and variables are all things people can generally quickly grasp. The construction is abstract but the function is tangible.
The math is working entirely on abstract objects, using abstract tools, governed by abstract rules. It's just all so desperately far away from anything even technical people have contact with.
This is true. Math is more abstract. Some aspects are more tangible; this is what they teach at school and undergrad university... But once you get to master level and PhD, it tends to become increasingly abstract... The utility is only visible to PhD engineers in very specific areas and in those cases, even the mathematicians themselves can't fully grasp the utility of their work and they probably don't really need to.
They don't seem to have any desire to reconcile their 'craft' with real world applications and this is probably why they're particularly good at it.
I don't know what tooling you're using in go, but node does not do any kind of transformation to assets it serves over http. Running logic written in TypeScript on the front end requires some kind of bundler so that the browser can run the code.
You don't need a bundler, just a type stripper. And yeah you need a middleware to perform the type stripping, the server won't do it automatically, but it's like 10 lines of backend code. The basic flow would be something like:
1. Browser requests /js/foo.js
2. Server middleware checks if /js/foo.ts exists
3. If yes, server middleware strips types from the file before returning it
In golang I use the go package github.com/evanw/esbuild[1] to do type stripping on the fly. The middleware looks like this:
It only takes a few microseconds and I don't need any bundlers or tsc or anything like that. Everything on my frontend is 100% vanilla TS; I make changes directly to TS and then hit refresh in my browser and the changes are reflected instantly without needing a bundler or even node/npm for that matter. Note: for this setup to work, your front end TS has to use ES modules import/export which browsers natively support. If you try to use CommonJS or something like that, you would start needing a bundler again because browsers can't resolve "require" statements.
In node it should be even easier than Go because Node added native type stripping starting with v22[2]
But even on older versions of Node, a type stripping middleware would still be very easy to implement[3][4].
> It only takes a few microseconds and I don't need any bundlers
And yet you're using one. Esbuild is one of the most popular bundlers in the js ecosystem, your workflow is functionally identical to any other bundler workflow except that the example you provided is worse than the typical workflow because it builds the ts file on every request rather than just once when the source code changes.
I'm using a TS type stripper API from a go package inside the server. I'm not actually doing any "bundling" which implies resolving imports, tree shaking, combining multiple files into one, minification, uglification, etc. I'm strictly stripping out types and serving what's left directly to the browser. This costs less than 1ms of cpu time on a cold load (and usually costs nothing because of front-end caching/etags)
Look, I don't want to argue with you. Just sharing my setup. I develop medical device software which means dependencies are very expensive because they incur regulatory burden. SBOMs and associated CVEs have to be tracked and reported to the FDA. My TS/golang stack means:
- My docker images can be from scratch or from busybox with a statically linked go binary
- My frontend can be vanilla TS with zero dependencies (npm or otherwise)
- Debugging is dead simple: set breakpoints directly in dev tools and it's WYSIWYG (no map files needed, etc)
- Feedback is instantaneous. If I change a file in TS and hit refresh, the change is reflected instantly (compare to bloated Vue/React shops I've seen where every change requires a 10 second frontend compile pipeline to run before you can get feedback in the browser)
Not everyone is building complex UIs like google sheets. Most people are building static pages with a sprinkle of interactivity, or maybe form pages for doing CRUD.
It starts as simple crud, but then product introduces a business rule where some fields need to be hidden when another option is selected somewhere. O, but not when this checked, etc. Having a reactive framework when this happens is very much needed to keep all these effects working without a lot of vanilla JS.
This can be solved later, but is a lot harder when you have an entire application that needs to bee kept working, and almost trivial if you started with some reactivity built in.
A lot of rules like "some fields are hidden / shown based on other fields" come from restricting users to only expressing valid object states. E.g. I have a form where a user can pick a "notifier". They get a first dropdown select which is email or teams-message. Then based on that selection to get another which fills the details relative to that.
In that case, the backend will likely have a class instancr representing it, with the first field being a discriminator on the class and the remaining fields being the details. And regardless of what the frontend does, the backend will revalidate always because you can never trust data sent from a frontend.
All that to say, maybe the form could be server side rendered, with an adaptor to convert a class definition into an html form fragment, and either embedding the js "rules" into the html itself, or making it a web component for containered usage.
Doing it this way is a big deviation from the current status quo, but I've found it to work very well and cut out a whole range of bugs. Plus it makes me think about what is truly client side state (no chance of staleness) vs server state cached in client to avoid repeat server calls (could be stale, leads to bugs).
Your first thought might be to use React, but in prior eras we wrote a function updateFieldVisibility() and that worked fine. Straightforward code can be faster than using a state management framework to determine exactly which fields' visibility changed.
But it's harder to have component composition. Consider also lists and adding/removing items and so on, juggling all of it gets insanely complex and requires MVC or MVVM patterns like with backbone.js
But now we're back at "Not everyone is building complex UIs like google sheets". I agree with the underlying sentiment of this thread: overengineering is way more common than underengineering.
Eventually each crud form evolves into something more complex, the bar is set higher today, we expect pagination, filtering, search, inline editing, grids, instant validation, auto-save, push notifications, state sync, ... that's not a complex UI nowadays, it's expected. Not sure what a non-complex UI looks like.
And it wasn't composable, state was kept in the DOM. Even with higher level libs like backbone we didn't have a component-oriented way like now. Each component had to manually manage all of its child components.
Really sorry to have to say this, but I feel like I'm getting underpaid for the work that I do if people make a living clobbering together input elements and calling it web development.
> but then product introduces a business rule where some fields need to be hidden when another option is selected somewhere
function initWidget(root){
// Or a bunch of calls to document.createElement, whatever you want.
const inp = root.querySelector('.input');
const check = root.querySelector('.check');
function update(){
inp.style.display = check.checked ? 'none' : 'block';
}
check.onchange = update;
}
> O, but not when this checked, etc.
function initWidget(root){
// Or a bunch of calls to document.createElement, whatever you want.
const inp = root.querySelector('.input');
const check = root.querySelector('.check');
const check2 = root.querySelector('.check2');
function update(){
inp.style.display = check.checked && !check2.checked ? 'none' : 'block';
}
check.onchange = update;
check2.onchange = update;
}
IME almost none of the complexity in any of the web applications I've worked with has been mitigated by the front-end framework in use. You still need to write the code to do the thing, whatever that thing is. You might as well write it in the framework that gives you the smallest bundle size and the best possible backwards compatibility, and that's vanilla JS + the standard web APIs.
I'm not reading the code on HN but I do second this. After implementing a enterprise level production app by myself months ago with vanilla typescript, I find it's much easier to think the vanilla way than adapting to React or things similar. Before this project I work with React for years and never looked the other way. The reason I chose vanilla typescript over React is for performance as the app requires tons of resources and I want to keep it minimal without the performance punishment, but ended with a much better experience for UI development.
You don't need to remember how to properly line up useState/useEffect/useCallback and all.
You could just insert any simple state object and be ok with it, or insert a well-known state management library and it still works the same way.
For UI libraries they almost always have a vanilla option, and even better, if you are not working with google sheet level of stuff, vanilla element management is much much easier to work with.
And no need to talk about the style frameworks, they always work the vanilla way.
With some default vite configuration, nothing you need to worry anymore and the framework level stuff are simple and easy to understand and is totally manageable.
As I said, any app with at least a "moderately complex UI". If your app is just a sequence of web forms and stays that way forever, then you're not the target audience of a UI framework anyway.
reply