Show HN: Wyzer Programming Language
github.comafter 5 months of research and a few weeks of development i am soon going to release version 0.1.0 of it, if you would like to contribute to it you're most welcome!
after 5 months of research and a few weeks of development i am soon going to release version 0.1.0 of it, if you would like to contribute to it you're most welcome!
However, your light is hidden under a basket, to use an old metaphor. I'm having to go digging to find the genuinely new things going on. I suggest recalibrating the entire documentation with a focus on the new stuff. People on HN often complain about not having syntax examples front and center but I would say for you, the very first thing I you should be hitting your new visitors with is the choreography idea.
Set up a simple example of doing something like a concurrent remote counter that is atomically safe by the construction of your language and immediately dive in to what that means. Forget even educating us on the rest of the mundane syntax of the language, immediately dive in to what that is and what that means. I see in the docs/ dir that it probably hurts your programmer mind to cover the choreography before covering sections 1-8, but you can safely assume that if you intrigue with the choreography that they'll hang around to learn about the rest, whereas you can't safely assume that a new reader will wade through all the rest of the relatively mundane details to get to the really interesting stuff.
A modern language with a modern take on compiling a "program" that takes a unified view of the world at the programming language level, and then emits a "server" and a "client" (and perhaps other roles) as separate executables is a pretty nifty idea. Hit it early and hit it hard.
The choreography stuff is actually really cool! Definitely agree this should be front and center
Nothing worse than PDFs full of theory and no working examples of the thing you’ll actually be doing all day.
I get that it’s important to show what abstractions and methodologies can arise out of using it, but with a good example that would be obvious. It’s the developer community using the language that will come up with the best abstractions (libraries) that - if it has an active community - helps shape what those novel developer experiences are.
A good analogy is the development of the skateboard - released first as a scooter - until someone knocked the handle off a started “surfing” down the street. Just show me the thing. I’ll tell you if it’s cool and how to use it
Should be the header.
Newer is not always better. Lisp is full of good ideas that haven't stopped being good, even if a pure Lisp experience is understandably not to everyone's liking.
We definitely fell into the author’s trap of structuring docs "bottom-up" (Prerequisites -> Basic Syntax -> Advanced Concepts) rather than leading with our actual core innovation: choreography.
We are restructuring the main README/docs front page right now to lead immediately with a concrete example of choreographic execution (e.g., atomic multi-node orchestration / client-server emitting) before getting into standard syntax.
Really appreciate you taking the time to dig into the docs/ dir to pull this out it’s a huge help for our presentation.
The next thing is, I need more examples. Read me documents can scroll forever and that’s fine. Add examples for every concept your language wants to cover to it. This is your chance to think things through and make the read me and the language astonishing.
And your AI disclaimer (or your AI’s disclaimer) makes sense.
What stops a choreography where Claire send a message to Bob but Bob is waiting for Alice and Alice is waiting for Claire?
Is it like Rust memory safety where not all valid programs are accepted but all invalid programs are rejected?
I think some examples of the distributed code in action on a trivial and non trivial distributed example is more compelling than a 3d donut render
The protocol doesn't describe "Claire sends" and "Bob receives" as two independent actions that wait for each other, it describes them as a single communication in the global program/state.
When it gets executed into code, every send already has a corresponding receive by construction, so you can't write something like "Claire sends to Bob while Bob is actually waiting for Alice" unless the protocol itself allowed that execution.
So the cycle you're describing can't just accidentally appear because of sync issues, because the assumption is a communication is represented correctly at each turn.
So yeah it kinda does limit the set of all possible programs since I would expect not everything can be encoded this way also seems hard to resolve this in practice without only allowing communication b/w Wyzer systems.
I am not very familiar with this topic in practice so OP would be the best person to answer this, I am quite intrigued by how it works in practice as well.
A choreographic programming language features programming abstractions for programming communication intent. For example, often they have a primitive like:
Alice.expr -> Bob.x
read 'Alice communicates the evaluation of expr to Bob, which stores the message in its local variable x'. (In fact, we discovered that we can extend any mainstream language to have this kind of high-level primitives by extending data types with locations, see choral-lang.org).
This makes it impossible to write mismatched communication actions, because you're expressing both the send and receive actions in a single atomic instruction: they are well-matched by construction. You then build a compiler (typically called 'projection') that generates distributed programs for Alice and Bob -- the former doing the send to Bob and the latter doing the receive from Alice. We like making formal models of these compilers and mathematically proving them correct. A compiler that respects the choreography then automatically entails deadlock-freedom of the compiled code without the need for complex checks, because the source choreography cannot syntactically express deadlocked terms.
Consequently, there are no deadlocked distributed programs that we can compile from choreographies. It's an application of the neat trick of designing high-level languages for 'guiding' programming: instead of programming a distributed system with low-level primitives and then attempting the generally very hard task of checking for deadlocks, we use a high-level language where deadlocks cannot be written (or are at least easy to check against).
The above hopefully explains the intuition of how choreographic programming works. But then, as you did, one naturally asks: What can we express in choreographic programming languages? Are there fundamental limitations?
We do not know exactly yet; this is an area of very active exploration. Over the years, people have developed more and more clever choreographic programming languages that capture more and more interaction patterns.
What's perhaps surprising is that, for some theories of distributed languages (or interaction patterns, if you like), we know that choreographic programming is complete, in the sense that it can capture all deadlock-free systems that can be modelled in those theories. The first result of this kind was about capturing all interaction behaviours that can be described in linear logic (in the Curry-Howard interpretation of it with process calculi), but there are also works that can deal with recursive behaviour and even process spawning (fork). That's encouraging.
I think that investigating what the paradigm precisely can and cannot do is fascinating (but I'm very biased here..), not least because using a mathematically-modelled compiler lets us optimise the generated code aggressively (e.g., adding more asynchrony, as in Ozone). From the state of the art already out there, it looks like choreographic programming is 'expressive enough' for many different purposes. Hopefully it's gonna be the typical situation with high-level abstractions, whereby for most cases and most people the high-level language is gonna be good and low-level communication actions will be necessary only in niche scenarios. In the meantime, there are choreographic languages that can be integrated with middleware and foreign APIs to cover up for deficiencies (like Choral, HasChor, etc.).
Too bad the github readme doesn't explain how the choreographic side of Wyzer works, or even what it looks like (please correct me if I'm wrong, couldn't find it after a quick skim).
Where’s the cool stuff?
In there it says you started this journey when you were 8 years old and that you are a 14 year old programmer
I'm not sure how I feel about this to be honest, I need to process that.
1. The v0id_isgood HN user impersonated the actual creator of Wyzer and posted this Show HN.
2. The v0id_isgood HN user then left the credentials to his HN account in the Wyzer discord.
3. Now the real creator of Wyzer is apparently using the v0id_isgood account to answer questions here?!
What's going on? This whole thing feels like a really strange hoax.
const MAX: u32 = 100; // Compile-time constant
let x: u32 = 10; // Cannot be changed
If x cannot be changed, how does it differ (meaningfully) from a compile time constant in a safe language, ie in a case of no raw pointers> 1. What Wyzer Is, In One Paragraph...
> 2. Why Make a New Language At All?...
Far too often I see projects on HN where, on a casual skim, I just can't figure out "the point." This is clear and concise.
---
One of the issues with "Writing one network rule that creates code for every computer. We borrowed this from academic research" is that often it's hard to have the same language on every computer. For example, for a web application, you're either going to have to transpile to Javascript or target WASM. (And WASM has a lot of overhead compared to Javascript.)
Definitely a cool idea. I guess time will tell whether lifting it into the language proves itself as worth it.
It does not. The term "garbage collectors" covers a whole spectrum of algorithms, some might slow you down (though not for the reason you may think) while others were invented to speed up memory management beyond that of C++, in exchange for other tradeoffs. Python's (mostly) refcounting GC is actually closer to C in its memory management overhead than to either Go or Java. It's also not what makes Python slow. Go uses a mark-and-sweep collector to find a balanace between speed, FFI, and footprint. Java uses moving collectors, which are faster - and some of which are even more predictable - than memory management in C++. That's because Java aims to offer better performance than C++ in large concurrent software, where low-level languages tend to suffer from various overheads due to their requirement for low-level control (Java trades off some performance in smaller programs, but mostly it trades of startup time and footprint). Moving collectors (but not refcoting collectors or mark-and-sweep collectors) are an optimisation over free-list approaches, not a compromise for convenience.
So it is true that slow programming languages tend to use some kind of GC, but that's not what makes them slow, nor does it make the super-fast languages that also use a GC (often of a very different kind) any slower. The range of languages that use GCs covers everything from the super slow to the super fast.
ps: were you looking at efforts such as clojure electric (https://github.com/hyperfiddle/electric) ? they aim to represent computation on different hosts as one expression.
What happens if the piece of data has multiple owners? Do you get sudden performance bugs which are hard to debug?
Most of the important stuff is in this section:
```3. What's Actually New About It?```
But you don't really go into any details about what's actually happening, have any honest conversation about any trade-offs, mention anything about why this is memory safe & correct now (highly skeptical), or why you have a clear path towards that in the near future.
From the VERY brief examples you show, it looks like it's just Rust without a borrow checker. The borrow checker gives Rust a bad reputation, but it's only a very small part of why Rust is hard. You didn't give any insight into how you're solving the rest of the problems.
Is choreographic programming the same as session types?
Is mut a thing? looks like rust.
But .. your language mostly hide when you're doing an 'inside' function call or an 'external' function call. I'm not sure I like this; 1) the latency of both operation is very different so you want to minimise the number of 'external' function calls 2) what happens in case of 'timeout' for external function calls? I didn't see it in the doc, did I miss it?
Can you you give a hello world example in each of them and show where your languages shines?
Promising insofar as all of the essentials seem to be right (for me): compiled, good type checker, no garbage checker etc.
https://felix-tutorial.readthedocs.io/en/latest/intro_corout...
Note this is for cooperative threading.
> The one rule is that once you use a resource, you cannot use it again
What about data structures which need to be shared? Can I use some sort of mutex for them?
It's "pretentious."
(said pretentiously, lol)
Hey, at least we know AI didn't write it, lol
Also I really like that somebody said that Rust syntax is complex and too hard to learn. So many unreadble things. However Rust did good think about fn keyword - it fits better than fun, func, function keywords. I hope you will not choose path where every 2nd word is abbreviated.