> 2. It makes no sense to invest in development of only-for-Rust GUI libraries. Just use in Rust something ready that has stable plain-C ABI. And so people from C/C++, Delphi can use it too. That would be more robust on the long run.
Disagree. Anything that uses a C ABI has to keep track of ownership externally, and that tends to be error-prone; you end up with excessive copying, leaks, or both. And this is a particularly thorny problem for GUIs because, as you say, ownership of GUI objects can be complicated. So it makes a lot of sense to have a Rust-specific GUI library that leverages Rust's ownership-tracking capabilities to make this easier.
Sure, but at the cost of not being able to share logic between the two layers and giving up most of the advantages of native UI. For example, you can't have an encapsulated component that combines user input with validation that comes from the business logic - you'd have to have an input box that sends a message to the business layer when the user inputs a value and then the business layer does the validation and sends a message back.
Again, we are doing the messaging for years now, AJAX/REST are messaging protocols ...
I am not saying that this is the only way...
In Sciter you can use custom native UI components extending existing DOM - they can handle event, do custom painting, etc. And you can design those components in Rust, C, Go or whatever you like.
Like I said, you're no longer encapsulating the validation in the component, where it logically belongs from a business point of view. You're being forced to distort your architecture for these operational concerns. And it gets worse as your structures and UI get more complicated - e.g. if I want to validate several fields within a single database transaction, that's the sort of thing that Rust's ownership system is ideal for - each datastructure can know how to validate itself given a borrowed connection handle.
> Again, we are doing the messaging for years now, AJAX/REST are messaging protocols ...
Yes, and the overhead of having to serialise everything is the biggest problem with web UI. If you're going to separate the UI from the business logic like that then why even bother making a native UI at all?
I'm actually playing with a message-passing-based UI system right now, mostly
as a prototype; long story below. I'm making it considerably more Erlangy than
yours -- essentially, you have message-passing with a sequential/direct-style
interface on top of it, so one can write code like:
(send-to foo '(:bar 1 "foo"))
(setf val (recv))
(format t "~A~%" val)
(send-to baz `(:thingy ,val))
The basic idea is, you have some set of primitive widgets (e.g. :text, :image,
:text-input), which are "just data," like in HTML. Components, rather than
being objects or functions, are instead actors. Other, non-component, actors
would exist as well, including a compositor actor associated with each window,
which you would be sending messages that look like:
Below that, it places... whatever OTHER-ACTOR's current render tree is. Other
than having its name, the actor sending this tree doesn't need to call into
OTHER-ACTOR at all.
The compositor is in charge of gluing together the tree fragments,
laying them out (with Cassowary), "legalizing" them into primitives the
current platform supports, and displaying them to the screen. It also sends
back input events to the actors involved, probably with some
CALL-NEXT-METHOD -like primitive to opt into bubbling.
This lets the compositor operate concurrently with state updates to
components, and components to operate concurrently with each other. This is
good in the general case of "new processors getting more cores, not higher
clocks," and especially since I'm going to be using this mainly on ARM
devices, where this is especially true, and being able to split computations
to work with big.LITTLE is a huge win for battery life.
I think this also should help quite a bit with ensuring a user interface
remains interactive while performing lots of work, if I were to implement
preemption (or context switch checks often enough to act like preemption is
occurring, like Go has historically had). The only bottlenecks where the whole
interface can get stuck are in the compositor, and the only expensive thing
there is Cassowary. And if that's fast enough for Apple, it's fast enough for
me.
Once this is in a state where I can take pretty screenshots (okay, considering
my aesthetic taste, not too pretty...), I'll probably submit a blogpost
version of this here with code samples. If you wanna discuss this beyond the
length HN makes convenient, feel free to drop me a line on
https://lists.sr.ht/~remexre/public-inbox (~remexre/public-inbox@lists.sr.ht).
Long story:
I recently got a PinePhone, and I'm experiencing keyboard latency that makes
it incredibly annoying to actually type on it. I only use a small handful of
apps on my phone, most of which have CLI or library equivalents, so I figured
it wouldn't be that much of a loss to reimplement crappy versions, if I at
least had a nice keyboard. (Plus, my old phone isn't actually broken yet, so
instability here isn't as big of a problem as it might be otherwise.)
So, I reflashed it to a non-graphical build of Arch Linux ARM, and set up SBCL
with Swank on it, with the intent of making a new interface to replace Phosh
and the apps that run under it. This has the pretty nice effect that I can
live-edit code that's running on the phone itself from Vim on any of my other
machines (or even several at once, if I want). Plus, Lisp itself has great
performance relative to other languages that provide this level of dynamism.
Lastly, since it's set up as a systemd service, even when I mangle EGL state
enough to get a segfault, it restarts and generally Just Works Right.
I've been meaning to try out this concept, but always meant to implement a
custom language that looks more like Erlang semantically to do it with. Using
Lisp lets me buck Greenspun's tenth rule, though, and forces me to avoid
spending a year implementing my own efficient code generation. Plus, Lisp
already runs great on my phone.
I am probably performing the do-notation transform with a macro, though, to
allow for the green thread implementation I need for large numbers of actors.
Alternately, I could use cl-cont, but I'm not sure that I want continuations
exposed to the programmer.
Disagree. Anything that uses a C ABI has to keep track of ownership externally, and that tends to be error-prone; you end up with excessive copying, leaks, or both. And this is a particularly thorny problem for GUIs because, as you say, ownership of GUI objects can be complicated. So it makes a lot of sense to have a Rust-specific GUI library that leverages Rust's ownership-tracking capabilities to make this easier.