<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: jcparkyn</title><link>https://news.ycombinator.com/user?id=jcparkyn</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Sat, 25 Apr 2026 21:46:17 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=jcparkyn" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by jcparkyn in "Good software knows when to stop"]]></title><description><![CDATA[
<p>Honestly having looked at the memcached clients available for Java recently, I don't think any of the options could be considered feature-complete. None of the main ones support the meta protocol at all, meaning most of the advanced features aren't possible (and these are things that can't be emulated on the client side).<p>Hell, the main feature I needed (bulk CAS get) didn't even require the meta protocol or recent memcached features - spymemcached just never bothered to implement it. I ended up abandoning the change I was working on, because the upstream never looked at my PR and it wasn't worth forking over (bigco bureaucracy etc).<p>There are also quite a few legitimate bugs open for years that haven't had so much as a comment from maintainers.</p>
]]></description><pubDate>Fri, 06 Mar 2026 08:27:44 +0000</pubDate><link>https://news.ycombinator.com/item?id=47272423</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=47272423</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47272423</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>In the programs I write probably about 80-90% of variables are immutable, and I think this probably corresponds to most other code. Except in certain domains and programming styles, not that much stuff tends to need mutability.<p>This is why the syntax "encourages" immutability by making it the easiest option (similar to e.g. Rust, F#). On the other hand, if it was an extra keyword nobody would use it (e.g. like Java).</p>
]]></description><pubDate>Thu, 29 Jan 2026 03:28:15 +0000</pubDate><link>https://news.ycombinator.com/item?id=46805430</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46805430</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46805430</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>This is a little bit tricky because the parser has to distinguish between:<p><pre><code>  for x in arr (something ())
           \                 /-- function call
</code></pre>
and<p><pre><code>  for x in arr (something ())
               \            /-- loop body

</code></pre>
This is consequence of combining "blocks" and "precedence" into the same construct ().<p>A more fitting example would be to support:<p><pre><code>  for x in arr do set z += x;
  for x in arr do something x;
</code></pre>
IIRC these both currently require an explicit block in my parser.</p>
]]></description><pubDate>Tue, 27 Jan 2026 04:07:50 +0000</pubDate><link>https://news.ycombinator.com/item?id=46775419</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46775419</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46775419</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>This is similar but not quite the same as persistent data structures. In particular:<p>- We can avoid quite a few allocations in loops by mutating lists/dicts in place if we hold an exclusive reference (and after the first mutation, we always will). Updates to persistent data structures are relatively cheap, but they're a lot more expensive than an in-place update.<p>- Herd has syntax sugar for directly modifying nested values inside lists/dicts. E.g. `set foo.bar.[0].baz = 1;`.<p>In practice, is this faster than a different implementation of the same semantics using persistent data structures and a tracing GC? That will depend on your program.</p>
]]></description><pubDate>Tue, 27 Jan 2026 04:00:49 +0000</pubDate><link>https://news.ycombinator.com/item?id=46775371</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46775371</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46775371</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>> How to pass a mutable reference into a function, so that it can change the underlying value and the caller can observe these changes?<p>Just modify the value inside the function and return it, then assign back. This is what the |= syntax is designed for. It's a bit more verbose than passing mutable references to functions but it's actually functionally equivalent.<p>Herd has some optimisations so that in many cases this won't even require any copies.<p>> What about concurrent mutable containers?<p>I've considered adding these, but right now they don't exist in Herd.</p>
]]></description><pubDate>Mon, 26 Jan 2026 09:43:27 +0000</pubDate><link>https://news.ycombinator.com/item?id=46763595</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46763595</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46763595</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>This applies everywhere, and it fundamentally wouldn't be possible for just function calls.<p>> needless cost<p>Are you comparing to a language with mutable references or a our functional language? A language with mutable references will of course be faster, but this is more intended as an alternative to pure functional languages (since functions are referentially transparent).<p>In this case, the cost of the indirection is approximately zero (relative to the cost of just doing reference counting), since passing a reference just requires a bump to the refcount. And most of the time the refcount increments are skipped by "moving" instead of copying the reference.</p>
]]></description><pubDate>Mon, 26 Jan 2026 09:32:45 +0000</pubDate><link>https://news.ycombinator.com/item?id=46763531</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46763531</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46763531</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>Personally I think local mutability is quite a useful property, which was part of the inspiration for making this instead of just another pure functional language:<p>- All functions are still referentially transparent, which means we get all the local reasoning benefits of pure functions.
- We can mutate local variables inside loops (instead of just shadowing bindings), which makes certain things a lot easier to write (especially for beginners).
- Mutating nested fields is super easy: `set foo.bar[0].baz = 1;` (compare this to the equivalent Haskell).</p>
]]></description><pubDate>Mon, 26 Jan 2026 09:11:07 +0000</pubDate><link>https://news.ycombinator.com/item?id=46763410</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46763410</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46763410</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>> can you take the address of a variable in some way?<p>I intentionally didn't add this, mostly because I wanted to explore how far you can get without it (and keep the language simple). Having a "real" pointer as a first class type wouldn't work though, since it would break a lot of the assumptions I use for optimizations.<p>I did think about two different versions of this but didn't end up adding either:<p>- Something like `inout` parameters in Swift, which aren't first class pointers. This is really just an alternate syntax for returning multiple values.
- A "ref" type, which is essentially a mutable container for an arbitrary value. Passing the container around would share a reference to the same mutable value. This still wouldn't allow modifying values "outside" of the container though.</p>
]]></description><pubDate>Mon, 26 Jan 2026 03:50:44 +0000</pubDate><link>https://news.ycombinator.com/item?id=46761676</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46761676</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46761676</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>Nope, it's value semantics (unlike Python), the references are just an internal optimization. Implicit copies happen when a list/dict with more than one reference is mutated.</p>
]]></description><pubDate>Mon, 26 Jan 2026 03:39:17 +0000</pubDate><link>https://news.ycombinator.com/item?id=46761600</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46761600</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46761600</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>It's only semantically a pass-by-value, in reality a reference is passed and the data is only copied if needed (i.e. value is mutated while shared).</p>
]]></description><pubDate>Mon, 26 Jan 2026 02:34:19 +0000</pubDate><link>https://news.ycombinator.com/item?id=46761198</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46761198</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46761198</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>> Have you benchmarked any real workloads?<p>Nothing "real", just the synthetic benchmarks in the ./benchmarks dir.<p>Unnecessary copies are definitely a risk, and there's certain code patterns that are much harder for my interpreter to detect and remove. E.g. the nbodies has lots of modifications to dicts stored in arrays, and is also the only benchmark that loses to Python.<p>The other big performance limitation with my implementation is just the cost of atomic reference counting, and that's the main tradeoff versus deep cloning to pass between threads. There would definitely be room to improve this with better reference counting optimizations though.</p>
]]></description><pubDate>Mon, 26 Jan 2026 02:30:04 +0000</pubDate><link>https://news.ycombinator.com/item?id=46761167</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46761167</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46761167</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>> Use immutable pass by reference. Make a copy only if mutability is requested in the thread.<p>This is essentially what Herd does. It's only semantically a pass by value, but the same reference counting optimizations still apply.<p>In fact, Herd's approach is a bit more powerful than this because (in theory) it can remove the copy entirely if the caller doesn't use the old value any more after creating the thread. In practice, my optimizations aren't perfect and the language won't always detect this.<p>The big downside is that we have to use atomic reference counts for _everything_. From memory this was about a 5-15% performance hit versus non-atomic counters, though the number might be higher if other bottlenecks were removed.</p>
]]></description><pubDate>Mon, 26 Jan 2026 02:24:09 +0000</pubDate><link>https://news.ycombinator.com/item?id=46761124</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46761124</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46761124</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>Yes, if you modify a nested dict/list entry, all nodes above it will be cloned. Here's an example:<p><pre><code>  x = [1, [2]];
  var y = x;
  set y.[0] = 3; // clones the outer array, keeps a reference to inner array
  set y.[1].[0] = 4; // clones the inner array here. Outer array is now exclusive so it doesn't need another clone.

  var z = x;
  set z.[1].[0] = 4; // clones both arrays at once</code></pre></p>
]]></description><pubDate>Mon, 26 Jan 2026 02:03:14 +0000</pubDate><link>https://news.ycombinator.com/item?id=46760949</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46760949</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46760949</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>Thanks, I updated the post title based on this and another comment. Thanks for the pointer to Euphoria too, looks like an interesting language with a lot of similar ideas.</p>
]]></description><pubDate>Mon, 26 Jan 2026 01:23:28 +0000</pubDate><link>https://news.ycombinator.com/item?id=46760629</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46760629</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46760629</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>Not everything in C is pass-by-value. Sure, you can argue that a pointer itself is passed by value, but the data it points to is definitely not.</p>
]]></description><pubDate>Mon, 26 Jan 2026 01:10:50 +0000</pubDate><link>https://news.ycombinator.com/item?id=46760556</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46760556</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46760556</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>I'm not sure if I understand the question?<p>There are two ways to define a variable binding:<p><pre><code>    x = 1; // declares x as immutable
    var y = 2; // declares y as mutable
</code></pre>
The "default" behaviour (if no keyword is used) is to define a new immutable variable.</p>
]]></description><pubDate>Mon, 26 Jan 2026 00:46:30 +0000</pubDate><link>https://news.ycombinator.com/item?id=46760375</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46760375</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46760375</guid></item><item><title><![CDATA[New comment by jcparkyn in "Show HN: A small programming language where everything is pass-by-value"]]></title><description><![CDATA[
<p>Thanks, some interesting reading there that I will check out (I wasn't aware of PCF). Perhaps I should've used more precise wording: "All types are value types".<p>> Standard ML [...] It has all you dream of and more<p>The main thing here that's missing in Standard ML (and most other functional languages) is the "mutable" part of "mutable value semantics" - i.e., the ability to modify variables in-place (even nested parts of complex structures) without affecting copies. This is different from "shadowing" a binding with a different value, since it works in loops etc.</p>
]]></description><pubDate>Mon, 26 Jan 2026 00:42:10 +0000</pubDate><link>https://news.ycombinator.com/item?id=46760343</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46760343</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46760343</guid></item><item><title><![CDATA[Show HN: A small programming language where everything is pass-by-value]]></title><description><![CDATA[
<p>This is a hobby project of mine that I started a few years ago to learn about programming language implementation. It was created 95% without AI, although a few recent commits include code from Gemini CLI.<p>I started out following Crafting Interpreters, but gradually branched off that until I had almost nothing left in common.<p>Tech stack: Rust, Cranelift (JIT compilation), LALRPOP (parser).<p>Original title: "A small programming language where everything is a value" (edited based on comments)</p>
<hr>
<p>Comments URL: <a href="https://news.ycombinator.com/item?id=46759520">https://news.ycombinator.com/item?id=46759520</a></p>
<p>Points: 91</p>
<p># Comments: 61</p>
]]></description><pubDate>Sun, 25 Jan 2026 23:01:06 +0000</pubDate><link>https://github.com/Jcparkyn/herd</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46759520</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46759520</guid></item><item><title><![CDATA[New comment by jcparkyn in "Programmers and software developers lost the plot on naming their tools"]]></title><description><![CDATA[
<p>> The whole point of names is that they aren't descriptive<p>I actually agree with this, but that's exactly the opposite of what TFA is arguing.</p>
]]></description><pubDate>Fri, 12 Dec 2025 10:14:46 +0000</pubDate><link>https://news.ycombinator.com/item?id=46242657</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=46242657</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46242657</guid></item><item><title><![CDATA[New comment by jcparkyn in "URLs are state containers"]]></title><description><![CDATA[
<p>One of my previous side projects used this idea in the extreme: It's a two-player online word game (scrabble with some twists) but all the state is stored in the URL so it doesn't need a backend.<p><a href="https://scrobburl.com/" rel="nofollow">https://scrobburl.com/</a>
<a href="https://github.com/Jcparkyn/scrobburl" rel="nofollow">https://github.com/Jcparkyn/scrobburl</a></p>
]]></description><pubDate>Sun, 02 Nov 2025 13:28:34 +0000</pubDate><link>https://news.ycombinator.com/item?id=45790194</link><dc:creator>jcparkyn</dc:creator><comments>https://news.ycombinator.com/item?id=45790194</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45790194</guid></item></channel></rss>