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

> Especially when the US is a net exporter from oil and could conceivably protect domestic industries from the same?

The oil companies would likely be extremely unhappy if they were not permitted to export their products.


True I mean it’s high risk and maybe dumb, but I wouldn’t put it past the current thought leaders to turn against traditional free market ideology.

>> tariffs... too directly put the blame on the president. Would starting a war with Iran... be a more solid mechanism?

War puts the blame on the president even more directly.

>> Especially when the US is a net exporter from oil and could conceivably protect domestic industries from the same?

The US is a huge net importer of goods. The oil surplus is rather small, has been recorded only for the last 3 years and it can't meaningfully change the US balance of trade.

> shocking energy and transportation prices, raising the costs of exports from every other country... and the US could conceivably protect domestic industries from the same?

Nothing will be protected, quite the opposite, the US will be the country hardest hit by inflation because, given the huge net imports, we are the country that benefits the most from unimpeded trade and lower cost of production in other countries.

Trumps tariffs didn't decrease the trade deficit, in fact the deficit for 2025 was significantly higher than the pre-covid 2019. The deficits for Feb and Mar 2025 were the highest monthly deficits in history, beating the previous records by almost 100%.

>> Let’s say your goal was to reduce globalization

"reducing globalization" is a meaningless term, reducing the standard of living is what matters, choking international trade will cause higher reduction in the US than in other countries.

> I mean it’s high risk and maybe dumb, but I wouldn’t put it past the current thought leaders to turn against traditional free market ideology.

"Ideology" is a fig leaf, what matters is the money and power in the hands of the most special interest groups, it's a small club and you ain't in it.


Fun quote from the OP:

> But here’s the part that really gets us. At our CORE, our instinct is to only email folks when we actually have something fun to share. A big release, something we’re excited about, news worth your time.

I would prefer not to give my email address to a company that thinks that this should give them a good email reputation. If you email me because you are excited and I’m not, I probably think of it as spam.


Every single spam email ever sent is from someone who has “something fun to share” that they’re “excited about”.

If that’s really what you’re doing, show the open/click rates well above 80%.


I don't mind if a company sends me emails if I gave them my email address. As long as, when I click "unsubscribe" to the email, they stop. I don't want to have to go log back into their system and unsubscribe. I just want to click the unsubscribe button and have it be done - forever, not just until they add a new category for email.

I have a fair number of companies that send me emails (because I signed up for their service) on a "slow" basis (ie, when they have something interesting.. not just "every week, so you don't forget us). I don't mind those. Sometimes I read them, sometimes I don't. I don't unsubscribe and I don't mark them as spam.

I'm not saying you should be the same as me. I _am_ saying that, just because _you_ don't like it, doesn't make them "clearly in the wrong". Because there are people that feel like the way they are acting is reasonable.


> log back into their system and unsubscribe

FYI, requiring logging in to unsubscribe is a violation of the CAN-SPAM Act in the U.S., I just mark those as spam if they don't allow one-click unsubscribes.


I kinda don't mind period, since I just mark them as spam. As OP is finding out though they're in denial

When you mix different liquids, all manner of complex things happen to their vapor pressure vs temperature curves.

> the Teflon chemical

Teflon is PTFE, which is fully fluorinated but is also very much a plastic: it’s a highly unreactive solid at reasonable temperatures (which sadly do not include temperatures commonly encountered on stoves).

By “the Teflon chemical” are you perhaps referring to the various nasty liquid, water-soluble surfactants commonly used in factories that make or process PTFE? Those include PFOA, PFOS, and the newer and not obviously any safer “GenX” compounds.


Yes, they are referring to PFOA/PFOS; they're talking about PFAS which is the broad class of chemical compounds that includes PFOA/PFAS. And PFAS are not plastics.

One of my favorite bits of hardware is a UPS. I’ve played with several over the years, from fancy server-grade rack-mount APC stuff to inexpensive edge stuff. Without exception, downtime is increased by use of a UPS. I used to plug a server with redundant PSUs into the UPS and the wall so it could ride out UPS glitches.

Even today, a UPS that turns itself back on after power goes out long enough to drain the battery and is then restored is somewhat exotic. Amusingly, even the new UniFi UPSes, which are clearly meant to be shoved in a closet somewhere, supposedly turn off and stay off when the battery drains according to forum posts. There are no official docs, of course.


Sounds like crappy UPSes. Even the cheap old used eBay Eaton UPSes I have in my homelab have a setting for "Auto restart" and the factory default setting is "enabled".

But even rackmount UPSes are more of an "edge" sort of solution. A data center UPS takes up at least a room.


I assume that datacenters UPSes are better, but I’ve never used one except as a consumer of its output.

But I’ve had problems with UPSes that advertise auto-restart but don’t actually ship with it enabled. And that fancy APC unit was sold by fancy Dell sales people and supported directly by real humans at APC, and it would still regularly get mad, start beeping, and turn off its output despite its battery being fully charged and the upstream power being just fine (and APC’s techs were never able to figure it out either).


> I assume that datacenters UPSes are better [...]

I don't know about specific datacenter models, but in our colocation there are humans available 24/7. So the UPS might not start after failure, but there's a human to figure it out.


Most (all?) decent datacenters also have generators on site, and the intent is that the UPS will never run out of charge. So the fully-discharged case is an error and it might be intentional to require intervention to recover.

Yeah, some people treat UPSes as "backup power" but that's not really what they're intended for. Their intended purpose is to bridge the gap during interruptions... either to an alternative power source, or to a powered-off state.

Sure, but when you stick a UPS in the closet to power your network or security cameras or whatever for a little while if there is a power interruption, you expect:

a) If the power is out too long for your UPS (or you have solar and batteries and they discharge overnight or whatever) that the system will turn back on when the power recovers, and

b) You will not have extra bonus outages just because the UPS is in a bad mood.


I completely agree with B. But alas, people love buying shitty cheap UPSes.

But A is along the lines of the misconception that I'm referring to... There should be no such thing as "the power being out too long for your UPS". A UPS isn't there to give you a little while to ignore the problem, it's there to give you time to address it. Either by switching to another source of power, or to power off the equipment.

Now, the reason that every UPS that supports auto-restart has it as a configurable option, is because you often don't want to do this for many reasons, e.g.:

* a low SOC battery could not guarantee a minimum runtime for safe shutdown during a repeated outage

* a catastrophic failure (because the battery shouldn't be dead) could be an indication of other issues that need to be addressed before power on

* powering on the equipment may require staggering to prevent inrush current overload

The whole use case of "I'm using the UPS to run my equipment during an outage" is kind of an abuse of their purpose. It's commonly done, and I've done it myself. But it's not what they're for.

But also, if you want a UPS that auto-restarts -- they exist -- but you get what you pay for.


Some of these is IMO a bit silly:

> a low SOC battery could not guarantee a minimum runtime for safe shutdown during a repeated outage

A lot of devices are unconditionally safe to shut down. Think network equipment, signs, exit lights, and well designed computers.

> a catastrophic failure (because the battery shouldn't be dead) could be an indication of other issues that need to be addressed before power on

This is such a weird presumption. Power outages happen. Long power outages happen. Fancy management software that triggers a controlled shutdown when the SOC is low might still leave nonzero remaining load. In fact, if you have a load that uses a UPS to trigger a controlled shutdown, it’s almost definitional that a controlled shutdown is not a catastrophe and that the system should turn back on eventually.

All of your points are valid for serious datacenter gear and even for large server closets, but for small systems I think they don’t apply to most users, and I’m talking about smaller UPSes.


> > a low SOC battery could not guarantee a minimum runtime for safe shutdown during a repeated outage

> A lot of devices are unconditionally safe to shut down.

Yeah, but that doesn't mean you want to expose them to brownout conditions when your UPS is depleted. If the power is continuing to flip on and off, it's better to just leave it off if you don't have the battery to prevent even short interruptions. A good UPS can do this automatically for you. A cheap one will just stay off and let you respond to the outage.

> This is such a weird presumption.

It wasn't a presumption I was making for all users -- but an example of why some users might not want auto-restart as a feature. Of course, if you want auto-restart as a feature, you can buy a UPS that has it as a feature and turn it on.

> they don’t apply to most users, and I’m talking about smaller UPSes.

Yeah, I know the situation: Someone has a network closet on a budget with a UPS they've sized to get them a few minutes of runtime. They put a UPS on the BOM because it checks a box. So they buy a low-end UPS that either doesn't have the feature, or it doesn't work right.

The solution is just to buy the right UPS for the thing they were trying to do... and test it.


GPT 5.4 is remarkably good at figuring out machine code using just binutils. Amusingly, I watched it start downloading ghidra, observe that the download was taking a while, and then mostly succeed at its assignment with objdump :)

A pilot light is tricky: in typical designs, it needs to heat a thermocouple enough to produce enough current to drive a solenoid to allow the rest of the flame to ignite. Thermocouples are outrageously inefficient.

The pilot lights I’m familiar with just light the rest of the flame directly since they are burning already - turning on the fuel is all that is required. What systems uses a thermocouple and a solenoid?


Any modern country with safety regulations will require a thermocouple in the loop if there is a pilot light on the appliance. The last non thermocouple appliance I saw was an industrial kitchen stove, but it had been modified for propane, and I suspect that the guy who did it ripped out the safety stuff.

Every factory appliance will gate the full gas flow behind the activation of a the thermocouple.

When you push and hold a dial or button to get a pilot lit, what you are actually doing is bypassing the thermocouple safety until it gets to temperature. If you release the “hold to light” knob too soon your pilot will go out since the thermocouple needs ~10 seconds to get to temp.


The only commercial kitchen stove I interact with on a somewhat regular basis is a miserable piece of crap. It has multiple pilot lights, some of which go out frequently and stink up half the building with unburnt fuel. I suspect that just the pilot lights consume $50-$100/month of natural gas.

Stoves seem to be somehow special in safety regulations. I guess regulators assume that they are never operated unattended, so they tend to have no real built in safety features. Both commercial and residential stoves will happily operate unlit at full power.


I've got a Honeywell digital controller on my hot water heater. It's powered by the thermocouple. It can make troubleshooting a lot easier because it has flashing lights for diagnostics.

It’s extremely common for the mechanism that only allows the fuel to be turned on if the pilot is lit to work by having a thermocouple in the pilot flame. Some of these also power the controls (thermostat, for example) and some don’t.

Yeah blowing yourself up with a gas leak is common enough when you're working on these systems that it's pretty important to have an interlock there.

These services are designed such that security sort of depends on reviewing the programs that are allowed to run. Microsoft, Google and Apple all do this. It adds expense, annoyance, limitations, and really very little security.

The contrasting approach, where one designs a platform that remains secure even if the owner is allowed to run whatever software they like, may be more complex but is overall much better. There aren’t many personal-use systems like this, but systems like AWS take this approach and generally do quite well with it.


> The contrasting approach, where one designs a platform that remains secure even if the owner is allowed to run whatever software they like

There's a lot that one can gripe about Amazon as a company about, but credit where credit is due -- their inversion of responsibility is game-changing.

You see this around the company, back to their "Accept returns without question" days of mail order.

Most critically, this inversion turns customer experience problems (it's the customer's problem) into Amazon problems.

Which turns fixing them into Amazon's responsibility.

Want return rates to go down because the blanket approval is costing the company too much money? Amazon should fix that problem.

Too often companies (coughGoogleMicrosoftMetacough) set up feedback loops where the company is insulated from customer pain... and then everyone is surprised when the company doesn't allocate resources to fix the underlying issue.

If false positive account bans were required to be remediated manually by the same team who owned automated banning, we'd likely see different corporate response.


Hmm, they seem to have chosen to avoid names to the choices in the union, joining C++ variants and (sort of) TypeScript unions: unions are effectively just defined by a collection of types.

Other languages have unions with named choices, where each name selects a type and the types are not necessarily all different. Rust, Haskell, Lean4, and even plain C unions are in this category (although plain C unions are not discriminated at all, so they’re not nearly as convenient).

I personally much prefer the latter design.


Hi there! One of the C# language designers here, working on unions. We're interesting in both forms! We decided to go with this first as felt there was the most value here, and we could build the named form on top of this. In no way are we thinking the feature is done in C#15. But it's part of our ongoing evolution.

If you're interested, i can point you to specs i'm writing that address the area you care about :)


I think it would be a considerable improvement to allow duck-typing over the top. implicitly defined interface that includes exact member matches, something like that.

Hi! Love to see that C# language designers are here on HN :)

Just wanted to add just another opinion on a few things.

I think many people already mentioned it, but I also don't feel to good about non-boxed unions not being the default. I'd personally like the path of least resistance to lead to not boxing. Having to opt-in like the current preview shows it looks like a PITA that I'd quickly become tired of.

Also, ad-hoc union types could be really nice. At least in Python those are really nice, stuff like `def foo(x: str | int)` is just very nice. If I had to first give this union type a name I'd enjoy it way less.

But I'm aware that you are trying your best to find a good trade-off and I'm sure I don't know all the implications of the things I wish you'd do. But I just wanted to mention those to have another data point you can weigh into your decision process.


> Having to opt-in like the current preview shows it looks like a PITA that I'd quickly become tired of.

My belief is that we will have a `union struct` just like we have `record` and `record struct`. Where you can simply say you want value-type, non-boxing, behavior by adding the `struct` keyword. This feels very nice to me, and in line with how we've treated other similar types. You'll only have to state this on the decl point, so for each union type it's one and done.


That actually sounds like a promising idea. Thanks for putting so much thought into this.

> I think many people already mentioned it, but I also don't feel to good about non-boxed unions not being the default. I'd personally like the path of least resistance to lead to not boxing. Having to opt-in like the current preview shows it looks like a PITA that I'd quickly become tired of.

The problem is that the only safe way for the compiler to generate non-boxed unions would require non-overlapping fields for most value types.

Specifically the CLR has a hard rule that it must know with certainty where all managed pointers are at all times, so that the GC can update them if it moves the referenced object. This means you can only overlap value types if the locations of all managed pointers line up perfectly. So sure, you can safely overlap "unmanaged" structs (those that recursively don't contain any managed pointers), but even for those, you need to know the size of the largest one.

The big problem with the compiler doing any attempt to overlap value types is that if the value types as defined at compile time may not match the definitions at runtime, especially for types defined in another assembly. A new library version can add more fields. This may mean one unmanaged struct has become too big to fit in the field, or that two types that were previously overlap compatible are not anymore.

Making the C# compiler jump though a bunch of hoops to try to determine if overlapping is safe and even then leaving room for an updated library at runtime to crash the whole things means that the compiler will probably never even try. I guess the primitive numeric types could be special cased, as their size is known and will never change.


Not OP but I would love to check that out

Sure, as an example: https://github.com/dotnet/csharplang/blob/main/meetings/work...

Again, very rough. We go round and round on things. Loving to decompose, debate and determine how we want to tackle all these large and interesting areas :)


Nice! (Well, nice the first time I loaded the page, but GitHub appears to be rocking maybe 90% uptime today and I can’t see it anymore.)

I admit that I haven’t actually used C# in 20 years or so.


Oh I’m very happy to hear this is being worked on!

Careful not to mix unions with sum types, though. The key distinction is that the latter are disjunct sets, even if you "sum" together the same type twice, you can always tell which "way" you went.

An example that may show the difference: if you have a language with nullable types, then you basically have a language with union types like String|Null, where the Null type has a single value called `null` and String can not be null.

Now if you pass this around a function that itself may return `null`, then your type coalesces to String|Null still (you still get a nullable string, there is no doubly nullable). This is not true for Maybe/Option whatever you call types, where Some(None) (or Optional.of(Optional.empty())) is different from None only.

Rich Hickey once made a case that sort of became controversial in some FP circles, that the former can sometimes be preferred (e.g. at public API surfaces), as in for a parameter you take a non-nullable String but for returns you return a String|Null. In this case you can have an API-compatible change widening the input parameters' type, or restricting the return type - meanwhile with sum types you would have to do a refactor because Maybe String is not API compatible with String.


> Careful not to mix unions with sum types, though. The key distinction is that the latter are disjunct sets, even if you "sum" together the same type twice, you can always tell which "way" you went.

This is a really good point. I'd love to be able to have a sum type of two strings ("escaped" and "unescaped"); or any two kinds of the same type really, to model two kinds of the same type where one has already passed some sort of validation and the other one hasn't.

Edit to add: I figure what I want is for enums to be extended such that different branches are able to carry different properties.

Edit again (I should learn to think things through before posting. sorry): I suppose it can be faked using a union of different wrapper types, and in fact it might be the best way to do it so then methods can take just one of the types in arguments and maybe even provide different overloads.


Not sure, but I think C++ actually does allow std::variant with multiple choices using the same type. You might not be able to distinguish between them by type (using get<Type>()), but you can by position (get<0>(), get<1>(), ...)

I haven’t tried this, and I don’t intend to, because visitors and similar won’t work (how could they?) and I don’t want to have to think about which is choice 2 and which is choice 7.

I think GP is talking about name-of-field access, not index access or name-of-type

The C and Rust union types are extremely sharp blades, enough so that I expect the average Rust beginner doesn't even know Rust has unions (and I assume you were thinking of Rust's enum not union)

I've seen exactly one Rust type which is actually a union, and it's a pretty good justification for the existence of this feature, but one isn't really enough. That type is MaybeUninit<T> which is a union of a T and the empty tuple. Very, very, clever and valuable, but I didn't run into any similarly good uses outside that.


Unions can be used as a somewhat safer (not safe by any means but safer), more flexible, and less error-prone form of transmute. Notably you can use unions to transmute between a large type and a smaller type.

That is essentially the motivation, primarily in the context of FFI where matching C's union behaviour using transmute is tricky and error-prone.


There are rare cases where all attributes of the C union are valid at the same time. Say you have a 32-bit RGBA color value and you want to access the individual 8 bit values. You can make a union of an 32 bit int and a struct that contains 4x 8 bit integers.

Also you can manually tag them and get s.th. more like other high level languages. It will just look ugly.


Yes. I once wanted C unions limited to fully mapped type conversions, where any bit pattern in either type is a valid bit pattern in the other. Then you can map two "char" to "int". Even "float". But pointer types must match exactly.

If you want disjoint types, something like Pascal's discriminated variants or Rust's enums is the way to go. It's embarrassing that C never had this.

Many bad design decision in C come from the fact that originally, separate compilation was really dumb, so the compiler would fit in small machines.


In Rust's case, union types should only be used for FFI with a C ABI.

As for C, it is a sharp blade on its own.


I do not agree. MaybeUninit<T> is without any doubt more valuable than the C FFI use

I can't even think of any prominent C FFI problems where I'd reach for the union's C representation. Too many languages can't handle that so it seems less useful at an FFI edge.


OS APIs for one, at least there are some Win32 calls that take unions if I remember correctly.

One of the reasons .NET had Managed C++, replaced by C++/CLI (nowadays C++20 compliant, minus modules), is exactly that P/Invoke (and RCW/CCW) cannot represent everything.

Which they don't want to expose on .NET type system directly.


FYI small string optimizations are generally implemented using unions.

In Rust? The two I'm big fans of, CompactString and ColdString do not use unions although historically CompactString did so and it still has a dependency on smallvec's union feature

ColdString is easier to explain, the whole trick here is the "Maybe this isn't a pointer?" trick, ColdString might be a single raw pointer onto your heap with the rest of the data structure at the far end of the pointer, this case is expensive because nothing about the text lives inline, but... the other case is that your entire text was hidden in the pointer, on modern hardware that's 8 bytes of text, at no overhead, awesome.

CompactString is more like a drop-in replacement, it's much bigger, the same size as String, so 24 bytes on modern hardware, but that's all SSO, so text like "This will all fit nicely" fits inline, yet the out-of-line case has the usual affordances such as capacity and length in the data structure. This isn't doing the "Maybe this isn't a pointer?" trick but is instead relying on knowing that the last byte of a UTF-8 string can't have certain values by definition.


My bad I thought it still used `union`s. I guess I'm not very up to date

I realise that I don't do the best job of explaining ColdString here. After all most 8 byte strings of UTF-8 text could equally be a pointer so, why can this work?

All ColdStrings which look like 8 bytes of UTF-8 text really are 8 bytes of UTF-8 text, just the type label on those 8 bytes isn't "[u8; 8]" an array of 8 bytes but instead "mut *u8" a raw pointer. "Validate" for example is 8 bytes of ASCII, thus UTF-8, and Rust is OK with us just saying we want a pointer on a 64-bit machine with those bytes. It's not a valid pointer, but it is a pointer and Rust is OK with that, we just need to be careful never to [unsafely] dereference the pointer because it's invalid

OK, so there are two cases left: First, what if there are fewer bytes of text? Zero even?

Since there are fewer than 8 bytes of text we can use the whole first byte to signal how many of the remainder are text, we use the UTF-8 over-long prefix indicator in which the top five bits of the byte are all set, bytes 0xF8 through 0xFF for this, there are eight of these bytes corresponding to our 8 lengths 0 through 7 inclusive. Because it's over-long this indicator isn't itself a valid UTF-8 prefix. Again we can pretend this is a pointer while knowing it's invalid.

Lastly, the seemingly trickiest problem, what if the string didn't fit inline? We use a heap allocation to store the text prefixed by a variable size integer length and we insist this allocation is aligned to 4 bytes. This means a valid pointer to our allocation has zeroes for the bottom two bits, then we rotate that pointer so those bottom two bits are at the top of the first byte position (depending on machine word layout) and we set the top bit. This is now always invalid UTF-8 because it has the continuation marker - the top bit is set but the next is not, which cannot happen in the first byte of any UTF-8 text, and so our code can detect this and reverse the transformation to get back a valid pointer using the strict provenance APIs if this marker is present.

This type is tomtomwombat's idea, credit to them:

https://github.com/tomtomwombat/cold-string*


> The C and Rust union types are extremely sharp blades

Sure, but the comparable Rust feature is enum, not union.


I would love to see a page that has cross-language comparisons of how different structures work. Eg “unions: differences between langs. Enums: …” while grouping together the different design choices, as you do in this one case.

I suppose an LLM could do a pretty good job at this.


I think Zig does a very good illustration of this distinction. They separate:

- enum: essentially just a typed uint tag collection

- union: the plain data structure that can contain any of several types

- tagged union: combines enums and unions, so you can dispatch on its tag to get one of the union types

Read from this section and they appear in order:

https://ziglang.org/documentation/master/#enum


Keep in mind that VSCode’s own security story is beyond poor. Even if the container runtime perfectly contains the container, VSCode itself is a hole you could drive a truck through.

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

Search: