<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: tomn</title><link>https://news.ycombinator.com/user?id=tomn</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Tue, 14 Apr 2026 20:24:04 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=tomn" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by tomn in "The Effect of Noise on Sleep"]]></title><description><![CDATA[
<p>Bullets are a bad example because they have multiple properties which makes them much harder to localise than many other sounds.<p>I'm pretty sure most people can localise a vehicle emitting broadband noise (engine or white reversing sound) in the conditions that matter.</p>
]]></description><pubDate>Sat, 28 Jun 2025 01:41:24 +0000</pubDate><link>https://news.ycombinator.com/item?id=44401760</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=44401760</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=44401760</guid></item><item><title><![CDATA[New comment by tomn in "The Effect of Noise on Sleep"]]></title><description><![CDATA[
<p>> They have to be loud enough to be heard through hearing protection.<p>It's kind of a nit-pick, but this is not really true.<p>Very approximately, you will perceive a sound if it is above your threshold of hearing, and also not masked by other sounds.<p>If you're wearing the best ear defenders which attenuate all sounds by about 30dB, and you assume your threshold of hearing is 10dBSPL (conservative), any sound above 40dBSPL is above the threshold of hearing. That's the level of a quiet conversation.<p>And because your ear defenders attenuate all sounds, masking is not really affected -- the sounds which would be masking the reversing beepers are also quieter.<p>There are nuances of course (hearing damage, and all the complicated effects that wearing ear defenders cause), but none of them are to the point that loud reversing noises are required because of hearing protection -- they are required to be heard over all the other loud noises on a construction site.<p>> The utility of having a backup beeper or any noise making device on that site is thus zero.<p>The inverse square law says otherwise; on site the distances will be much more apparent.</p>
]]></description><pubDate>Sat, 28 Jun 2025 01:33:29 +0000</pubDate><link>https://news.ycombinator.com/item?id=44401723</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=44401723</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=44401723</guid></item><item><title><![CDATA[New comment by tomn in "Jokes and Humour in the Public Android API"]]></title><description><![CDATA[
<p>looking around a bit, it's used as an example in the documentation:<p><a href="https://github.com/haiku/haiku/blob/7d07c4bc739dbf90159a5c02e48b9118c47ebbcd/docs/develop/kernel/system_calls.rst">https://github.com/haiku/haiku/blob/7d07c4bc739dbf90159a5c02...</a><p>This is actually a great reason to keep it around; it's as simple as possible, and nothing uses it so it's easy to find the relevant bits of code.</p>
]]></description><pubDate>Mon, 16 Jun 2025 13:56:06 +0000</pubDate><link>https://news.ycombinator.com/item?id=44289529</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=44289529</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=44289529</guid></item><item><title><![CDATA[New comment by tomn in "Building a Tiny CNC Router for Making Circuit Boards"]]></title><description><![CDATA[
<p>Yeah, it's certainly doable, just a bit tricky because the spoil-board is not attached to the base, and is replaced nearly every time. It also needs at least one extra tool set-up.<p>If I needed a lot of double-sided boards it would be worth optimising this, but I don't really, single-sided (or the second side being 100% ground) is generally sufficient.</p>
]]></description><pubDate>Sun, 15 Jun 2025 16:17:33 +0000</pubDate><link>https://news.ycombinator.com/item?id=44283106</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=44283106</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=44283106</guid></item><item><title><![CDATA[New comment by tomn in "Making a smart bike dumb so it works again"]]></title><description><![CDATA[
<p>You're comparing a hub dynamo with cheap low-capacity rechargeable lights.<p>Rechargeable lights from the usual suspects are generally not good, they are expensive for what they are, have low capacity, and don't have swappable standard-size batteries.<p>They make dynamo systems look like a good deal, but if typical battery-powered lights were even close to their theoretical optimum I think people would be much less enthusiastic about dynamos.</p>
]]></description><pubDate>Wed, 23 Apr 2025 11:48:13 +0000</pubDate><link>https://news.ycombinator.com/item?id=43771002</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43771002</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43771002</guid></item><item><title><![CDATA[New comment by tomn in "Advanced Python Features"]]></title><description><![CDATA[
<p>The simple contextlib.contextmanager example doesn't really sell the benefits.<p>The main one is that it makes error handling and clean-up simpler, because you can just wrap the yield with a normal try/catch/finally, whereas to do this with __enter__ and __exit__ you have to work out what to do with the exception information in __exit__, which is easy to get wrong:<p><a href="https://docs.python.org/3/reference/datamodel.html#object.__exit__" rel="nofollow">https://docs.python.org/3/reference/datamodel.html#object.__...</a><p>Suppressing or passing the exception is also mysterious, whereas with contextlib you just raise it as normal.<p>Another is that it makes managing state more obvious. If data is passed into the context manager, and needs to be saved between __enter__ and __exit__, that ends up in instance variables, whereas with contextlib you just use function parameters and local variables.<p>Finally, it makes it much easier to use other context managers, which also makes it look more like normal code.<p>Here's a more real-world-like example in both styles:<p><a href="https://gist.github.com/tomjnixon/e84c9254ab6d00542a22b7d79945ef2b" rel="nofollow">https://gist.github.com/tomjnixon/e84c9254ab6d00542a22b7d799...</a><p>I think the first is much more obvious.<p>You can describe it in english as "open a file, then try to write a header, run the code inside the with statement, write a footer, and if anything fails truncate the file and pass the exception to the caller". This maps exactly to the lines in the contextlib version, whereas this logic is all spread out in the other one.<p>It's also more correct, as the file will be closed if any operation on it fails -- you'd need to add two more try/catch/finally blocks to the second example to make it as good.</p>
]]></description><pubDate>Wed, 23 Apr 2025 11:16:38 +0000</pubDate><link>https://news.ycombinator.com/item?id=43770768</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43770768</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43770768</guid></item><item><title><![CDATA[New comment by tomn in "Making a smart bike dumb so it works again"]]></title><description><![CDATA[
<p>A spare battery in your saddle-pack solves most of those problems.<p>If you're worried about being without light, a (typical) dynamo system is more complicated and exposed than a battery system, so will be more prone to failure.</p>
]]></description><pubDate>Tue, 22 Apr 2025 23:32:40 +0000</pubDate><link>https://news.ycombinator.com/item?id=43767280</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43767280</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43767280</guid></item><item><title><![CDATA[New comment by tomn in "Making a smart bike dumb so it works again"]]></title><description><![CDATA[
<p>I get why people like them, but they make way less sense when you work out the capacity of an equivalent weight (not to mention cost) of lithium cells.<p>It's easy to get to about 90Wh, which will run a dynamo-powered light for 30 hours on max (most dynamos seem to be rated 3W).<p>There are definitely cases where it makes sense, and not having to keep batteries charged is nice, it's just easy to miss how good batteries are these days.</p>
]]></description><pubDate>Tue, 22 Apr 2025 22:35:51 +0000</pubDate><link>https://news.ycombinator.com/item?id=43766944</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43766944</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43766944</guid></item><item><title><![CDATA[New comment by tomn in "Apple M3 Ultra"]]></title><description><![CDATA[
<p>I don't see why it should be so binary. I said it "mostly" just works because there are no packaging systems which do exactly what you want 100% of the time.<p>I've had plenty of problems with node, for example. You mentioned nix, which is much better, but also comes with tons of hard trade-offs.<p>If a packaging tool doesn't do what i wanted, but I can understand why, and ultimately the tool is not to blame, that's fine by me. The issues I can think of fit reasonably well within this scope:<p>- requirement version conflicts: packages are updated by different developers, so sometimes their requirements might not be compatible with each other. That's not pip's fault, and it tells you what the problem is so you can resolve it.<p>- code that's not compatible with updated packages: this is mainly down to requirement versions which are specified too loosely, and not the fault of pip. If you want to lock dependencies to exact versions (like node does by default) you can do this too (with requirements.txt). It's a bit harsh to blame pip for not doing this for you, it's like blaming npm for not committing your package.lock. It would be better if your average python developer was better at this.<p>- native library issues: some packages depend on you having specific libraries (and versions thereof) installed, and there's not much that pip can do about that. This is where your "ssl issues" come from. This is pretty common in python because it's used so much as "glue" between native libraries -- all the most fun packages are wrappers around native code. This has got a lot better in the past few years with manylinux wheels (which include native libraries). These require a lot of non-python-specific work to build, so i don't blame pip where they don't exist.<p>It's not perfect, but it's not a big enough deal to rant about or reject entirely if you would otherwise get a lot of value out of the ecosystem.</p>
]]></description><pubDate>Tue, 11 Mar 2025 00:16:39 +0000</pubDate><link>https://news.ycombinator.com/item?id=43327757</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43327757</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43327757</guid></item><item><title><![CDATA[New comment by tomn in "Improving on std:count_if()'s auto-vectorization"]]></title><description><![CDATA[
<p>Yeah, I thought about that too, but if you want to process more than 255 values this might not be valid, depending on the implementation of count_if.</p>
]]></description><pubDate>Mon, 10 Mar 2025 23:35:22 +0000</pubDate><link>https://news.ycombinator.com/item?id=43327452</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43327452</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43327452</guid></item><item><title><![CDATA[New comment by tomn in "Improving on std:count_if()'s auto-vectorization"]]></title><description><![CDATA[
<p>Just to correct my own comment:<p>> with an uint8_t local variable and size_t return value, an earlier optimisation removes the cast to uint8_t, because it only has an effect when undefined behaviour has been triggered<p>In this case, there is no undefined behaviour, because a narrowing cast to an unsigned type is well-defined. So, this could never have been a good explanation.</p>
]]></description><pubDate>Mon, 10 Mar 2025 23:32:22 +0000</pubDate><link>https://news.ycombinator.com/item?id=43327426</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43327426</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43327426</guid></item><item><title><![CDATA[New comment by tomn in "Improving on std:count_if()'s auto-vectorization"]]></title><description><![CDATA[
<p>I've had a look at what's going on in LLVM, and we're both a bit wrong :)<p>This optimisation is applied by AggressiveInstCombinePass, after the function has been completely inlined. In cases where it is applied, the i64 result of the count is truncated to i8, and this gets propagated to the counter.<p>In the case where the result is assigned to a local variable, an earlier pass (before inlining) turns a truncate (for the cast) followed by a zero extend (for the return) into an and with 0xff. This persists, and AggressiveInstCombinePass then doesn't propagate this to the counter.<p>I've posted some selected bits of LLVM IR here:<p><a href="https://gist.github.com/tomjnixon/d205a56ffc18af499418965ab76669a9" rel="nofollow">https://gist.github.com/tomjnixon/d205a56ffc18af499418965ab7...</a><p>These come from running clang with "-mllvm=-print-after-all" and grepping for "^define.*_Z20count_even_values_v1RKSt6vectorIhSaIhEE"<p>This is why i don't see this as an optimisation pass "backfiring" or "go[ing] the other way around" (well, except for the "trunc,extend->and" one which we weren't talking about). Rather, it's just an optimisation not being applied. That might just be a language thing.</p>
]]></description><pubDate>Sun, 09 Mar 2025 21:17:11 +0000</pubDate><link>https://news.ycombinator.com/item?id=43313940</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43313940</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43313940</guid></item><item><title><![CDATA[New comment by tomn in "Improving on std:count_if()'s auto-vectorization"]]></title><description><![CDATA[
<p>I'm not sure how "it can go the other way around too" -- in that case (assigning to a uint8_t local variable), it seems like that particular optimisation is just not being applied.<p>Interestingly, if the local variable is "volatile uint8_t", the optimisation is applied. Perhaps with an uint8_t local variable and size_t return value, an earlier optimisation removes the cast to uint8_t, because it only has an effect when undefined behaviour has been triggered? It would certainly be interesting to investigate further.<p>In general I agree that being more explicit is better if you really care about performance. It would be great if languages provided more ways to specify this kind of thing. I tried using __builtin_expect to trigger this optimisation too, but no dice.<p>Anyway, thanks for the interesting article.</p>
]]></description><pubDate>Sun, 09 Mar 2025 19:23:13 +0000</pubDate><link>https://news.ycombinator.com/item?id=43312704</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43312704</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43312704</guid></item><item><title><![CDATA[New comment by tomn in "Improving on std:count_if()'s auto-vectorization"]]></title><description><![CDATA[
<p>Oh right, I didn't see it in a couple of passes (and searching for cast); for anyone else looking it's in the 3rd footnote.  Thanks.</p>
]]></description><pubDate>Sun, 09 Mar 2025 15:43:34 +0000</pubDate><link>https://news.ycombinator.com/item?id=43310105</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43310105</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43310105</guid></item><item><title><![CDATA[New comment by tomn in "Improving on std:count_if()'s auto-vectorization"]]></title><description><![CDATA[
<p>another solution is to just cast the result to an uint8_t; with this, clang 19.1.0 gives the same assembly:<p><a href="https://gcc.godbolt.org/z/E5oTW5eKe" rel="nofollow">https://gcc.godbolt.org/z/E5oTW5eKe</a></p>
]]></description><pubDate>Sun, 09 Mar 2025 15:23:43 +0000</pubDate><link>https://news.ycombinator.com/item?id=43309849</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43309849</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43309849</guid></item><item><title><![CDATA[New comment by tomn in "Apple M3 Ultra"]]></title><description><![CDATA[
<p>This is incoherent to me. Your complaints are about packaging, but the elixir wrapper doesn't deal with that in any way -- it just wraps UV, which you could use without elixir.<p>What am I missing?<p>Also, typically when people say things like<p>> Tell me, which combination of the 15+ virtual environments, dependency management and Python version managers<p>It means they have been trapped in a cycle of thinking "just one more tool will surely solve my problem", instead of realising that the tools _are_ the problem, and if you just use the official methods (virtualenv and pip from a stock python install), things mostly just work.</p>
]]></description><pubDate>Wed, 05 Mar 2025 17:21:31 +0000</pubDate><link>https://news.ycombinator.com/item?id=43269516</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=43269516</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43269516</guid></item><item><title><![CDATA[New comment by tomn in "Ross Ulbricht granted a full pardon"]]></title><description><![CDATA[
<p>Real justice would be changing the laws and sentencing guidance (through a democratically legitimate process), and re-evaluating the sentences of everyone affected.<p>Whatever you think about the outcome in this case, it is the moral equivalent of vigilante justice. It is unfair to others convicted under the same regime, who don't happen to be libertarian icons who can be freed in exchange for a few grubby votes.</p>
]]></description><pubDate>Wed, 22 Jan 2025 23:34:32 +0000</pubDate><link>https://news.ycombinator.com/item?id=42798721</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=42798721</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=42798721</guid></item><item><title><![CDATA[New comment by tomn in "Couriers mystified by the algorithms that control their jobs"]]></title><description><![CDATA[
<p>despite that, the employment rights bill is at least moving in the right direction</p>
]]></description><pubDate>Wed, 22 Jan 2025 12:15:37 +0000</pubDate><link>https://news.ycombinator.com/item?id=42791930</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=42791930</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=42791930</guid></item><item><title><![CDATA[New comment by tomn in "Nix – Death by a Thousand Cuts"]]></title><description><![CDATA[
<p>> I am pretty sure that, unless you use --impure, all files that are read are required to be in the store. Since the store is read-only, it does not break purity.<p>Right, but even then the logical type for readFile would be something like "string -> string" (because from nix's perspective it is pure), but in haskell it would have to be "string -> IO string" (because from haskell's perspective it is not).<p>Maybe this is fine, i just suspect it would make things messier than expected.<p>Alternatively this could be worked around using unsafePerformIO or the FFI, but that feels a bit far away from the idea of just making a DSL? Unclear...<p>> But I don't know why one would want to.<p>Same, I just think it's an interesting discussion.</p>
]]></description><pubDate>Wed, 15 Jan 2025 17:11:14 +0000</pubDate><link>https://news.ycombinator.com/item?id=42713760</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=42713760</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=42713760</guid></item><item><title><![CDATA[New comment by tomn in "Nix – Death by a Thousand Cuts"]]></title><description><![CDATA[
<p>> the help online is always in the form of code fragments whose purpose kinda sorta looks alright maybe, but doesn't ever seem to fit into the setup I've built. So then I'm faced with completely rearranging the structure to match the helpful code, or try to massage the helpful code into my structure (which may or may not be a monstrosity, nor could I explain what every one of the magical incantations are for)<p>None of these are language problems, they are problems with the way nixpkgs is structured and the ways nix is used (or your understanding of those).<p>Perhaps being purely functional causes some of this complexity/unfamiliarity, but in that case replacing it with another pure functional language (the original point i was replying to) is not going to help. Maybe replacing it with scheme (functional/imperative) does, I don't know.</p>
]]></description><pubDate>Wed, 15 Jan 2025 12:42:43 +0000</pubDate><link>https://news.ycombinator.com/item?id=42710245</link><dc:creator>tomn</dc:creator><comments>https://news.ycombinator.com/item?id=42710245</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=42710245</guid></item></channel></rss>