HNHacker News
TopNewBestAskShowJobs

chowells

3,851 karma · joined April 14, 2013

submissionscomments
chowells··on I don't think AGI is right around the corner
If you think it can't be done with a countable state space, then you must know some physics that the general establishment doesn't. I'm sure they would love to know what you do.

As far as physicists believe at the moment, there's no way to ever observe a difference below the Planck level. Energy/distance/time/whatever. They all have a lower boundary of measurability. That's not as a practical issue, it's a theoretical one. According to the best models we currently have, there's literally no way to ever observe a difference below those levels.

If a difference smaller than that is relevant to brain function, then brains have a way to observe the difference. So I'm sure the field of physics eagerly awaits your explanation. They would love to see an experiment thoroughly disagree with a current model. That's the sort of thing scientists live for.

chowells··on Corrected UTF-8 (2022)
Forbidding \r\n line endings in the encoding just sort of sinks the whole idea. The first couple ideas are nice, but then you suddenly get normative with what characters are allowed to be encoded? That creates a very large initial hurdle to clear to get people to use your encoding. Suddenly you need to forbid specific texts, instead of just handling everything. Why put such a huge footgun in your system when it's not necessary?
chowells··on July 5, 1687: When Newton explained why you don't float away
It's how a lot of science was written, and knowing that makes strong Sapir-Whorf a really funny joke. We didn't derive our ideas about science from our language. Developing our ideas of science shaped our language so it could communicate them efficiently.

(Weak Sapir-Whorf is still a perfectly fine observation, but it's a lot less predictive as a hypothesis.)

chowells··on Lens: Lenses, Folds and Traversals
That might be a strong argument in many languages, but in Haskell you really don't need to memorize operator precedence. In nearly every case, the types tell you the precedence. They don't literally, but most expressions only type check in one particular parse tree.

As a result, you just don't think about precedence when reading code. If you assume the code type checked correctly, you know that it all just makes sense. You don't need to create a parse tree. You just trust.

(Actually, this is the huge advantage of Haskell in most every case. You don't need to understand everything. You just trust that it does what makes sense, and you're right. The compiler enforces it.)

chowells··on Lens: Lenses, Folds and Traversals
I strongly recommend using the lens operators. They are uniformly named such that you can trivially identify their behavior based on their lexical construction, and using them reduces mental parsing overhead significantly.

For the former assertion: ^. means "get a single result". ^.. means "get multiple results". ^? means "get zero or one result". ^@.. means "get multiple results, along with their indices". <<|>~ means "modify a value by combining the target with the |> operator from Snoc, then return a tuple of the old target value and the full structure including the combined value". There is a tiny language in the pattern of operator names, and it's worth the 3 minutes of work it takes to learn it.

And as a reward for learning it, you get to write expressions with far fewer parentheses. This is a massive win. Parenthesized expressions introduce a miserable minigame during reading, where you have to properly match each paren to its correct partner keeping a mental stack to handle nesting. By contrast, the lens operators give you the far simpler mental parsing task of separating the optic, the input, and the operation on the input. There's no nesting involved. The process is a simple visual scan that doesn't require keeping a mental stack. It's a lot easier to quickly read and comprehend.

About the only thing you lose is the ability to easily read code out loud. I don't limit myself to thinking in sounds, but I guess for some people it's important to communicate code out loud. For those kinds of pedagogical purposes, I guess it's ok to pass on the operators. But for code I'm going to work with over a long period of time I'd much rather have the readability advantages of the operators.

chowells··on Don’t use “click here” as link text (2001)
> They don't try to be helpful, they only do exactly what they are told.

This is how software should work. Attempting to be "helpful" usually makes things worse. Doing exactly what it's told makes it predictable and usable.

Just look at how much of the HTML 5 spec is a nightmare of parsing rules for handling malformed SGML. Look at how it got there - all the invocations of Postel's law justifying attempting to handle malformed input in "helpful" ways, until things were eventually such a compatibility nightmare that a new spec was created to give precise rules for parsing every single input the same way. "Helpful" was specified away, because it was so broken.

Now if only screen readers provided consistency in following rules, too. They're not in a great state, but your attempted solution is worse.

chowells··on Why JPEGs still rule the web (2024)
They're just for different jobs.

JPEG is lossy, in ways that were initially optimized for photographs. The details it loses are often not details photographs are good at providing in the first place. As the upside for losing some data, it gets to pick the data it gets to compress, and it chooses it in such a way as to minimize the size of the compressed data.

PNG is a lossless format. It's practically mandatory when you need 100% fidelity, as with icons or other graphics that are intended to have high contrast in small areas. It's able to optimize large areas of the same color very well, but suffers when colors change rapidly. It's especially unsuitable for photographs, as sensor noise (or film grain, if the source was film) create subtle color variations that are very difficult for it to encode efficiently.

You basically never have a situation where either one is appropriate. They are for different things, and should be used as such.

chowells··on Frequent reauth doesn't make you more secure
Note that modern web browsers do not define a session end as "when you close your browser" unless you hunt for and enable settings to make them do that. Session cookies will happily survive a browser restart by default, because browser makers know that most users don't consider closing their browser to be ending any kind of session.
chowells··on Why we still can't stop plagiarism in undergraduate computer science (2018)
If you really want to dig into it, the problem is that there are a huge number of students who don't know anything at all about how or why to learn. If they actually wanted to learn and understood how exercises help them, the fact that they're all well-known problems really wouldn't be a big deal.

But universities are businesses now. They produce diplomas in exchange for money, and interrupting that with details like "this student shouldn't be here" costs them money they can't afford to lose.

chowells··on Beware of Fast-Math
Do you believe that the way the REPL prints a number is the way it's stored internally? If so, explaining this will be a fun exercise:

    $ python3
    Python 3.11.2 (main, Apr 28 2025, 14:11:48) [GCC 12.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> a = 0.1
    >>> a + a + a
    0.30000000000000004
By way of explanation, the algorithm used to render a floating point number to text used in most languages these days is to find the shortest string representation that will parse back to an identical bit pattern. This has the direct effect of causing a REPL to print what you typed in. (Well, within certain ranges of "reasonable" inputs.) But this doesn't mean that the language stores what you typed in - just an approximation of it.
chowells··on What Is the Difference Between a Block, a Proc, and a Lambda in Ruby? (2013)
Ah, you're right. They do have observably different behavior. But I can't even close an open file handle after a break. That's still pretty miserable.
chowells··on What Is the Difference Between a Block, a Proc, and a Lambda in Ruby? (2013)
No, return exiting the enclosing function scope from a block is the special case that's there to resolve an edge case.

Blocks should be nothing special. They're anonymous functions that capture the environment mutably. The only new part is all the special bits added to handle the weird edge cases that they're trying to pretend don't exist.

chowells··on What Is the Difference Between a Block, a Proc, and a Lambda in Ruby? (2013)
Given that you completely ignored what I said I wanted to do and gave an answer for some other question, I'm pretty sure it's more complicated than you think.

I want to write a method that takes a block and distinguishes between next and break, exactly like the methods of enumeration do. It's obviously possible because a super common interface does it.

Last time I looked, that interface does it by being written in native code that interfaces with the interpreter. That is, it's not part of the language semantics. It's a special case with weird rules unlike what anything else gets to do.

Or at least it was. Maybe the language has actually made it accessible since then, but I'm not optimistic. That's not the ruby way.

chowells··on For algorithms, a little memory outweighs a lot of time
Oh, that's not a problem. Just cache the retrieval lookups too.
chowells··on What Is the Difference Between a Block, a Proc, and a Lambda in Ruby? (2013)
Flexible in a way, sure. But non-locality is generally a bad property, not good. Adding it is a workaround for all the enumeration methods using blocks in a way that makes people think they're weird looping syntax instead of a fundamentally different idea.

People want to do early returns from looping over a collection, so take the easy solution of adding more messy language semantics instead of finding a semantically simple solution instead. (For that matter, have fun working out the semantics of break and next when used in a block that isn't an argument to an enumeration method. How do you as a method author opt in to distinguishing between the two after yielding to a block?)

This is generally the case with Ruby everywhere. Why does that thing have an edge case with weird semantics? To work around the edge case with weird semantics somewhere else. It's all fine if you want to just try things until something works. But if you want to really understand what's going on and write code that's a first-class participant in the language features, it gets really frustrating to try to deal with it all.

chowells··on Project Verona: Fearless Concurrency for Python
That's the wrong distinction, and bringing it up causes pointless arguments like are in the replies.

The right distinction is that assemblers and compilers have semantics and an idea of correctness. If your input doesn't lead to a correct program, you can find the problem. You can examine the input and determine whether it is correct. If the input is wrong, it's theoretically possible to find the problem and fix it without ever running the assembler/compiler.

Can you examine a prompt for an LLM and determine whether it's right or wrong without running it through the model? The idea is ludicrous. Prompts cannot be source code. LLMs are fundamentally different from programs that convert source code into machine code.

This is something like "deterministic" in the colloquial sense, but not at all in the technical sense. And that's where these arguments come from. I think it's better to sidestep them and focus on the important part: compilers and assemblers are intended to be predictable in terms of semantics of code. And when they aren't, it's a compiler bug that needs to be fixed, not an input that you should try rephrasing. LLMs are not intended to be predictable at all.

So focus on predictability, not determinism. It might forestall some of these arguments that get lost in the weeds and miss the point entirely.

chowells··on If nothing is curated, how do we find things
Yes, people noticed it's good. But that's not how I heard about the game. That's not how anyone in the three separate groups of friends I heard about the game from heard about it. In fact, the only person I knew who really follows that sort of stuff is the only person I know who wasn't interested.

I think you're confusing cause and effect. If you look at steam's concurrent player counts, you see that the number of concurrent players kept increasing for the first 10 days after the game's release. That's not consistent with curators instructing people to buy a game at release. That's consistent with massive word-of-mouth spread. Everyone is talking about it and rating it highly because it's good, not because they were told to.

https://steamdb.info/app/1903340/charts/

chowells··on If nothing is curated, how do we find things
I don't really disagree with the idea that there's value in curation. And I even think there's some value in gatekeeping. Sometimes, at least.

But the timing is really funny here, given the massive success Clair Obscur: Expedition 33 is currently experiencing. People have found this game - and it's not by curation. It's by massive word of mouth, as people who try the game tend to tell all their friends about it. In the case where something is really good, people find out about it without curators.

Curators are good for finding some stuff. But the ones so good that everyone talks about? You'll find them anyway.

chowells··on The birth of AI poker? Letters from the 1984 WSOP
That's not exactly true. It's a non-trivial but not exactly difficult task to design a fair shuffling cryptographic protocol that every participant can validate after the fact.

On the other hand, that still doesn't prevent cheating in the form of the server providing information to some participants via a different channel. There's nothing cryptography can say about out-of-band communications.

So maybe fair shuffling is cute but ultimately pointless.

chowells··on Stringly Typed
> IIRC it has something to do with how they both descend from Object...

It's far less interesting than that. The truth is that the symbol + means a wide variety of different things in the language, and it uses compile-time type information to select exactly which of those things it means. In the case where either operand is a string, it means string concatenation, with string conversion for a non-string operand if one exists.

That specific conversion part is the only thing that cares that stuff descends from Object. The conversion algorithm is "call ToString() and let dynamic dispatch sort it out."

(For completeness, the other meanings are various forms of addition, but adding two doubles is a different machine instruction than adding two floats. It really does still need to use type information to figure out which of those operations it is.)

chowells··on As an experienced LLM user, I don't use generative LLMs often
With concurrency, they still might get it wrong the rest of the summer. It's a hard topic. But at least they might learn they need to ask for feedback when they're doing that looks similar to stuff that's previously caused problems.
chowells··on The cat that wouldn't die
But the whole point is that such a superposition is never observable. Any way of detecting it would cause it to collapse into one specified state. The only way to distinguish it from a non-quantum system is that it can be linked statistically to another quantum system. And even then, you're still only going to observe the same set of outcomes you'd see otherwise. The quantum part affects only the distribution of those outcomes.
chowells··on Programming languages should have a tree traversal primitive
You know, if Haskellers already have that functionality, maybe it's less that they're smug and more that they have already solved the problem. Do you call someone smug when you complain about being freezing and they invite you in out of the cold?
chowells··on Programming languages should have a tree traversal primitive
Traversable and lenses are very closely linked. If you go to the original paper leading to Traversable [1] and read through it, it feels basically identical to reading through the parts of the lens library that lay down the core abstractions and the laws implementations must follow if you want to be able to blindly manipulate them. In fact, the traverse function is a Traversal, and so fits trivially into the lens ecosystem.

[1] https://www.cs.ox.ac.uk/jeremy.gibbons/publications/iterator...

chowells··on Why Pale Blue Dot generates feelings of cosmic insignificance
Ok, why are you acting like you're contradicting OP when the two viewpoints necessarily go together?

If the rest of the universe cares about us, we need to live our lives for the rest of the universe. If we're cosmically insignificant, then what's here and now is what matters, and what we have to live for.

chowells··on Can we still recover the right to be left alone?
What? "Dominion"? What are you on about? What is the moral and rational basis of this supposed authority?
chowells··on Show HN: I built a Ruby gem that handles memoization with a ttl
Does the memory model guarantee that double-check locking will be correct? I don't actually know for ruby.
chowells··on Show HN: I built a Ruby gem that handles memoization with a ttl
No, Ruby is more strict than that. Only nil and false are falsely.
chowells··on Android phones will soon reboot themselves after sitting unused for three days
Everything except a very minimal core is kept on an encrypted partition. Until the password is provided, most things can't launch.
chowells··on TLS certificate lifetimes will officially reduce to 47 days
So what you're saying is that you actually understand the identity portion is critical to how the web is used and you're just cranky. It's ok. Take a walk, get a bite to eat. You'll feel better.
← PreviousPage 6 of 33Next →