11 ms·
Xilem: An Architecture for UI in Rust
- deleted 4y ago[deleted]
- patrickberkeley 4y agoRelated and possibly helpful: * How Glimmer.js implemented autotracking: https://www.pzuraq.com/blog/how-autotracking-works https://www.pzuraq.com/blog/how-autotracking-works * Discussion specifically on Lamport Clocks and autotracking: https://v5.chriskrycho.com/journal/autotracking-elegant-dx-via-cutting-edge-cs https://v5.chriskrycho.com/journal/autotracking-elegant-dx-v...
- rektide 4y agoAuthor Raphlinus has an incredible history of great, superb technical posts here, many which have spawned great discussions[1]. Referenced in this article are: Xi-Editor, discussed in Xi-Editor Retrospective[2] and Druid, discussed in Rust 2021: GUI[3], which follows closely after Principled Reactive UI[4] (describing a prototype for Druid called Crochet). > I have long believed that it is possible to find an architecture for UI well suited to implementation in Rust, but my previous attempts (including the current Druid architecture) have all been flawed. These have all been very very good & technical posts on what toolkits really support & enable ui (amid other great technical topics too). It's delightful seeing such an ongoing continuation, an evolcing refinememt of ideas & self-review from someone of such expert caliber. Rarely do we get such an intimate view into what the real hunt for rightness is, see how we ever hunt for perfection. Personally I believe that hunt for better is one of the undertold aspects of hackerdom, a less visible less knowable reciprocal to fast-and-dirty. Tapping & enabling this creative, knowledge & intellect based capability is a core spring from where greatness emerges. > I have studied a range of other Rust UI projects and don’t feel that any of those have suitable architecture either. It's also notable how widely raphlinus travels to get the best persepctive available. This post begins with a a vast field survey of other ui libraries & their origins. I lack the energy to search down & link HN discussions on each of these, for there are many! But seeing how everyone else is doing, looking wide & far to explore their peer's attempts, is also a notable characteristic I admire here. [1] https://news.ycombinator.com/from?site=raphlinus.github.io https://news.ycombinator.com/from?site=raphlinus.github.io [2] https://raphlinus.github.io/xi/2020/06/27/xi-retrospective.html https://raphlinus.github.io/xi/2020/06/27/xi-retrospective.h... https://news.ycombinator.com/item?id=23663878 https://news.ycombinator.com/item?id=23663878 (538 points, 26 months ago, 157 points) [3] https://raphlinus.github.io/rust/druid/2020/09/28/rust-2021.html https://raphlinus.github.io/rust/druid/2020/09/28/rust-2021.... https://news.ycombinator.com/item?id=24631611 https://news.ycombinator.com/item?id=24631611 (374 points, 31 months ago, 244 comments [4] https://raphlinus.github.io/rust/druid/2020/09/25/principled-reactive-ui.html https://raphlinus.github.io/rust/druid/2020/09/25/principled... https://news.ycombinator.com/item?id=24599560 https://news.ycombinator.com/item?id=24599560 (234 points, 31 months ago, 97 comments)
- dwmbt 4y agoit's... it's beautiful... wishing Ralph good luck! his blog posts have taught me sooo much in the past. i particularly enjoyed the disclaimer at the end, a lot of these Rust projects aren't production ready but learning about their respective architectures is a great way to passively consume 'academic' paradigms/concepts. if anything, this is what keeps me interested in Rust! i don't have a formal background in CS, so new projects and their inspiration serve as a great gateway into more rigorous study. edit: the potential for Python bindings is very interesting, it seems to me that Python and Rust are developing a sweet kinship :,)
- adamnemecek 4y agoIs this inspired by adaptron by any chance? If no, do you have an opinion on said work?
- raphlinus 4y agoAdapton is definitely an inspiration, and I have cited it in previous iterations (and even had it in an earlier draft - if you check the Markdown source, the link def is still there). Here's my current thinking on the topic. It all depends on whether you want to model your problem as a tree or a graph (see also [1] for some great discussion of that tension). If you model your problem as a graph, then a general purpose incremental computation engine like Adapton (or Incremental or Salsa) is great. However, if your problem is a tree, then constructing the explicit dependency graph requires a nontrivial amount of ceremony. What Xilem does is represent the most common tree-structured flows of information in a very lightweight manner (mostly just plain code that builds views), while allowing you to insert arbitrary graph edges if you like with more work. I think it's a discussion worth continuing. One thing you could do is integrate Adapton and Xilem together, where the implementation of most view nodes in the latter becomes queries into the Adapton engine. How well would that work? Really only one way to find out. [1]: https://glazkov.com/2022/02/06/tension-between-graphs-and-trees/ https://glazkov.com/2022/02/06/tension-between-graphs-and-tr...
- deleted 4y ago[deleted]
- ______-_-______ 4y agoBig fan of your work, Raph. One small typo: > {anonymous function of type FnMut(u32) -> ()} It looks like the param type should be `&mut u32`. And in that simple case the whole thing could probably just be `fn(&mut u32)` since the closure doesn't capture any locals.
- raphlinus 4y agoHeh yes, somebody else caught that. I think the current state is ok. This closure won't capture any locals, but in general closures in the view tree will. I'll take a PR if you think it should be improved further :)
- Barrera 4y agoFrom the first paragraph: > ... Architectures that work well in other languages generally don’t adapt well to Rust, mostly because they rely on shared mutable state and that is not idiomatic Rust, to put it mildly. ... The author doesn't mention Redux (the architecture), which is surprising. There are three principles[1]: 1. The global state of your application is stored in an object tree within a single store. 2. The only way to change the state is to emit an action, an object describing what happened. 3. Changes are made with pure functions. In other words, the components of an application never mutate the state tree directly. Rather, they emit actions which re-generates the state tree without mutation. This style of state management is compatible with Rust's ownership model.[2] The emphasis on pure functions (that clone state rather than mutate) means that it's not necessary for your application to alias mutable references, which I'm guessing underlies the "generally don't adapt well to Rust" part of the claim. [1] https://redux.js.org/understanding/thinking-in-redux/three-principles https://redux.js.org/understanding/thinking-in-redux/three-p... [2] https://github.com/jaredonline/redux-rs https://github.com/jaredonline/redux-rs
- ______-_-______ 4y agoI think Redux is similar enough to Elm that it's not worth mentioning separately. Redux plays fast and loose with types whereas Elm uses types strictly; that's probably why Elm is mentioned more often in the context of Rust. He does mention Redux in passing if you expand "Advanced topic: comparison with Elm"
- cultofmetatron 4y agoredux architecture is just a global scan(). more or less what the elm architecture is as well.
- raphlinus 4y agoThe other responses have this right. I think the Redux pattern is similar enough to Elm that I didn't feel a need to make a finer distinction. I'll also say this: the tools that Rust provides for reasoning about mutation are powerful and principled. A central philosophy of Rust is that mutation isn't the problem, it's shared mutable state. If you believe that philosophy (and I do), then restricting yourself to pure functions over clonable state feels like tying one hand behind your back. I hope I've made the case that providing finer grained access to mutable app state is an approach at least worth exploring.
- kuon 4y agoI am currently designing an UI framework in rust and I took a similar approach. It is intended for medical monitoring systems. I should be able zo open source it at some point. But for now, all I can say is that this approach seems the way to go.
- melony 4y agoWhat are your thoughts on Sycamore? It uses Svelte-style compile-time reactivity. https://github.com/sycamore-rs/sycamore https://github.com/sycamore-rs/sycamore
- raphlinus 4y agoTo be honest, I haven't looked too deeply into Sycamore. A lot of the reactive machinery looks pretty similar to Dioxus (threading a context scope, using explicit observable objects for change propagation). I think it's worth comparing more carefully, and would be more than happy to link a writeup to such a comparison.
- danappelxx 4y agoReally cool work. My impression after reading the article is that it’s significantly inspired by SwiftUI, but without the magic annotations (@State, @Binding, @EnvironmentObject, @StateObject, etc.). It will be interesting to see how Rust handles the fully-statically-typed view tree, which has been really pushing the limits of the Swift compiler. Question for the author: perhaps I missed it, but how do you plan to handle view trees that change based on state (ie SwiftUI’s IfElseView + viewbuilder)?
- raphlinus 4y agoGood catch! Yes, the plan is to implement _ConditionalContent. It would look something like this: if_view(bool_predicate, || view1(...then...), || view2(...else...)) Whether we end up having a proc macro that has similar functionality as ViewBuilder in SwiftUI is an open question. For the time being, I'm seeing how far I can get with just vanilla Rust. I'm generally pretty hopeful about the ability of the Rust compiler to handle big complex types, but it is a risk. There other projects out there that also stress it, and the compiler team is pretty serious about making this work well.
- CyberRabbi 4y agoSeems like a large part of the complexity is enabling the creation and use of reusable UI components that work in a variety of UI hierarchies and modify a variety of backend models (or app states), in a type-safe way. Is that right or are there other problems attempting to be solved? The simple way to do this is a callback system. Why is that not appropriate for Rust? Does it require custom ownership dynamics that the borrow checker does not support?
- stormbrew 4y agoBorrow checking gets a lot more complicated with closures that live past their scope. It’s usually much more frustrating than it’s worth.
- tcmart14 4y agoI think I just ran into this issue about a week ago. I started working on a task manager written in Rust using the Cursive library, which provides like an ncurses TUI. Heavy use of callbacks, but all callbacks require a <'static> lifetime. All the structures I make for information on the database of course don't have <'static> lifetimes. I eventually figured out that cursive has a function where you can kind of give it the data, but to pull the data back out requires a lot of cloning and boiler plate code.
- LegionMammal978 4y agoIsn't the standard solution to pass the data within an Rc or Arc? That way, the closure still owns all of its data.
- thatguy_ 4y agoReally interesting post. One thing I think might be problematic for you would be fallibility in the `Adapt` callback process. i.e. if it would not be sound to change the state of a child due to some emerging app state inconsistency or similar. To put it differently, I understand your architecture outputs a new _statically typed_ tree every time through kind of recursive state mutation. However, being statically typed, it is clear from the start of the operation what the end complete static type will be (to the compiler at least). If the transformation of one of the children is not possible (although the rest might be fine), what do you do? The obvious way would be to make each conversion fallible, but this might be a pain to use/propagate. Otherwise, you might have state that all operations involved in state mutation must be infallible. Anyway just my 2c. I might have misunderstood the mechanism, though. Thank you for all your impressive work!
- infogulch 4y agoVery interesting! This somehow seems convergent with the model-level incrementalization approach that incr_dom [1] and its successor bonsai [2] are using. Have you had a chance to compare these? [1]: https://github.com/janestreet/incr_dom https://github.com/janestreet/incr_dom | https://www.youtube.com/watch?v=R3xX37RGJKE https://www.youtube.com/watch?v=R3xX37RGJKE [2]: https://github.com/janestreet/bonsai/blob/master/docs/blogs/history.md https://github.com/janestreet/bonsai/blob/master/docs/blogs/...
- raphlinus 4y agoI would say that they were even greater inspirations for the Druid architecture that predated this latest work - we were hoping that a lot of the incremental/reactive patterns could be expressed using combinators over immutable data structures. That didn't work out as well as hoped; I think it's possible to build things that way, but it's also pretty hard going and the community never really reached critical mass. A semi-explicit goal of this work (that somehow didn't make it into the blog post) is that developing for this architecture, both building the UI components and using them, should be a lot more fun than before. Of course, that's a slippery goal to quantify. We'll just have to see how it goes, but I'm hopeful.
- deleted 4y ago[deleted]
- thurn 4y agoAnimation is usually the biggest pain point with frameworks like this -- and it usually feels like a complete afterthought for framework designers. Of course you always have the simple CSS-style stuff (here's a list of properties you can attach transitions to) but as soon as you get into anything more complicated it all falls apart.
- infogulch 4y agoCSS is pretty flexible. What kind of animations would you expect to be difficult to express?
- webmaven 4y ago> CSS is pretty flexible. What kind of animations would you expect to be difficult to express? Interpolations of anything beyond basic properties such as size, orientation, opacity, color, stroke, and fill; vector shapes, particle systems, and generative textures come to mind. There are intermediate possibilities. In theory you could "compile" the animation of a skeletal system with inverse kinematics to CSS, but I'm not aware of anyone going to the trouble.
- infogulch 4y agoIf you're going all the way to skeletons, kinematics, particle systems, etc maybe you just need a game renderer. Say, Bevy, if you want a rust flavor.
- webmaven 4y agoNo need to go that far. If you're just looking for the edge of where the capabilities of CSS animation fails, consider the pseudo-physics of various direct manipulations in touch UIs: eg. the bounce when you swipe to scroll and reach the last item, or swipe down again to refresh, or swipe to fling cards aside left or right, or pinch to zoom past the last zoom level, etc. In some cases you could get a good-enough result by animating from arbitrary (ie. user controlled) starting point to one or more fixed end-states (eg. Three "flick right" animations, one each for flick up and to the right, right, or down and to the right), but at that point you might as well just use an animation library.
- coryvirokmobile 4y agoApologies for the noob question, but why reinvent the wheel when we have HTML/DOM/CSS?
- deleted 4y ago[deleted]
- __jem 4y agoSo that you don't have to ship an entire web browser for your application.
- chriskrycho 4y agoBesides the (correct!) sibling comment: the idea here is to provide underlying primitives which can then be used to express UI in a variety of contexts, first of all native UIs but (as the post notes at the end) also including the DOM. For example, people have implemented experiments which use SwiftUI for authoring HTML, and you can use React to author native UI (React Native, but also e.g. the Raycast widget system), text UIs, etc.
- berkut 4y agoI've never persevered with immediate-mode UIs deeply enough to get to the point I needed to solve this, given I mostly deal with complex nested UIs and in my (possibly limited/incomplete?) experience, immediate-like UIs don't really work well for that type of complex and dynamic setup, but it sounds like the Widget tree persists in this model (at least more than the other trees), but it's not clear if it's update-able as well? (there is mention of it being rebuild-able, so I guess so?). I wonder what happens regarding state (say, selection state, or visibility/enabled state) in the case where you might want to allow the user to re-arrange entire UI components (say the user draging a nested tab/pane from one window of the app to another, and docking it into another different hierarchy): would the trees have to be completely re-built (I guess sub treelets could still be kept?) along with re-building the id paths. Would that mean diffing is hard/impossible in some cases to transfer across a large re-build of these trees?
- raphlinus 4y agoFirst question is easy: yes, the widget tree can be updated. That's generally done by diffing data stored in view nodes, but in fact the View trait is open-ended and you can implement the rebuild method to do anything you like. And yes, selection state lives in widgets and it is absolutely a goal to have that persist. The second question is more challenging (see the "advanced topic" under identity for a little more background). View id's cannot be re-parented, in other words when a parent relationship is expressed in an id path (by virtue of having the child id follow the parent in a path), that relationship cannot be changed. However, widget ids and view ids are not necessarily the same, though they can be. I think what's needed for your use case is a level of indirection so the view id paths remain stable, but the widget id structure relationships can be changed. I haven't worked out all the details, but think it can be done, and if it's done right it wouldn't require any rebuilding of widget subtrees.
- berkut 4y agoThanks for the info!
- aaaaaaaaaaab 4y agoAnother UI framework that re-renders everything each cycle? Yeah, it's gonna be awesome for todo lists (as long as you don't have more than ~100 todo items). Meanwhile high-performance apps will still be written in retained-mode UI toolkits.
- eximius 4y agoThis is targeting retained mode.
- aaaaaaaaaaab 4y agoUmmmm... no? "As is completely standard in declarative UI, it is done by diffing the old view tree against the new one, in this case calling the rebuild method on the View trait. This method compares the data, updates the associated widget if there are any changes, and also traverses into children. The view tree is retained just long enough to do event propagation and to be diffed against the next iteration of the view tree, at which point it is dropped. At any point in time, there are at most two copies of the view tree in existence."
- eximius 4y agoRetained mode is distinct from immediate mode where it _retains_ what is _drawn on the screen_, only redrawing visual components that have changed. Immediate mode redraws the entire application each time, replacing all pixels it's responsible for even if nothing has changed. Throwing away some internal state is not relevant to this distinction.
- aaaaaaaaaaab 4y agoWhat? No, that’s not the definition of retained mode graphics… https://en.m.wikipedia.org/wiki/Retained_mode https://en.m.wikipedia.org/wiki/Retained_mode
- infogulch 4y agoWhat happens if two child components need mutable access to the same data? Say, a group of dropdowns to filter/sort a table plus a pie chart with clickable slices that also change the filtering.
- archagon 4y agoGreat technical article as always, and apologies for not responding to the meat of the article, but I tend to look at declarative UI with some degree of skepticism. Raph, do you think this general approach can eventually be scaled up to develop complex and highly interactive applications such as DAWs, video editors, and graphic design software? At least based on my experience with SwiftUI, I find the paradigm easy and satisfying to get started with, and great for prototyping and widgets, but quickly run into roadblocks whenever trying to build creative software that's not just a view around a database. Or do you see this as just another tool in the UI toolbox, and not necessarily mutually exclusive with imperative and immediate mode UI? Curious to hear your thoughts!
- raphlinus 4y agoI think your skepticism is well placed, and I think you are asking the right question. Here is why I'm hopeful. SwiftUI is as you say wonderful, but is very much a closed ecosystem. You can't really implement your own custom views, rather you can assemble the premade ones in various (cool and interesting!) ways. If you wanted grid layout before iOS 14, you were on your own. By contrast, in what I'm building, everything is open-ended, and you are invited to build fully custom versions of every piece of the system - change propagation, async resource loading, layout, drawing, animation, everything. So yes, I am hopeful this approach will give good results for especially those highly intensive applications you mention. And if not, we'll learn something why not. I'm looking forward to trying!
- elcritch 4y agoI’ll have to checkout your project. I’ve been experimenting with something similar, but in Nim. It’s interesting to devise declarative or immediate mode UIs that make use of compiled languages with good async. Animations become very easy. I think those more complicated UIs may work well with declarative frameworks. I’m curious to see how you’re handling events. Best of luck! 1: https://github.com/elcritch/fidgetty https://github.com/elcritch/fidgetty
- elcritch 4y ago
- Klasiaster 4y agoWould be great to eventually have different backends for this, like Java had where the app looked native in Windows, Gtk, etc. One could even think of having a TUI backend besides an HTML or Canvas backend. That would be restricting of course when one needs features available in only one backend and developers could opt-in for more control and require a certain backend like Gtk or not require but detect the backend and get extra features.
- AbuAssar 4y agokudos for explaining the meaning of the name, alot of projects just puck a random name and call it a day. > The name “Xilem” is derived from xylem, a type of transport tissue in vascular plants, including trees. The word is spelled with an “i” in several languages including Romanian and Malay, and is a reference to xi-editor, a starting place for explorations into UI in Rust (now on hold).
- eximius 4y agoI think the answer to this is no, but I'll ask anyway. Is there any concern with the allocation for the view/widget tree every cycle? I know it's retained mode so the most important resources (graphics) are cached between cycles, but I'm wondering if the trees ought to be allocated out of arenas or something so that the allocating/freeing every cycle isn't undue performance penalty. (I'm not sure what existing regained frameworks do.)
- deleted 4y ago[deleted]
- ogoffart 4y ago> The problem is that it requires shared mutable access to that state, which is clunky at best in Rust (it requires interior mutability). I don't see the problem with using interior mutability (Rc<RefCell<T>> or Arc<Mutex<T>>) With Slint [1], we just embrace it, and rely on interior mutability for the shared state, and that works well. [1] https://github.com/slint-ui/slint https://github.com/slint-ui/slint
- tayistay 4y agoI tried using interior mutability in rui [1] but the clunkiness appeared in having to call clone on the Rc/Arc too often. I'd have a few clones before moving into a closure, like this: let text = self.text.clone(); focus(move |has_focus| { let text = text.clone(); state(TextEditorState::new(), move |state| { let text = text.clone(); let text2 = text.clone(); let cursor = state.with(|s| s.cursor); let state2 = state.clone(); currently looks like this: focus(move |has_focus| { state(TextEditorState::new, move |state, cx| { let cursor = cx[state].cursor; canvas(move |cx, rect, vger| { (Note the context (cx) passed to callbacks to look things up.) [1] https://github.com/audulus/rui https://github.com/audulus/rui
- conradev 4y agoHave you thought about backing the persistent widget tree with native widgets as the final layer? Or, at least supporting it as a render target. That is, UI/NSViews on Apple platforms, DOM nodes on web, GTK objects on Linux, etc. Essentially using them as the final “render tree”. SwiftUI takes this approach, as ComponentKit did before it. The framework still does most everything (state updates, layout, animation, etc), but the host compositor handles the actual rendering. This approach has a few advantages in my opinion. These widgets integrate nicely with the host accessibility system, for one. They also can come with built-in styling to make them “fit into” the target platform. There are also performance benefits to leveraging the system compositor – Firefox switched to have platform native layers on macOS and it helped immensely with battery life. It is worth noting that SwiftUI and ComponentKit components don’t have 1:1 mappings with native widgets – they both perform flattening (i.e. for drawing paths and layout only nodes) to optimize their performance. I think most importantly, though, it allows for rewriting code incrementally as that approach naturally supports bidirectional embedding. Having rewritten the Shortcuts app editor from UIKit into ComponentKit into SwiftUI (maybe one of the larger projects written in SwiftUI?), incremental rewriting is crucial for existing software projects. The other concern is mobile – it just is not feasible to rewrite the text input stack on mobile, for example, so being able to use native text editing views would very much be necessary. This all looks fantastic!
- pkphilip 4y agoPersonal opinion but I think the old RAD approach in tools like Delphi where the components are laid out visually using the IDE but having the option of generating the components programmatically during runtime including attaching/detaching event handlers etc with state handled application-wide or within the context of the "form" is a much faster way to develop than to use the declarative approach in tools like Flutter where state management is really complex. Also, one could develop custom components very easily in Delphi with custom draw events which would draw just the component.
- tayistay 4y agoI haven't used Delphi, but what you're describing sounds like Interface Builder, which I've used a lot. The biggest problem I had with IB was that it got quite tedious to specify all the constraints to make an app responsive to different screen/window sizes. Plus, you'd have some constraint in there and you wouldn't remember why it was there! IIRC you couldn't add comments. Also you couldn't diff the files because it was a ton of XML and merging them was really scary. I think bigger teams tended to stay away from IB/Storyboards altogether (storyboards were really bad because it was all centralized in one file).
- flohofwoe 4y agoObviously Raph knows what he's doing, so this isn't a critique, but a question: What's the reason for replicating the "React idea" outside the web browser? The way I understand the motivation behind React is that it tries to work around the too high level and too rigid DOM by mapping one way to describe an UI (the React API) to another (the DOM), for the only reason that there's no realistic way to bypass the DOM (except doing everything yourself - including fundamentals like text rendering - via a 2D- or WebGL canvas). But if you don't have something as rigid as the DOM as lowest layer to begin with, what's the point of building a React-style system with 'tree diffing' against data that persists across frames? Is it really worth the complexity managing intermediate data that sits between the UI description that (most likely) needs to be updated each frame, and the low-level rendering instruction stream - which most likely also needs to be generated each frame? Or is it all about Rust's language restrictions?
- loxs 4y agoAs someone who writes exclusively Rust on the backend and React on the frontend... To me React is a "language", not the technique of the "tree-diffing". And I think it's the best one there is for expressing an UI. The tree-diffing (and the speed deterioration) is only the (unfortunate) way to compile it to the DOM. Still worth it IMO. With Rust it can probably be done both safely and imperatively (i.e., fast) while retaining the declarative language. Haven't really thought it over fully, but so far it sounds really nice.
- mikevm 4y agoWhat about various libraries that don't use a virtual DOM and have vastly better performance than React, for example https://www.solidjs.com https://www.solidjs.com or Svelte?
- loxs 4y agoSvelte is nice, although a lot less ergonomic than React as it is not "native JS" which creates the need for "two domains" of programming - one, the Svelte domain (which is later compiled) and one JS domain which is called as a library. Haven't tried SolidJS yet. Cannot really say if Svelte is worse than React, as I have much more experience with React itself. My main blocker to adopt it (Svelte) is mostly library support - with React one can use "everything" in all kinds of "hackish" ways and with TypeScript, which wasn't really the case with Svelte last I checked, maybe 2 years ago.
- chaosprint 4y agoVery insightful post. Although my work is mainly about audio not GUI, I still learn a lot from your idea. For my audio work, I also use declarative style and diff algorithm for updating the audio graph. But when rewriting it, I found sending messages is also very convenient: https://github.com/chaosprint/glicol/tree/main/rs/synth https://github.com/chaosprint/glicol/tree/main/rs/synth This might be interesting for you as I found that you also have a synth project (https://github.com/raphlinus/synthesizer-io https://github.com/raphlinus/synthesizer-io). Admittedly, there is still some way to go for this audio lib. Will further study this post when I got more spare time.
- webmaven 4y agoSome of your previous explorations were motivated (IIRC) by UIs that had (potentially) many thousands of objects for interactive visualizations of datasets. Is that still a motivating example for this evolved approach?
- raphlinus 4y agoYes, most definitely. My main work these days is on supporting high performance drawing of such large data sets on GPU. It's not entirely wrong to say that my continued explorations into UI architecture are motivated by wanting to drive the renderer with really high-bandwidth input.
- webmaven 4y agoOkay. That said, are there any particular conclusions or implications from this approach for that use case? For that matter, are you next going to extend this simple exploration toward more complexity (eg. more widget types, more interactions, more layout constraints, etc.) or toward more data? As I've followed your efforts in this area, the power and utility of selecting the right motivating example has been coming into focus. The parallels with a startup's MVP are fairly clear, the parallels to selecting a (dissertation) research topic a bit handwavy (in part because guidelines for the latter are extraordinarily vague). So far you haven't really chosen a new motivating end-user application since suspending development of Xi. There are lots of directions you could go, from making an equivalent to Processing, to creating a game engine, or eventually restarting Xi development with an eye toward exploration and visualization of large codebases, etc. Personally I'm starting to become intrigued by the need to dig into large neural nets and the representations encoded within (related subtopics: latent spaces, feature vectors, orthogonality): https://distill.pub/2019/activation-atlas/ https://distill.pub/2019/activation-atlas/ Meanwhile, I've been casting about for a proper (Rust) motivating example app/library of my own, and the closest I've come so far is something like a HTML + CSS rendering engine, though not targeted at the Web per-se, but instead at ebooks (esp. EPUB), a much smaller set of required functionality. In theory a desktop ebook library + reader app with features like MathML support, advanced typography, and visualizing connections between millions of works and annotations seems like it would be a better fit with the direction you're (currently) going than any existing framework.
- yencabulator 4y agoAs someone who has written some 10,000 lines of Rust, if this comma is intentional this is just frankly unreadable: adapt( |data: &mut Arc<Parent>, thunk| { let mut child = data.child.clone(); thunk.call(&mut child), // <-- HERE if !Arc::ptr_eq(&data.child, &child) { Arc::make_mut(data).child = child; } }, child_view(...) // which has Arc<Child> as its app data type ) Maybe it was meant to be a semicolon?