Hacker Newsnew | past | comments | ask | show | jobs | submit | jve's commentslogin

Are you talking about income or real income?

> Adjusted gross disposable income of households per capita in real terms is the total amount of money households have available for spending and saving after subtracting income taxes and pension contributions, plus the individual goods and services (such as education and health services) received free of charge from government and non-profit institutions serving households. Real means that its nominal value is adjusted for price increases (by the deflator of household actual final consumption expenditure). Per capita indicates that the value was divided by the total population.


That’s a pretty fuzzy number. How do they value or even allocate the value of those free services?

I was also dreaming of an opening in a wall where I can brush my dust into and it magically disappears... Since having cordless vacuum I no longer dream about that.

I mean even a plug which would let you plug in an elephant nose - I think that is more cumbersome than the cordless vacuum. I mean having to get that hose and hook it up every time I want to vacuum something? Meh. Easier to pick up the 21th century broom that makes dust disappear when you roll over it.

And manual brooming makes you give n passes over the same place to do the job... juck.


As I understand that is the core design feature of any strongly typed language.

I believe they're talking about gradual typing[0].

[0]: https://en.wikipedia.org/wiki/Gradual_typing


Not really. Strongly typed languages don't usually support not having any types in your code (or any amount of gradual typing). At least not with any convenient syntax. There's usually some one clumsy "dynamic" type that doesn't interact with the rest of the system well and you'd be crazy to start writing your code using only this dynamic type.

I can't just write C++ like:

  any a = 1;
  a = "Hi!";
I also can't tell JS this shouldn't be allowed. But I can tell this to TS, at any stage of evolution of my program.

Nitpick: In the "static, dynamic, strong, weak" quad, C/C++ are considered weakly but statically typed because you can nonchalantly bypass the type system.

In this case you'd need to be pretty explicit about the bypassing but you could write

  int a = 1;
  strcpy((char *)&a, "hi");
(and it'll even kind of work in this instance since "hi" fits in an int, if on your C/C++ implemnentation int happens to be sized 3 bytes or more)

> then they don’t deserve code that is prove

I don't get it. Types are a way to write code. Nothing to do with how fast/much the code changes.


Typed code is significantly more cumbersome to change (because there's more code to change). At least until you reach a certain size of your spaghetti bowl. Then both typed and untyped are cumbersome and people endlessly discuss which one is more.

I don’t think so. With a good editor, you change the type and run the compiler which will warn you with all the locations you’ll need to edit. Then you can quickly navigate to those locations.

> which will warn you with all the locations you’ll need to edit

This is true, but with a program built with a dynamic language, taking advantage of the fact that it's written in a dynamic language, doesn't need to make those changes at all.

I'm fan of static typing in many situations, but it's hard to deny it doesn't lead to more changes as you need to properly propagate changes.


I don't find that dynamic typing reduces the number of places I need to update stuff. It just changes when the error occurs.

If I change the shape of some data (such as renaming object properties), I'll need to update all the code that used that data, regardless of the type system. Static typing just ensures that I catch those cases at compile time, not runtime.


Just one simple and contrived example I could come up with the five minutes I had available:

JavaScript:

  // rename host -> hostname, update ONE place
  function connect(opts) {
    const host = opts.hostname ?? opts.host; // compat shim
    return `tcp://${host}:${opts.port}`;
  }

  // old call sites keep working
  connect({ host: "db", port: 5432 });
  connect({ host: "cache", port: 6379 });

  // new call sites also work
  connect({ hostname: "db", port: 5432 });
TypeScript:

  // same compat goal, but types force propagation unless you widen them

  type Opts = { port: number } & ({ host: string } | { hostname: string });

  function connect(opts: Opts) {
    const host = "hostname" in opts ? opts.hostname : opts.host;
    return `tcp://${host}:${opts.port}`;
  }

  // If instead you "just rename" the type to {hostname; port},
  // EVERY call site using {host; port} becomes a compile error.
Again, this is just a simple example. But multiply 100x + way messier codebases where everything are static types and intrinsically linked with each other, and every change becomes "change -> compile and see next spot to change -> change" until you've worked through 10s of files, instead of just changing it in one place.

Personally, I prefer to spend the extra time I get from dynamic languages to write proper unit tests that can actually ensure the absence of specific logic bugs, rather than further ossifying the architecture with static types while changes are still ongoing.


In your Typescript example, the solution would be to use your IDE to refactor hosts to hostnames, a process that takes like 2 seconds. You might have problems if the change exists at a service boundry, but in that case I'd just put the transformation at the service boundry, and keep everything the same internally.

> Personally, I prefer to spend the extra time I get from dynamic languages to write proper unit tests that can actually ensure the absence of specific logic bugs, rather than further ossifying the architecture with static types while changes are still ongoing.

I'd argue static typing makes this much easier, because I know any input types (or output types from other components) will be enforced by the type system. So I don't need to bother writing tests for "what if this parameter isn't set" or "what if this function returns something unexpected". The type system handles all of that, which eliminated a lot of tedious boilerplate tests.


> In your Typescript example, the solution would be to use your IDE to refactor hosts to hostnames

Yeah, sure, and with LLMs you can do this, and you can do that. But if we're talking about languages and their features, relying on IDE features feels slightly off-topic.

But regardless, changes is changes, no matter if you, your IDE or your LLM made them. So even if your IDE makes the changes, it seems at least you can now agree that there are more changes needed, it's just that with TypeScript you have a editor who can help you refactor, and with JavaScript you haven't yet found an editor that can do so.

> So I don't need to bother writing tests for "what if this parameter isn't set" or "what if this function returns something unexpected".

Yeah, those unit tests does nothing, and people who write in dynamic languages don't write tests like that either. You test actual logic, in unit tests, and you rely on the signals that gives you.

In fact, I could bet you that if you and me both sat down and wrote the exact same application, one in JS and one in TS, we'd end up with more or less the same amount of unit tests, yet the JS codebase will be a lot more flexible once product requirements start to change.

But again, YMMV and all that, it's a highly personal preference. I don't think there is a ground truth here, different minds seem to prefer different things. I mostly work in environments where the requirements can change from day to day, and being able to adopt to those without introducing new issues is the most important thing for me, so with JS I stay.


> Yeah, sure, and with LLMs you can do this, and you can do that. But if we're talking about languages and their features, relying on IDE features feels slightly off-topic.

Refacoring tools (such as renaming properties) have been supported by IDEs for decades. And in Typescript specifically, the language is designed with these tools in mind, which are developed and distributed directly by the Typescript team. For all intents and purposes, IDE integration using the Typescript language server is a feature of Typescript.

And if somehow these tools don't work, the compiler will catch it immediately! This means I can refactor with confidence, knowing any type issues will be caught automatically.

It seems like you're vastly overestimating the time and effort it takes to change types in Typescript. In my experience it's something that takes basically no time and effort, and has never caused me any issues or headaches.


You're changing the point though, you claimed "I don't find that dynamic typing reduces the number of places I need to update stuff", which just because your editor makes the change, doesn't suddenly make the change not show up in the diff for you and others. A change is a change, regardless of how it's made, unless you don't keep your code in a SCM that is, which I'm assuming most of us do.

I'm not saying it's hard to change types in TypeScript, I understand that your IDE is connected with the language and they're used together, but again my argument was that having types leads to having to change things in more places. Which is true too, and it's a good thing, it's on purpose, and the tools you use help with that, so yay for that! But it's still more changes, and at least for me it's important to be honest about the tradeoffs our choices leads us to.

As I mentioned earlier, I'm fan of static typing in many situations, just not all of them. And I'm not blind to the negatives they can bring too, I guess I just see more nuance in the static typing vs dynamic debate.


Regardless of how dynamic typing is, the contract being enforced stays the same. It's just less enforced by tools. So with dynamic typing, you will have to change the same amount of code if you want your code to stay correct. The only variation in code changes comes from the annotation for the type system.

> So with dynamic typing, you will have to change the same amount of code if you want your code to stay correct.

No, because if a piece of data is pushed through multiple layers you can just change its type at the source and the destination and not in all the layers the data is pushed through. And you can still be correct.

Imagine you have a thing called target which is a description of some endpoint. You can start with just a string, but at one point decide that instead of string you'd prefer object of a class. In dynamic language you just change the place where it originates and the place where it's used. You don't need to change any spot in 3 layers that just forearded target because they were never forced assumed it's a string.

You can achieve that in staticly typed language if you never use primitive types in your parametrs and return types or if you heavily use generics on everything, but it's not how most people write code.

Tools can help you with the changes, but such refactors aren't usually available in free tools. At least they weren't before LLMs. So the best they could do for most people was to take them on a journey through 3 layers to have them make manual change from string to Target at every spot.


In some type systems, you don't need to change it either. Errors will happens only if you've written code that assumes that `target` is a string. If I write a function with the following signature:

  fn split(str: string) => string[]
And you called it with

const first_el = split(target)[0]

If you decide `target` to suddenly be an object, then the code you wrote is incorrect, because semantically, `split` only makes sense when the argument is a string. Which is why, even with dynamic typing, you'll see that the documentation of a function will state what kind of parameters it expects.

If you a call chain like `fn1 | fn2 | fn3 | fn4 | split`, Then yeah you need to ensure what reaches `split` is in fact a string. If you're against updating fn[1-4]'s signature, let's say that it's harder to find which function needs to change in a dynamic typing systems.

Dynamic typing is useful for small programs and scripts because they are easy to iterate upon. But for longer programs, I'll take static typing anytime.


Yeah, you are right that ease of drilling down values through the layers is balanced by the need to remember which places actually do something with the value.

While I always liked dynamic languages and probably wrote most of my code in them I don't think they are useful anymore. Tooling got great and LLMs need every chance they get of verifying stuff they hallucinated. At this point I wouldn't mind a language that's strict about typing but other things as well as ownership, protocols, mandatory assertions, tests, code coverage, even some formal verification. As long as I don't have to write them, but LLM does and uses them to check its work, I'm really fond of it.


Yeah, tooling for strongly typed languages is way better than 20 years ago. They are getting very being usable.

It’s more work, if it wasn’t there’d be no debate.

SO is actually a great resource to train your LLM on :)

"We've got an egg, why do we still need the chicken, eh?"


Amazing

This reminds me of an adventured died just a few months ago at age of 40 after suffering insult. He has crossed ocean on a rowboat and more.

https://boredofborders.com/adventures/

DeepL Translation of wiki:

Bardel's largest and most notable expeditions involve crossing oceans and traveling around the world without external assistance. On May 4, 2016, he and his traveling companion Gints Barkovskis set out to cross the Atlantic Ocean from Namibia to Brazil. After 142 days, they safely reached the coast of South America, becoming the first two-person crew to cross the Atlantic Ocean in a rowboat. [6] During the voyage, both men encountered serious health problems (vitamin deficiency, skin inflammation) and Barkovskis broke his ribs, but neither wanted to interrupt their journey, and the expedition ended successfully. [6]

After crossing the Atlantic, Bardelis continued his journey in South America and began a new stage in 2018. From Brazil, with the support of Gints Barkovskis, he traveled by tandem bicycle through South America to Lima, Peru, completing the approximately 5,400 km stage in 102 days. [7] Bardelis then set out alone in a rowboat to cross the Pacific Ocean in June 2018. He covered a distance of approximately 26,000 km from South America to Malaysia, spending a total of 715 days on the journey; with this achievement, he became the first person in the world to cross the Pacific Ocean from South America to Asia in a rowing boat. [7] During this sea expedition, he had to overcome several stormy periods and was forced to stop at islands, but in the end, Bardelis became known worldwide as the first ocean rower in this direction. [7]

https://lv.wikipedia.org/wiki/K%C4%81rlis_Bardelis


> This reminds me of an adventured died just a few months ago at age of 40 after suffering insult.

I did not understand what was meant with "suffering insult", so with the help of DeepL and his wikipedia page I could determine that he passed away due to a brain tumour.

An other link:

https://eng.lsm.lv/article/society/society/19.11.2025-farewe...


Not OC, but funny that in my native language "stroke" is "insult" - so I understood that and didn't catch it that in english it doesn't make sense. :)

Woops, translated it wrong. Insult I meant Stroke. But he had stroke earlier.

For such a brave and spirited fellow, it is surprising to learn that he was so sensitive that he passed away from having his character besmirched.

Sad to hear. Just watched his documentary 'Beyond the deep' on Prime this year. Trailer here https://www.youtube.com/watch?v=yFlSp17rTjY

There are also positive news in Dataverse: Environments get some free capacity upgrade: https://licensing.guide/december-2025-dataverse-default-capa...

Well except Google that got sued for US$8.8 Billion because they decided to use specific API signatures but provide their own implementation...?!


What Google did was similar what Microsoft did back in the days. Marketing something as Java, but wasn't Java.


It incredible how far the "Do not evil" marketing won the hearts of computing nerds, Google only got positive karma for doing with Android exactly what Microsoft did with J++.

To this day Android Java is not fully compatible with Java proper, and Kotlin became Google's version of C#.


Come on, that's a completely different story, Google made their own independent SDK using but incompatible with Java. Nobody's arguing you should do that.

Plus last time I checked Oracle lost that lawsuit.


... and Oracle lost


And the lesson is not to trust Oracle.


That list should surely had to prepend "pay off debt, live within your means"

Listening to Dave Ramsey on YT gets me amazed on how some people can be so irresponsible and accumulate debt on credit cards and cars they can't afford.


I firmly believe if people in this country were smart with their money in the way Dave Ramsey preaches, the entire service sector would collapse.


Is this "just because" fun project or made out of a need?

Disclaimer mentions:

No warranty provided

Use at your own risk

I guess the same can be said about the OS itself :)


Are there any software project having any warranties?


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: