[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fu8xgxaxookfr":3},{"_id":4,"slug":5,"title":6,"subtitle":7,"kind":8,"cards":9,"tags":58,"categories":59,"source":60,"lang":63,"author":64,"audioState":67,"stats":68,"publishedAt":71,"renderer":72},"6abc6203ca21c797c7e9eab6","needed-11-built-a-functional-programming-language-de9b9b86","Needed 1+1, Built a Functional Programming Language","I was given a data structures problem of converting an arithmetic expression into a binary tree.","news",[10,13,18,23,28,33,38,43,48,53],{"headline":6,"body":11,"imageUrl":12,"sourceImageUrl":12},"I was given a data structures problem of converting an arithmetic expression into a binary tree. Naturally, I decided to build an evaluator.","https:\u002F\u002Fhereticpleb.vercel.app\u002Fog-image.jpg",{"headline":14,"body":15,"imageUrl":16,"images":17},"A few days later I implemented closures, a","A few days later I implemented closures, a garbage collector, a custom memory allocator, a REPL, an FFI, and a whole bunch of other stuff in C. THE DATA STRUCTURES ASSIGNMENT The problem was: Evaluate 1 + 1 + 1 to 3 using a binary tree. Well, we first form our tree for 1+1+1 The operator becomes the root, with its two operands as children. Now let’s evaluate this tree.","\u002Fapi\u002Fmedia\u002Fposts\u002Fneeded-11-built-a-functional-programming-language-de9b9b86\u002F1.webp",{"local":16},{"headline":19,"body":20,"imageUrl":21,"images":22},"First, we evaluate the root’s left operand. It’s","First, we evaluate the root’s left operand. It’s another + expression, so we have to collapse it down to a value before the outer + can execute. We just performed the equivalent of But notice what the evaluator had to know to do this: what + means. One way to represent this is to make every operation a different case in our expression type: But what do these different cases actually represent? And does the evaluator really need to know the difference between Add and Sub? Then I started implementing our sum types. And when I looked at the structure: They all take two expressions and produce one expression. So why should the evaluator care whether the operation is Add, Sub, Mul, or Div? So now we can just represent our expression as: The evaluator doesn’t need to know what a function does. It only needs to know how to apply one. We can add vars to this. It wouldn’t be a big change","\u002Fapi\u002Fmedia\u002Fposts\u002Fneeded-11-built-a-functional-programming-language-de9b9b86\u002F2.webp",{"local":21},{"headline":24,"body":25,"imageUrl":26,"images":27},"Should be a tiny addition, no problem whatsoever","Should be a tiny addition, no problem whatsoever. I mean variables are just a hash table lookup that gives you an Expr. Oh wait. C doesn’t have built-in hash tables. Let’s just implement a hashtable. It’s a small change! m9(・∀・) Let’s just implement a hashtable. It’s a small change! m9(・∀・)","\u002Fapi\u002Fmedia\u002Fposts\u002Fneeded-11-built-a-functional-programming-language-de9b9b86\u002F3.webp",{"local":26},{"headline":29,"body":30,"imageUrl":31,"images":32},"Soo…how does that work? I never implemented it","Soo…how does that work? I never implemented it before. I look it up on Google like a caveman and find this amazing text. So now we just got a little change in the Expr: Would you look at that! We have variables now that can be passed to functions once evaluated. Just like (+ 1 1) Actually implementing it in C Alright then, time to code in C with this plan. Seems simple enough. Just a tagged union. Right now the mem size of each ( assuming 64 bit system) is:","\u002Fapi\u002Fmedia\u002Fposts\u002Fneeded-11-built-a-functional-programming-language-de9b9b86\u002F4.webp",{"local":31},{"headline":34,"body":35,"imageUrl":36,"images":37},"32 Bytes might not seem like a lot","32 Bytes might not seem like a lot, but we gotta think about how this is being used. For evaluating 1+1, we would need 3 nodes. That would be 32 x 3= 96 bytes to evaluate 1+1.","\u002Fapi\u002Fmedia\u002Fposts\u002Fneeded-11-built-a-functional-programming-language-de9b9b86\u002F5.webp",{"local":36},{"headline":39,"body":40,"imageUrl":41,"images":42},"But here’s the thing. On my system, when","But here’s the thing. On my system, when you malloc() a node, it adds metadata, which takes up 16 bytes of memory! Bringing our total per node to 32 (node size) + 16 (malloc header) = 48 bytes! So for our 3 nodes to evaluate a (+) we would need 144 bytes!","\u002Fapi\u002Fmedia\u002Fposts\u002Fneeded-11-built-a-functional-programming-language-de9b9b86\u002F6.webp",{"local":41},{"headline":44,"body":45,"imageUrl":46,"images":47},"And notice we’re going to be doing a","And notice we’re going to be doing a lot of little individual allocations. We need a better way to allocate these nodes. We clearly need a custom allocator. So, I look up what allocator we can use, again like a caveman, and I decide I will be writing an Arena Allocator.","\u002Fapi\u002Fmedia\u002Fposts\u002Fneeded-11-built-a-functional-programming-language-de9b9b86\u002F7.webp",{"local":46},{"headline":49,"body":50,"imageUrl":51,"images":52},"The idea of an arena allocator is pretty","The idea of an arena allocator is pretty simple. All you do is take a big chunk of memory at the start, allocate stuff yourself, and then at the end just free the entire block. So my arena allocator would just be: And when we allocate a node, we can just keep track of the top using. When we want to allocate a node, we just return. I wrote the allocator and defined a C function to allocate nodes: It was great! Now moving on to actually calling the functions. We can store vars and funcs in the same environment! That means functions can just be values too (°◇°) We can store vars and funcs in the same environment! That means functions can just be values too (°◇°) Remember the hashtable we created earlier? It’s time to upgrade it. In the Env table we are storing two things. Vars and functions.","\u002Fapi\u002Fmedia\u002Fposts\u002Fneeded-11-built-a-functional-programming-language-de9b9b86\u002F8.webp",{"local":51},{"headline":54,"body":55,"imageUrl":56,"images":57},"But what are functions? As far as our","But what are functions? As far as our evaluator is concerned, it is a thing that consumes arguments on one side and spits out a result on the other. The initial idea was that they would just be pointers to C funcs. Seems simple enough. But there is a huge problem with this: how do users write their own functions? But there’s another problem.","\u002Fapi\u002Fmedia\u002Fposts\u002Fneeded-11-built-a-functional-programming-language-de9b9b86\u002F9.webp",{"local":56},[],[],{"name":61,"url":62},"Hacker News","https:\u002F\u002Fhereticpleb.vercel.app\u002Fblog\u002Fneeded-one-plus-one\u002F","en",{"handle":65,"displayName":66},"spots","Spots","queued",{"views":69,"likes":70,"saves":70,"shares":70,"completions":70,"opens":70,"skips":70,"depthSum":70},1,0,"2026-09-30T01:12:35.259Z","local"]