Would it be possible to use Rust to create a DSL based GUI framework like Flutter(but in and for Rust)

This is a thought experiment.

I know you can call Rust in Flutter, but I was wondering if one could if one put enough time into it, create a DSL based GUI framework like Flutter, but written in and for Rust lang.

I'm asking because OOP based GUI frameworks don't seem to be a thing for Rust because of borrow checker or not having enough OOP?(I'm not sure which)

Do the same problems also disqualify Rust from having a DSL based GUI framework which I assume Flutter is.

More details in a simple to understand manner would be appreciated. Thanks!

Also, are DSL based frameworks like Flutter light weight unlike ECS which requires high RAM?(Can't be implemented in 80s PCs)

I'd say https://slint.dev is what seems closest to that idea.

Though, I'd say it is still pretty far. The thing is, DSL and even the Dart language itself are not particularly interesting aspects of Flutter, there are there because you need some kind of language.

Flutter's secret sauce is the runtime, the system where you have AOT, JIT, and also live-reload that just works. Live reload in particular is something you can perhaps 60% retrofit into an existing system, but, to get to the 90%, you need to design for it from the start.

So, I'd say you can replicate pretty much the entirety of flutter in Rust, sans the runtime, but its the runtime bits that make Flutter interesting!

3 Likes

Sorry, this one stuck out to me: does ECS really require any more RAM than OOP GUI approaches? I don't have any real examples of using ECS for GUI - even bevy's most popular GUI is just slapping egui on top, and that isn't ECS, so you might be talking about a vdom or immediate mode, but in case you are, this is an area I've been on the lookout for...

In theory, ECS should be capable of being more memory efficient than OOP, but maybe at the cost of being less CPU or memory bandwidth efficient, depending on what approach you take, since it doesn't necessarily need a bunch of pointers to compose things together. The trade off is that it's far more complex to get the same result (to the point we don't really have any great examples still) and the main benefit is a better utilization of hardware memory access prediction, something that basically didn't exist in the 80s (since memory was so much faster than the CPU anyway).

1 Like

As annoying as browser-based GUI can be, I currently think it's the best solution outside of special cases like game engines that already have a distinct world and custom rendering pipeline that you'd like the GUI to integrate well with. Browsers are highly optimized for the purpose of displaying custom interactive UI, so it just makes sense to take advantage of that. And if you're using a browser based UI system, then it's reasonable to stick to an API paradigm that's more directly compatible with the WebIDL data model.

If you don't just reuse an existing system, you have to ask yourself how much of the existing system are you just going to reimplement, and is it really worth it? Sometimes it very much is! But generally it isn't.

I'm not free from sin; I very much enjoy reinventing the wheel from first principles. But I do it in order to learn, knowing that the intrinsic value to new systems is negative. It takes a miracle to get anyone to move from ab established system to a new untested one.

The answer is always yes. Rust is a Turing complete general purpose programming language, so you can do anything with it that you could do with any other programming language if you put enough effort in, with very few caveats. Although "with enough effort" is doing some very heavy lifting if all you know is that a language is Turing complete.

Rust has GTK bindings, and GTK is an OOP-y retained-mode GUI system that provides OOP-y functionality to Rust through the same system that it does for C. Rust isn't particularly well suited to OOP, thus the general trend of more Rust-first tools to pick different paradigms, but as much as OOP based GUI is well understood, OOP isn't a particularly great choice for GUI either; if you take a general survey of the "hot new thing" options in UI, while most do have OOP-y underpinnings, most also have a veneer which is distinctly not retained-mode OOP-y.

The Rust community has a strong inclination to pursue strongly "correct" designs, even if that means rejecting a body of existing practice... at least when rewriting in Rust. If you want something like an existing system, you'd be better off just using the existing system and its existing body of support. If you're building something new, it's much more worth it if you can do something better than the existing options.

In the abstract, no, or minimally so. It's very easy for simply implemented ECS solutions to have more wasted RAM, though (e.g. using dense component storage when utilization is sparse), and established OOP-y toolkits have generally picked up optimization over time to manage RAM bloat. At a minimum, GC runtimes have much smarter allocation tuning to use to optimize for common OOP GUI patterns than Rust can do with its general purpose allocator.

I haven't been following it, so I don't know how far along it actually is, but the first party bevy UI project is fully embracing ECS driven UI. But also bevy has been and I expect will remain somewhat stuck in the "feels like a research project" stage for a while yet, so while I have hopes for what it can eventually become, I'm not particularly inspired by the the short term.

Also, bevy UI is expected to be more focused on the "redraw everything every frame" usage, since games are redrawing everything anyway, but GUI for other purposes really would prefer to have reactive redraws that only does work when something changes.

After all, in the limit you can look at and use ECS as a weirdly shaped GC to just do the OOP patterns in. It's not the most optimal way to utilize ECS, but it works surprisingly well.

This reminded me of this article: Proving Immediate Mode GUIs are Performant

There's more trade-offs than just performance, of course, but it's still encouraging to see performance concerns are not necessarily an issue.

1 Like

just FYI, makepad could be an interesting one too.

it takes an "hybrid" approach: on the one hand, you can define the ui tree separately from the action code, similar to classic retained mode GUIs; on the other hand, the data are owned by the application state, and you pass the data to the widgets only when you draw the ui tree, and also, the events are handled in a centralized place (as opposed to attaching "callbacks" to each individual event), which is akin to immediate mode GUIs.

to me, this design looks more like immediate mode: the app is responsible to draw the ui widgets, and redrawing the ui is part of the event handling logic (drawing is just an event type); yet it's not purely immediate mode, e.g., there's a data binding model, which resembles the old-style retained-mode GUI, so you don't need to write event handling code for every single ui element like pure immedate mode, and most importantly, it can support sophiscated layout that are very hard (or impossible) to do in purely immedate mode GUI.

something interesting to mention, not only does it have a DSL for UI description, but it also has a DSL for a customized shader language to render the UI widgets.

here's video introduction, which is both inspiring, and entertaining to watch:

EDIT:

here's a more recent talk:

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.