6 ms·
Hey folks. I'm the creator of jank. I didn't expect to be on HN today, but I appreciate the interest. In short, jank is Clojure, but it's on LLVM and has seaml
by Jeaye 1y ago
Hey folks. I'm the creator of jank. I didn't expect to be on HN today, but I appreciate the interest.
In short, jank is Clojure, but it's on LLVM and has seamless C++ interop. You still get full nREPL capabilities, can redefine anything on the fly, and we can actually JIT compile C++ code alongside your Clojure. The seamless C++ interop is first of its kind, for a lisp, and is done by JIT compiling C++ alongside the LLVM IR we generate for jank and then stitching them together into one IR module.
Note, jank isn't released yet. I'm targeting the end of this year for the first alpha release. I put out monthly development updates on the jank blog, with the next one coming out this week.
- dzonga 1y agobeautiful work. clojure is very nice. one of the most impactful talks I have ever seen was from Rich Hickey - simple made easy. however my only gripe with clojure while it's easy to write and comprehend at first - it's difficult to read. & yet most our time we read code not write it. but then again it might be my lack of brain power.
- barrell 1y agoMy 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)
- NeutralForest 1y ago> Conversely, a lot of time I can condense hundreds of lines of equivalent python into 5 or 6 lines of Clojure. I'm curious if you have any example of this? Even if it's an hyperbole, I don't really see how.
- d4mi3n 1y agoIn my (limited) experience with Clojure and other functional languages, this is usually true under situations where: 1. You’re mapping or reducing some dataset 2. Your iteration logic does not branch a lot 3. You can express your transformation logic using higher order functions (e.g. mapping a reduction operation across a multidimensional array) Some domains have a log of this style of work—finance comes to mind—others do not. I suspect this is why I’ve personally seen a lot more of Clojure in finance circles than I have in other industries.
- barrell 1y agoMaybe 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)
- cess11 1y agoCould you show an example or two between Elixir and Clojure?
- barrell 1y agoThis 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.
- lisbbb 1y agoThat's great, and I agree, but nobody really cares is the problem. They don't care about brevity and LISP is a really hard sell outside of those who "get it."
- Jeaye 1y agoI agree with you, but perhaps in my own way. Jumping into an arbitrary Clojure program can be tough, since the data shapes may not be defined anywhere. Hopefully the program uses spec or malli, but even then, unless they annotate every function with the shape it expects, you may be left needing to REPL in and poke around. However, REPLing in to check just a function or two may not be easy if the program requires some setup and doesn't use integrant or similar. Once Clojure parity is achieved, I'm interested in static typing, pattern matching, value-based errors, and some other opt-in improvements that I think will greatly improve both readability and toolability (i.e. how well tooling can work with the code, based on what it knows of the code). Stay tuned. :)
- thethimble 1y agoWhat’s your take on Hickey’s talk titled “Maybe Not” which fundamentally criticizes static types? Is there a middle ground where some form of static typing makes sense in a Clojure-esque world? https://youtu.be/YR5WdGrpoug?si=4mI8doBX6jj6PJkk https://youtu.be/YR5WdGrpoug?si=4mI8doBX6jj6PJkk
- Jeaye 1y agoRich has many great ideas and he founded Clojure. I respect him deeply. On typing, however, we do not agree entirely. For a practical example of a Clojure-like language with a completely static type system (with affine typing), see Carp. https://github.com/carp-lang/Carp https://github.com/carp-lang/Carp I don't see why there can't be a Carp mode in jank, with bridges in place to connect the Clojurey world from the Carpy world. This would allow jank users to develop interactively to start with, figure out their shapes, use the REPL, etc. Then, if they want, they can lock down some parts of the code for both performance and correctness gains.
- narnarpapadaddy 1y agoFWIW, (I have one Clojure project I inherited at work that my team maintains) I love this direction.
- 1y ago
- beders 1y agoYou need a REPL to truly read Clojure code. Could be a weakness or could be a strength. In my day to day work I consider a strength since I’m working at the REPL the whole day anyways
- lisbbb 1y agoIt's not difficult to read once you get writing it. My problem was getting other developers on board with it, which, ultimately, I failed at.
- binary132 1y agoI’m a bit curious why you chose to implement this as a different language (even though it implements Clojure) instead of an alternative Clojure backend and/or C++ syntax extension. Do you plan to make Windows support first-class? I think a lot of people looking at LLVM based languages are interested in alternatives to C++ for games.
- Jeaye 1y ago> I’m a bit curious why you chose to implement this as a different language (even though it implements Clojure) instead of an alternative Clojure backend and/or C++ syntax extension. jank is Clojure. However, the Clojure name is trademarked and using it requires permission which I don't have. Furthermore, I want to build upon the Clojure base to provide more, going forward. That may include static typing, value-based error handling, first class pattern matching, and so on. Those would be opt-in features on top of Clojure. All of these reasons lead me to not use Clojure in the name (like Clojure++, ClojureNative, etc). > Do you plan to make Windows support first-class? I think a lot of people looking at LLVM based languages are interested in alternatives to C++ for games. Indeed, a lot of game dev folks use Windows. Right now, jank's Windows support is limited. My initial audience is Clojure devs who want native access and lighter binaries. Once that launch has stabilized, I will focus on appealing to existing native devs who want to embed an interactive, functional language into their C++ applications. That will requires strengthening the Windows support, establishing stable native APIs, and writing the onboarding material for lisp, REPL-based editing, data-driven design, and so on. This is a much larger task, which is why I'm focusing on existing Clojure devs first.
- neutronicus 1y agoI commented to this effect on Reddit, but my interest is entirely conditional on ability to embed Jank into a pre-existing C++ application as a shared library. Ideally without controlling the code of the main application (e.g. to implement a plug-in).
- Jeaye 1y agoYep, this will be an important use case and will be officially supported. For the first alpha release this year, I'm focusing on Clojure devs, but support for existing native devs will come once things stabilize.
- twism 1y agoShouldn't it be an 'if' instead of 'when' in the first example?
- Jeaye 1y agoYes it should. Thanks for the keen eye and taking the time to point that out.
- no_wizard 1y agoWhy call it jank? It is a negative associated word in most contexts that’s why I’m curious about it
- amelius 1y agoI guess it stands out. "Git" is similar. "Rust" isn't a very positive word either. Perhaps it's a new trend. Maybe the answer is "all the good names have been taken" and/or they are simply lazy.
- graemep 1y agoNeither is as negative. This sort of name is more like Gimp. It is definitely a lot less negative than Nimrod (which is actually positive in origin - but Americans do not get biblical references) which changed its name. You can also get away with a lot more if you are Linux Torvalds or Mozilla.
- barrenko 1y agoI view "jank" similarly to "cracked", not necessarily negative.
- bgro 1y agoYep I won’t use anything with a negative self deprecating name like this. Because some tech bro will use it as a a basis to disqualify my entire resume or sabotage an interview after solving the leetcode trivia troll questions and whatever other video game battles they add to the interview process in the future. Project manager fires the entire team except 1 intern to finish the project with 1000 points of stories in 1 sprint? Heh or did you just figure out jank wasn’t capable of doing the job what did you expect? Hotfix to fix a bug with the stage environment because the SREs set it up wrong? No bro it’s jank it’s that jank thing. Source: ctrl F “jank” in the message analytics and copilot says all matches are in the stage environment and that jank is also a tech thing. It also bright up every engineers profile that lists jank as a skill. Time to pick a scape goat.
- athorax 1y ago
- benreesman 1y agoI don't have anything terribly insightful to say other than that I really like this project. I loved using Clojure back during it's brief time in the sun, it was a great time, and jank has all the same awesome vibes. I haven't used it on anything serious yet, it seems like it would be great for like a `zig`-flavored approach to C++ builds for example. I'm doing a big C++ project ground up at the moment, I think I'm going to get jank into it and see if I can automate some stuff. The compilation strategy is very much what Carmack did in Trinity and whether you got your inspiration there or independently had a great idea, that's good company to be keeping. Keep it up!
- Jeaye 1y agoI hadn't heard of Carmack doing something similar, but I will take that company any day. Thanks for the kind words!
- zamalek 1y agoI'm very excited about jank, and it's on my backlog.