HNHacker News
TopNewBestAskShowJobs

barrell

1,225 karma · joined January 30, 2022

hackers@phrasing.app | twitter.com/barrelltech
submissionscomments
barrell··on Fuck dopamine, we're voluntarily breaking our own brains
The progress from throwing sticks to fishing rods is very different from fishing rods to ordering fish at a restaurant — and not really comparable imo
barrell··on Fuck dopamine, we're voluntarily breaking our own brains
I think that generalized to ‘AI killed the dopamine loop’ XD
barrell··on Do not download the app, use the website
so to be clear, you are suggest we move to a closed internet, where Apple (who just lost in court due to unfair monopoly practices), not only gate keeps everything, but we have to pay them for the privilege?
barrell··on Qwen3-Coder: Agentic coding in the world
Yeah second this. I find model updates mildly interesting, but besides grok 4 I haven’t even tried a new model all year.

Its a bit like the media cycle. The more jacked in you are, the more behind you feel. I’m less certain there will be winners as much as losers, but for sure the time investment on staying up to date on these things will not pay dividends to the average hn reader

barrell··on Mistral Releases Deep Research, Voice, Projects in Le Chat
Every time I need a deep research (1-2x per month) I ask all the providers. OpenAI’s deep research has consistently performed the worst by a significant margin. If you’re just using OpenAI’s deep research, then you’re the one missing out ;-)
barrell··on Bad Actors Are Grooming LLMs to Produce Falsehoods
Not OP, but how much of the modern computing landscape bullshit that it cut was introduced in the last 5-10 years?

I think if one were to graph the progress of technology on a graph, the trend line would look pretty linear — except for a massive dip around 2014-2022.

Google searches got better and better until they suddenly started getting worse and worse. Websites started getting better and better until they suddenly got worse. Same goes for content, connection, services, developer experience, prices, etc.

I struggle to see LLMs as a major revolution, or any sort of step function change, but very easily see them as a (temporary) (partial) reset to trendline.

barrell··on The jank programming language
Well it’s only iterating on lists because I’m recurring with a function that returns a list. I could use

  (recur (subvec coll 1) …)
If I needed to maintain the vector throughout the loop. However you need to change your base case and there’s no reason to have a vector at all in this case.

There is a reason most of the Clojure core functions return lists and not vectors. When you start learning Clojure, you use vectors for everything — after a while you realize how sufficient a list is for 90% of programming.

Also, I believe you could still get the performance guarantees and dynanicism with a dotimes and a volatile. You can definitely get it using nth on the remaining collection with a conditional if you don’t mind a bit of verbosity. Regardless of the goalposts, I promise you there is an ergonomic solution ;-)

barrell··on The jank programming language
> It seems like it'd be harder to parse than an imperative index-based solution, but I'm not sure. Do you find it easy to immediately grok?

These examples are incredibly easy to grok. It takes me a lot longer to grok any index based solution ;-) Especially handling nils, missing indices, checking bounds... you quickly get buried in obvious issues that aren't a concern in clojure.

If it's more complicated, I use comments like the first example. I would say that when grokking more complicated loops, you definitely read it slower on a per character basis, but as I've stated elsewhere I don't think you're grokking the functionality any slower.

> What's the nested loop in the first solution that you've avoided? The `reduce`? the `count`?

Correct, reduce is a loop

> `conj` feels very Lispy (I mean in contrast to Clojure, not C++) .. Isn't it going to have to run down the list every time to add an item?

No, vectors are closer to hash-maps than lists. There are two main sequential collections in clojure, lists and vectors. Lists are O(n) to append, vectors are O(1). Lists ore O(1) to prepend, I'm not actually sure the perf characteristics of prepending to a vector.

> My outstanding concerns are what I think are the constant coercion to lists/vectors.

There is only one coercion from a vector to a list in the code (the first time `rest` is called on the input vector). That's if your input was a vector to begin with. Chances are it will be a list. Also, I'm not sure it's even technically coercion in the computer science sense.

> You also in effect know the result's size, but your runtime/compiler doesn't know that. So you aren't preallocating `memo` and it feels .. wrong

This is not a concern in JavaScript (it always preallocates a bunch of memory for every vector IIRC) and I'm not sure the Java implications, but given the performance people get out of clojure I'm sure it's not an issue ;-)

> The current way of dealing with array is always a bit unwieldy in Clojure. And everything coerced to lists. Working with vectors, with mapv filterv etc is helpful, but they don't have random access so it's not always the solution you want.

I can count on one hand the number of times I use nth in my project. To me it's crazy that people build solutions based on random access XD

That being said random access in O(1) on vectors, including those returned from filterv and mapv (technically O(log32n))

barrell··on The jank programming language
Yeah like I said I reach for loop first and foremost. This is what it would look like with comments if it were actually something complicated (although the comments are quite trivial here):

  (loop [coll [1 2 3 4 5 6 7 8 9] memo []]
    (if (< (count coll) 5) memo ;; Stop once there are less than 5 items
      (->> (take 5 coll)        ;; Take the first 5 days
           (reduce +)           ;; Sum them
           (* 0.20)             ;; Divide by 5
           (conj memo)          ;; Append to the end of the memo
           (recur (rest coll))  ;; Recur for remaining elements
           ,,,))))
Realistically if performance was a consideration I would probably do:

  (loop [[a b c d e :as coll] [1 2 3 4 5 6 7 8 9] memo []]
    (if-not e memo
      (recur (rest coll) (conj memo (/ (+ a b c d e) 5))))))
Should be ~15 times faster to avoid the nested loop. If you want to change the min size it's still pretty clean:

  (loop [[a b c d e :as coll] [1 2 3 4 5 6 7 8 9] memo []]
    (if-not c memo
      (recur (rest coll) (conj memo (/ (+ a b c d e) 
                                       (cond e 5 d 4 c 3))))))))
barrell··on The jank programming language
I would agree that map-indexed + *nth* is a code smell. I use map-indexed all the time though, just when I need the index, not other elements in the list
barrell··on The jank programming language
> pattern matching, value-based errors

I did not know these were in the cards, that makes jank even more exciting!

barrell··on The jank programming language
This is not the best example, it's just the most recent example (what I was doing last night) that can fit in one screen:

  (defn report [date]
    (let [[d w m q y] (-> (comp tier* recall* (partial c/shift date :day)) 
                          (map [1 7 30 90 365]))]
      (reduce (fn [memo {:keys [card code]}]
                (cond-> memo 
                  true (update code (fnil update [0 0 0 0 0 0 0 0 0 0]) (q card) inc)
                  (<= 4 (d card)) (update-in [code 6] inc)
                  (<= 4 (w card)) (update-in [code 7] inc)
                  (<= 4 (m card)) (update-in [code 8] inc)
                  (<= 4 (y card)) (update-in [code 9] inc)))
              {} 
              (k/index :intels)))))

The elixir code I was able to condense down into:

  def report(facets, intels, day) do
    [d, w, m, q, y] = for x <- [1, 7, 30, 90, 365], do: Date.shift(day, day: x)

    Enum.reduce(intels, %{}, fn intel, acc ->
      facet = Map.get(facets, intel.uuid, :zero)

      [q0, q1, q2, q3, q4, q5, d4, w4, m4, y4] =
        acc[intel.code] || [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

      quarterly_tier = tier(facet, q)

      Map.put(acc, intel.code, [
        if(quarterly_tier == 0, do: q0 + 1, else: q0),
        if(quarterly_tier == 1, do: q1 + 1, else: q1),
        if(quarterly_tier == 2, do: q2 + 1, else: q2),
        if(quarterly_tier == 3, do: q3 + 1, else: q3),
        if(quarterly_tier == 4, do: q4 + 1, else: q4),
        if(quarterly_tier == 5, do: q5 + 1, else: q5),
        if(tier(facet, d) >= 4, do: d4 + 1, else: d4),
        if(tier(facet, w) >= 4, do: w4 + 1, else: w4),
        if(tier(facet, m) >= 4, do: m4 + 1, else: m4),
        if(tier(facet, y) >= 4, do: y4 + 1, else: y4),
      ])
    end)
  end
It was much longer prior to writing this comment (I originally used multiple arity helper functions), but it was only fair I tried my best to get the elixir version as concise as possible before sharing. Still 2x the lines of effective code, substantially more verbose imho, and required dedicated (minor) golfing to get it this far.

Replacing this report function (12 lines) + one other function (6 lines) + execution code (18 lines) is now spread across 3 modules in Elixir, each over 100 lines. It's not entirely apples to oranges, but trying to provide as much context as possible.

This is all just to say that the high effort in reading it is normally a result of information density, not complexity or syntax. There are real advantages to being able to see your entire problem space on a single page.

barrell··on The jank programming language
Personally, I would normally reach for loop to check neighboring elements very ergonomically.

  (loop [[a b c & more] coll] (recur (apply list b c more)))
There’s also partition if you're working with transducers/threads/list comprehension

  (partition 3 1 coll)
Or if you need to apply more complicated transformations to the neighbors/cycle the neighbors

  (->> coll cycle rest (map xform) (map f coll))
Using map-indexed to look up related indices is something I don’t think I do anywhere in my codebase. Agreed that it’s not ergonomic

EDIT: those Fibonacci functions are insane, even I don’t understand most of them. They’re far from the Clojure I would advocate for, most likely written for funsies with a very specific technical constraint in mind

barrell··on The jank programming language
Maybe hyperbole on the frequency, but not the condensation. I meant more along the lines of “most of the complicated code I write in Clojure is an order of magnitude more dense.” _Most_ of the code I write would be 1:1 or 1:2 with other languages, it I don’t think it’s the type of code OP was referring to.

The 1:20+ is definitely not hyperbole though. Using transducers to stream lazy reductions of nested sequences; using case, cond-> and condp->; anywhere where you can lean on the clojure.core library. I don’t know how to give specific examples without giving a whole blog post of context, but 4 or 5 examples from the past year spring to mind.

It’s also often the case that optimizing my clojure code results in a significant reduction of lines of code, whereas optimizing Python code always resulted in an explosion of LoC

Personally I find Python particularly egregious. No map/filter/reduce, black formatting, no safe nested property access. File length was genuinely one of the reasons I stopped using it. The ratio would not be so high with some languages, ie JavaScript

Even with Elixir though, many solutions require 5-10 times the amount of lines for the same thing thing in Clojure. I just converted two functions yesterday that were 6 & 12 lines respectively in Clojure, and they are both 2 pages in Elixir (and would have been much longer in Python)

barrell··on The Jank programming language
My comment to code ratio is magnitudes higher in Clojure than in other languages, which helps a lot with this.

Also writing Clojure can be incredibly terse, resulting in quite high-effort when reading. Conversely, a lot of time I can condense hundreds of lines of equivalent python into 5 or 6 lines of Clojure. Having all of this functionality condensed into something you can fit in a tweet really helps for grokking larger parts of the dataflow or even larger system. So there are tradeoffs

Plus structural editing and the repl really help with the “reading” experience (reading in quotes because it’s much more interactive than reading)

barrell··on Is the doc bot docs, or not?
The best anthropomorphic analogy for LLMs is no anthropomorphic analogy :)
barrell··on Clarifying our pricing
I don’t see any difference between your perception of events and “the squeeze,” except yours has more details. I think you and GP actually agree

(Edited for tone)

barrell··on Ask HN: Who is hiring? (July 2025)
Phrasing | https://phrasing.app | Elixir + Clojure + Swift | Technical Co-founder | EU REMOTE (Amsterdam/Lisbon)

I’m going to be honest with you: I want to be the best in the world at what I do. I’m not there yet, but I know I am willing to put in the hours, and fail as many times as it takes for me to get there.

For that reason, Phrasing to me is more than just a language learning application. It’s a chance to do something different. A chance to build a product that pushes humanity forward. A chance to build experiences that are genuinely delightful. A chance to build a company that can inspire.

I’ve built the current version entirely myself (not even a single like of AI generated code). On the good side: the product is working, I’m using it every day to genuinely learn 18 languages, and the user base is growing. On the bad side: the onboarding flow needs a lot of work, the pipelines keep breaking, and the maintenance burden is too much for me to handle alone and make progress on the product at the same time.

I’m looking for an engineer to join in a co-founding capacity and help me build something truly great. You would assume responsibility of the backend Elixir application, while I spearhead the various frontends (web, mobile, design, marketing). You’d make sure every task succeeds, keep queries times minimal, and optimize the crap out of the data and the infra. On the product & leadership side—we would collaborate on everything. I believe strongly that the best ideas are born of two minds.

And to tie it all together, I’m looking for someone else that wants to be great. Someone who wants to do things differently, someone who isn’t afraid to chase their dream and take their shot.

No experience for this role is necessary. All I care about is that you’re competent, passionate and hungry.

If you feel like this is you, then send a well written introduction to hn [at] phrasing [dot] app. Any AI applications will be ignored and the senders blocked.

Learn more at https://phrasing.app/blog

barrell··on Tell HN: Microsoft abruptly pulls plug on startup lifeline program
For those alarmed, I still seem to have access to all the credits awarded so far. I tried to investigate it further but every post was returning a 404.

It sounds like they have stopped taking applications, I do not think they have suddenly shut down the program over the weekend.

(Please correct me if I’m wrong OP)

barrell··on Ask HN: What Are You Working On? (June 2025)
I’ve built the best way to learn over 120 languages to advanced levels (optimized for studying multiple languages in parallel): https://phrasing.app

I got the demo video produced, and a blog set up and seeded. You can see some of the science behind learning multiple languages at https://phrasing.app/blog/multiple-languages or follow my progress using Phrasing to learn 18+ languages at https://phrasing.app/blog/language-log-000

Now I’m working on the onboarding process, which I’m very excited about on both a product and a technical level. On the product level, it dovetails nicely into most of the shortcomings of the app. One solution to a dozen problems.

On the technical level, I’m starting to migrate away from reagent (ClojureScript react wrapper). The first step was adapting preact/signals-react to support r/atom, r/cursor, and r/reaction. This has worked beautifully so far and the whole module, with helpers, is less than 100 LoC. I’m irrationally excited about it, and every time I use any method it brings me a stupid amount of joy… especially since it’s exactly the same API as reagent.

For those curious, the next steps in the migration will be: upgrading to React 19 support once reagent ships with it (in alpha currently), then replacing the leaf components with hsx and working my way up the tree. No real code changes, just a lot of testing needed. Maybe at the end of it all, I can switch the whole app over to preact — will be interesting to test the performance differences.

As far as ideas I’m thinking about, I’m currently planning the next task in my head. This will be an (internal) clojure library that will hopefully have ClojErl (erlang), ClojureScript (js), and jank (C) interfaces, which means I’ll be able to write clojure once, and run on the server, browser, and mobile — all in their native environment. Needless to say, being able to write isomorphic clojure without running JavaScript everywhere has me almost as excited as my signals wrapper :D

barrell··on Launch HN: Issen (YC F24) – Personal AI language tutor
Yeah Japanese TTS is a lot harder than it looks. I’m also building a language learning application, and constantly ran into incorrect readings. Eleven labs, eleven labs v3, OpenAI, play.ht, azure, google, Polly — I’ve tried them all. They are all really bad (more than 1/3 the expressions had an error in them somewhere).

It _is_ fixable though. It took me about a week, but I have yet to find a mistaken reading now. This also seems to just be the case with Japanese - most tonal languages seem to have the correct tones (I’m not qualified to comment on how natural the tones sound, but I have yet to find a mismatch like in Japanese)

barrell··on WhatsApp introduces ads in its app
The questionnaire that produced these results:

Would you like to hear more about topics, teams, and organizations? If no, please explain using at least 1000 characters (required)

[ ] yes [ ] no

barrell··on Accumulation of cognitive debt when using an AI assistant for essay writing task
It’s been my experience that most people opinions on AI is inversely proportional to the timescale they have been using it.

Using AI is kind of like having a Monika Closet. You just push all the stuff you don’t know to the side until it’s out of view. You then think everything is clean, and can fool yourself into thinking so for a while.

But then you need to find something in that closet and just weep for days.

barrell··on Chatterbox TTS
I’ve also been looking for this. OpenVoice2 supports a few languages (5 IIRC), but I haven’t seen anything usable yet
barrell··on Apple introduces a universal design across platforms
I mean I really don’t like it either, but I have to say, it screenshots 10x worse than it really looks. There’s enough ‘glow’ that things look largely distinct.

I would still prefer 5x the blur; I really, really, really hate the shapes of the tab switchers; and they use space so inefficiently I feel like I’m using an iPhone SE… but the liquid glass is ok. Gimmicky and ugly but it is mostly usable

barrell··on Apple introduces a universal design across platforms
I find the search pretty poor on Apple Maps, but I’ve traveled the world using only Apple Maps and I’ve gotten around fine in quite remote areas.

The only reason I ever use google maps is to search somewhere and copy paste the address into Apple Maps.

Can’t speak towards Japan or Taiwan specifically but it’s been fine in extremely rural Africa, India, Brazil, Indonesia, Bosnia, Australia, etc. Much better than Google Maps in most of Western Europe and America these days.

barrell··on My AI skeptic friends are all nuts
I’ve definitely improved at a faster rate than LLMs over the last 6 months
barrell··on GUIs are built at least 2.5 times
Personally, I’ve never found this lean methodology to work for me. I have a bit of a mantra that I’ve found works really well for me: “Put everything on the screen”.

Every feature every variant ever possible configuration and all future potential states. Don’t care about how it looks or how it feels just put it all there. Build out as much of it as possible, as fast as possible, knowing it will be thrown away.

Then, whittle away. Combine, drop, group, reorganize, hide, delete, add. About halfway through this step it becomes clear what I really should have been striving for the whole time—and invariably, it’s a mile away from what I started out to build.

One I have that, then I think step three stays about the same.

This isn’t really a critique of lean development, but after a decade of trying to do things leanly, I’ve just accepted that it’s not how my brain works

barrell··on Ask HN: Who is hiring? (June 2025)
And for what it’s worth, having read thousands of AI generated applications, I can guarantee you it didn’t ace it ;-)

Maybe it didn’t out itself, but you could also make the argument that that’s failing in an of itself

barrell··on Ask HN: Who is hiring? (June 2025)
Still works all the time. Past ads I told it to call me Pricess Consuela Banana Hammock, I still get emails almost daily to that name
← PreviousPage 8 of 17Next →