Noulith: A new programming language by the current Advent of Code leader
github.com
github.com
What's going on here? Are they just extra motivated to show off their languages? Is making your own programming language more common than I realized?
EDIT: same with the 4th place person[^2]
EDIT2: same with the 7th place[^3]. Btw this is the 4th person that's clickable so actually 3/4 leaders with their GHs linked have their own programming languages
EDIT3: jonahx pointed out I made a mistake and the 2nd place person didn't actually create Vyxal, just used (and contributed) to it
[^0]: https://adventofcode.com/2022/leaderboard
[^1]: https://github.com/Vyxal/Vyxal
* Making a programming language is like solving a puzzle.
* People that like solving puzzles like puzzles of all kinds, so the likelihood of a top advent of code solver to also have worked in the "puzzle" of making a programming language is big.
Feels pretty logical to me :-)
> Is making your own programming language more common than I realized?
yep it's just that
I'd assume that it's similar for others in that their programming languages aren't up to date or practically usable, but more like cool side-effects of their learning journey.
People who’ve made compilers and interpreters are both attracted to the problem solving element of AoC and good at solving those problems.
Beyond that, making your own compiler or language is fun — more people should try it.
These are great starting points:
Obviously, the OP targeted their language for AoC because, come on, whoever would want to have the ability to swap the precedence and meaning of operators? That would be a fresh hell that would make early-90s abuse of operator overloading in C++ seem like a joyful time.
I still had to restart the REPLs from time to time! I came to the conclusion I enjoy more a language with near 0 startup time as opposed to live environments. Extremely loose typing is not a good compromise for me... but I also came to dislike the "straight jacket" of extremely strict types systems (like Haskell's and friends!).
I think these days Golang is a good compromise between practicality and safety. It's fast, cross platform, it now supports generics (since 1.18) and it is overall OK to work with. I feel it falls in an OK sweetspot of features.
depends what you do, but many Lisp-based live environments have a near 0 startup time in a terminal. Try SBCL (a version of Common Lisp providing fast native compilation, incremental and batch) for example. SBCL also saves all memory (on demand) and can restart it, so one is in the same environment in milliseconds.
I did play with SBCL a bunch, and other a bit more "esoteric" lists too! [0]. I just feel like langs that are not in some form of top ten and with big corporate sponsoring are pretty much always super behind when it comes to tooling.
You can get one or two or three AMAZING golang IDEs to work with (VS Code with Vim plugin is what I use). For SBCL, it HAS to be emacs. And I have mixed feelings about emacs, even when using Evil mode.
--
PS. I know I know it is the other way around... it is just an attempt at a joke :-)
No, that's not the Nim[0].
I actually haven't come across any markdown flavors that support references and don't use a carrot
If you've written your own language, assuming it's a decent one, then:
a) It has all the tools you need to be productive.
b) You know exactly how it works and what the APIs are (assuming the implementation details are still fresh in your memory).
c) The features are tailored to exactly how you like to use them, personally.
IMO, high-speed competitive programming is part knowing your tools well, but also a lot about coming up with abstractions on the fly very quickly. If you watch the top Advent of Code solvers they'll carve up the problem in seconds, and they're really good at picking just the right amount of complexity for the problem at hand and not investing any more than that. Coupling that with a touch of cleverness ("let's eval the input", "who needs a tree when I can shove everything into a dictionary") and a very low error rate (I would hit the leaderboard but almost always lose a significant time to debugging…) and they come out on top.
Any recommendations of who/where to watch? I’d love to see what their process looks like.
Python is a very popular language to use in AoC. My theory: If Guido van Rossum were competing, he would not be on the leaderboard at this point.
He certainly knows Python much better than everyone using Python who is currently on the leaderboard.
He wouldn't be on the leaderboard because "knowing your tools and standard libraries" is only a small component of what makes you good at competitive programming.
The first time I did it it forced me to fix some major problems. My language would still be a handicap for me now, albeit a comfy one.
fwiw: https://github.com/darius/cant/tree/master/examples/advent-o... (haven't done this year's so far)
On a sidenote, I've had a good time reformatting input as python expressions and using eval()
I do have my own programming languages though; my best one so far is proton[^0] though it's pretty buggy because I wrote it in high school before I took the uni-level CS classes that taught things like language design and how to make actual parsers.
By the looks of it right now, Betaveros will win 2022 too. One could say that Betaveros dominates AoC.
Example of solving a (non-AoC) problem: https://youtu.be/i_zDbInYOpQ
One of my big takeaways is that the "IDE" plays a big role in how fast you can solve. Recomputing the expression on every keystroke seems a little insane, but the instant feedback you get is priceless.
In my opinion AOC is a very good example for "if all you have is a hammer". For AOC you don't need to write a program that finds a solution for any possible input, you need a calculator to compute the solution for your input. This is such a calculator, and a very nice one.
Suggestion: Flip the assignment operator. You keep writing an expression left to right, but then you have to scroll all the way back to the left to make a variable. This could be streamlined by making it e. g. "EXPR -> VAR_NAME" instead of "*VAR_NAME EXPR".
Why don't you make a Show HN submission? I'd upvote you. :)
Why not not immutable variables?
About 90% of my variables I only assign once, even when writing ordinary imperative (not functional) code. Wehever a variable is re-assigned that usually is a mistake or or something unexpected going on.
I find it maddening most of the languages don't have single-assign values like Scala's val (const doesn't count because you can't initialize it with a runtime-computed value).
In what language? C's const is an unmodifiable runtime value for example, as is Zig's. Go is one language that I can think of where const is compile-time though.
Bjarne's book calls these immutable variables "constants" which is completely crazy, but I guess indicates that the name is on purpose. This leads to the usual C++ insanity shortly afterwards in the book...
> An object that is a constant when accessed through one pointer may be variable when accessed in other ways.
Yeah, no. If the object were actually constant you can't do that, your language has betrayed the poor programmer. You can't "access" constants, you can use them to initialize variables, parameters, and so on, but they can't be "accessed" and that's where you've gone wrong here.
Rust's Quiz has a example showing what happens with actual constants, and it's not that
I do agree that "immutable" would have been a better name, but I guess that angle hadn't been invented yet. :)
Immutable variables are a good idea (indeed I agree with Rust's choice to make variables immutable by default), but, they're not constants, and so this is an unnecessary confusion.
Different people will have different breaking points about when things have been stretched too far, meaning they are not willing to compromise on. Working with people who have not the same level of flexibility or rigidity or differ in different contexts can be a day-to-day pain.
int x = 0;
int const *px = &x;
++x; // *px changed
There's no way to indicate true immutability in C++, unfortunately. The language does decree that any object (which in C++ parlance includes ints etc) with a const type cannot be mutated without triggering UB; but there's no way to declare a pointer or reference that can only point to such objects.Source: I do that all the time when trying to solve AoC problems :)
Compare Rust's for loop:
for k in 0..10 {
// k is an immutable variable, brought into existence for one iteration
// next time around the loop that's a different immutable k
}
Versus the C for loop: for (k = 0; k < 10; ++k) {
// k is a long-lived mutable variable, we can change k inside the loop and it'll remember!
}
We can tell Rust we want a mutable variable, if we want, but it's not the same: for mut k in 0..10 {
// k is a mutable variable...
// but still brought into existence for each iteration
// changing will work in this scope... but it won't last
}But it sure looks like a map where we throw away the result. What I mean with that is that the loop construct must be served the iterations from an iterator, which may or may not use immutable data. I don't think you can make an immutable while loop, for example?
EDIT: Also, you better have a side-effect in that construct, otherwise it has no effect, right?
Which is an interesting take on the concept of domain specific language.
Did they get banned or couldn’t they keep up with the puzzles?
Interestingly, it still produced internally consistent solutions with valid Haskell code, they just didn't have much to do with the given problem. And I feel like that sums up one of the main issues with ChatGPT quite well: if you scrolled through StackOverflow and saw a really polished solution for something, you'd assume it was mostly correct, because for people, 'visible effort' put into code usually correlates with correctness/ourselves. But ChatGPT always produces really polished solutions really confidently, even if they are complete nonsense.
No such luck with ChatGPT.
IME, that should, at best, be a very tentative assumption for StackOverflow.
Heck, for me it is also a very tentative assumption when I see a very polished solution in official documentation from lots of providers (AWS, I’m looking at you.) Though in that case I assume it was correct at some point in time, for some (possibly not publicly released) version of the software/service.
There's a video of Harstem I think, following build orders ChatGPT came up with for Starcraft II. ChatGPT doesn't say "I have no idea how to play this game" instead it confidently offers advice that is... not good. Harstem wins at least one game anyway, but you know, not from the great advice just from being a good player.
I managed to get 47th on one of the days once... and that was after solving it in under a minute.
That depends a lot on the day. Towards the end it takes longer. Today's 47th place solved the problem in 11:54
If you check the results for the events the last couple of years, you see the same set of persons being up at the top 10-20. Basically solving hundreds of problems. Problems that span a quite a large set of CS, math problem domains.
The language doesn't look bad in comparison to a lot of others, but the combination above is a nogo for me when it comes to any kind of production code.
Your criticisms are valid, but only if you're approaching it from the perspective of using it for a full-fledged project.
More likely use cases are quick scripts you wanna write or little thought experiments you wanna try out. For that, it's likely a great choice of language
Although the creator demonstrates this with `*` and `+` I could imagine this being useful within a set of higher level operators (functions)
eg. perhaps you want an argument of (infix) `map` to evaluate before `map` itself
Or more generally, you might have a bunch of scalar operators which you'd like to have higher precedence than collection operators which should act on the results
Or I'm probably missing something.
Being able to customise how they compose (through precedence) lets you build a kind of DSL for your problem space
No idea how often that would be used - but I can imagine hobby scenarios
What's the interplay between infix notation and operator precedence? Expressions are not infix?
Also, please explain the dictionary and set duality.
FWIW, in my toy language, I use one syntax for sets, lists, and arrays, delimited with brackets '[' and ']'. Whereas maps, dicts, and (prototypical) objects use curlys '{' and '}'. A la JavaScript et al.
Lastly, wrt using '++' for concatenating lists, there have been times I've wanted sugar for prepending to a list. So maybe support both 'atom ++ list' and 'list ++ atom'?
For future updates, please us posted.
I'm not sure I follow the question about infix notation and precedence, but: Trains of identifiers like `a b c d e f g` are always parsed as `b`, `d`, `f` being infix binary operators; their precedences are looked up at runtime to decide how that expression evaluates. Explicit function calls and indexing always bind more tightly, and operands in those trains can contain either; an expression like `a(arg) b c(arg1, arg2) d e[i] f g[j:k]` has the same binary operators as before. But operators are only single identifiers and don't contain function calls, so `a b (c)` is still the binary operator `b` with arguments `a` and `(c)`.
"Sets" are just dictionaries with set elements as the keys and null as every value. This makes sense because you want testing for set membership to be fast like locating a key in a dictionary and because, like in Python, iterating over a dictionary iterates over its keys.
We also already have `.+` for prepending a list element to a list and `+.` for appending. (These are the analogues of Scala's `+:` and `:+`.)
I can happily report that I now know the equivalent feeling to driving too fast over a speed bump, but for reading.
What fantasy world is this? :D
Competitive programming teams, afaik, exist in the context of universities and they want to win ACM-ICPC, that's pretty much it. Otherwise, competitive programming is largely a solo affair.
In an event that yields no prize whatsoever, winning is just for bragging rights. There are no bragging rights in winning as a team against solo competitors.
Also, you only have one problem per night and AoC problems are too easy for it to make sense to have a team collaborating. The only thing a team would do is take the minimum solution time of their participants.
I might implement it in C, as soon as I get some time.
Waiting for someone to tell me there ain't anything wrong with 12k lines in a single source file, yet for some reason other utility functions get their own file.
Also FWIW most software you use has 5k+ line source files in it.