vlang / v

Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic C => V translation. https://vlang.io
MIT License
35.64k stars 2.15k forks source link

Declarative UI: Swift/Dart vs Qt/QML approach #2065

Closed medvednikov closed 4 years ago

medvednikov commented 4 years ago

Hi,

Update

V UI has been released, V itself is used for declarations.

I'm working on declarative UI right now.

Which approach do you think is the best: Swift/Dart (using the same language for declarations) or Qt/QML (using a smaller cleaner different language)?

It's nice to have only one language, but the "VML" approach looks cleaner to me.

Also, I'd need to modify V a lot, for example to allow things like [TextBox{}, Button{}].

nedpals commented 4 years ago

I like Dart's approach. It's easy to debug and understand the properties of the component.

Delta456 commented 4 years ago

I like QML's approach because it's quite small and is more easy to understand IMHO .

dumblob commented 4 years ago

Hi @medvednikov, a good UI is undoubtedly a valuable endeavor. Believe me though, it's kind of waste of your precious time. Read carefully the discussion https://github.com/vlang/ui/issues/1#issuecomment-527892090 on this topic and dive thoroughly into the technical story (part 1, part 2) behind making modern UIs as referenced in the post.

To put it bluntly, don't even try to create yet another retained UI (as QML, Dart, WPF, Qt, GTK, ... you name it). It won't be used much and your work won't bring the fruits you'd expect and like to. There are literally hundreds of cross-platform UIs (sometimes embedded into applications, sometimes separated as a library). Your UI reminds me a lot of Lua tekUI and of QML. Don't recreate them, it's pointless :cry: (unless you want to avoid bindings to existing good UI libraries and an the same time make V a mainstream language, not a "better one" as I understood it until now :wink:).

All this boils down to can be summarized as:

For UI all approaches are equally necessary - declarative compile-time retained, then declarative run-time retained, then compile-time immediate (i.e. non-declarative), and finally run-time immediate (i.e. non-declarative) mode.

Above-mentioned frameworks do offer though just the declarative compile-time retained approach and partially the run-time retained, but not at all compile-time immediate nor run-time immediate.


P.S. Full-featured UIs are about as complex as full-featured programming languages offering builtin parallelism and stdlib. UIs can eat up all your time for years...

medvednikov commented 4 years ago

@dumblob there's no good cross platform native desktop UI library, this was one of V's main features. I've already written thousands of lines of UI code, I don't see a reason not to release my work :)

ylluminate commented 4 years ago

@medvednikov I must lean towards purist methodologies such as keeping it declared in the language itself vs having to remember something else or breaking out into a different methodology. When you get into generative aspects and such it seems superior to keep the language completely universal...

If i'm going to go for friendlier syntax, i'd just stick to Ruby. V is a far cry from the elegance of Ruby in terms of syntax and robust expression, but that's not why I value V and so i tend to think sticking with the "one way" mantra is the right way here.

Sidenote BTW (😀): I'm always for reducing boiler plate and simplifying syntax. If I could have V in Ruby syntax buddy you can believe I'd be first in line (!), but I realize there are tradeoffs. Hopefully at some point someone will take the initiative to write Ruby in V (similar to this Ruby with Rust project). :)

gslicer commented 4 years ago

I plead for declarative UI in V syntax

dumblob commented 4 years ago

I've already written thousands of lines of UI code, I don't see a reason not to release my work :)

If it's only about releasing, then sure, go ahead :wink:.

there's no good cross platform native desktop UI library, this was one of V's main features.

Well, this is a very bold statement and I'd argue it's exaggerating a lot. I know several very good cross platform libraries which are very hard to beat in their functionality and overall quality. Some of them are (very) minimalist, some of them leverage programming language(s) of their choice (pretty much like your declarative UI library uses V and will be hard(er) to use efficiently and as easily in other languages), some of them are more modern (allowing tighter integration with constrained platforms like web), etc.

So, generally there is no need for a cross platform UI library as they already exist and work well (might be less known, but that's another story). The only issue UI libs have is, that they are cumbersome to use. Still in each of them you can in the end achieve anything you need (beginning with animations, going through canvas-like painting up until fully dynamic behavior of widgets & any visual objects including their size/shape/content/position and their creation and/or destroying on demand in reaction to e.g. user input).

Don't take me wrong, but I'd rather say, don't try to push yourself to create a good UI library, as it's provably impossible with a declarative UI in the first place (in short: many of the above-mentioned requirements "animations ... on demand" are impossible with declarative UIs unless they're to be significantly more complicated then all the web CSS stuff nowadays).

medvednikov commented 4 years ago

Well, this is a very bold statement and I'd argue it's exaggerating a lot. I know several very good cross platform libraries which are very hard to beat in their functionality and overall quality.

I'm very interested in what these are. They key is native and cross-platform.

So Qt, GTK, Nuklear are not an option.

I can think of only wxWidgets and libui, and the latter is still at a very early stage and not under active development.

dumblob commented 4 years ago

They key is native and cross-platform.

Assuming native means

looking exactly as native, behaving as native, using native widgets/constructs everywhere where there is feature-set equivalent available

and cross-platform means

Windows, X11 (i.e. Linux/BSD, ...), macOS, maybe Android

then off the top of my head (in random order): .NET WinForms, libui, Python tkinter, wxWidgets, [Red/VID](https://doc.red-lang.org/en/vid.html , VCLua, Qt (it mimicks it very well), QML (same as Qt), GTK (yes, it uses native DLLs for look&feel), IUP, Solvespace GUI abstraction, ...

Regarding the risk of (not) being developed, it's the same risk of any project disregarding whether proprietary or open source. Btw. V and it's ecosystem has this risk way higher than libui because "nobody" uses V, but hundreds of active users use libui.


(Not speaking about the fact, that libui is actually being actively developed - not sure where does the misinformation about abandoned development come from. Also libui is way ahead of V and it'll stay so for months, maybe years even if the V's development pace won't decrease.)

P.S. Btw. libui is also a perfect showcase why retained UIs are the wrongest decision for UI development - look at what's on the libui TODO list to get a grasp of what's needed for retained UIs, but is absolutely unnecessary e.g. for immediate mode UIs.

ylluminate commented 4 years ago

Ultimately we need a native facility for UI implementation in V that provides native "widgetry" for each platform. For Windows and macOS that means to provide access to these systems' own UI toolkits with V interfaces. For Linux that obviously means something a little different and that, as you've noted, has been done via mechanisms you already have in place. Furthermore WASM and JS are also going a native and customizable UI interface that is immediately provided as well in this same vein (so it's essentially lumped in with Linux). From what I can tell you're on the right track @medvednikov.

I hear what @dumblob is saying, but I fear it may not hold true in this situation. Could libui fill this void and facilitate a UI for each platform with the necessary cross-compilation requirements that V needs to cleanly provide this? I don't know, I guess only you @medvednikov really can answer this. If V-UI is does this and does it cleanly and efficiently in native V then perhaps it's better and more maintainable than going with an existing C library.

If libui is even an option, for example, would it be time to create what we previously discussed with this back-and-forth tooling that will facilitate translation in both directions and diffing in order to keep projects in sync? Would that be a better investment of time? Again, I don't have the answer to this.

The one thing that I know is that we very much need a V-UI facility and it's something that cannot wait. It's also something that needs to be - LIKE V - cross compilable in every direction.

C proper has failed at this goal over the decades. It's a shame because C was supposed to be what V is. Everyone who has ever set out with C has effectively lost their way and got caught up in proprietary thought that has now yielded all of these platforms. It was a terrible mistake. Microsoft & Apple started the mess to a large degree (I know there were licensing issues at that time, but there were ways around it). Steve Jobs tried to bring some sanity back (and did) with NeXT, but here we are with Linux and this nightmare fragmentation. Too many of us hate GTK. Qt just simply didn't win thanks to the crap that went on with that circus. Etc. Etc. Etc.

So I guess at the end of the day I go back to my original thoughts: Alex, you've put a lot of work into this. You've done an amazing thing in a short period of time just bringing forth what you have. You have your own GUI needs with apps you've been working on. We need a true cross platform UI lib. Can V-UI do better than all of the other options and work in V's Live development mode? If all of this is the case, then let's do it your way and see what happens. And if all of this is the case, let's keep it in pure V.

Sometimes naivety and fresh perspective, as problematic as it can be, is the solution in this twisted metal wreck of computer science and software that presently exists.

medvednikov commented 4 years ago

then off the top of my head (in random order): .NET WinForms, libui, Python tkinter, wxWidgets, [Red/VID](https://doc.red-lang.org/en/vid.html , VCLua, Qt (it mimicks it very well), QML (same as Qt), GTK (yes, it uses native DLLs for look&feel), IUP, Solvespace GUI abstraction, ...

.NET WinForms (Mono) is not native, the link you referenced mentions that:

Why Not Use Native Widgets?

It's also C#, which makes it very hard to usefrom C.

Qt is anything but native. It renders everything, and Qt apps, just like Java GUI apps are notorious for their "un-native" look. I use a Qt password app every day (KeePassX) and it's very visible. Besides, Qt is a multi gigabyte C++ monstrosity with a custom C++ dialect, so it's not easy to integrate it into a small language like V.

GTK is just... No comments :)

libui is a one person project mostly that's still in alpha after more than 3 years of development. https://github.com/andlabs/libui/issues/274

libui is also a perfect showcase why retained UIs

If we want to have a native toolkit, then we have no choice but to use retained UIs, because that's what Win32 and Cocoa are.

I know that it's not 2007 anymore, and people don't care about the native feel that much. And the desktop app market is stagnating and being replaced by mobile. I also realize that what I'm doing may look like

But I'm 100% confident that's the right choice.

From the reviews I received, people are tired of 200 MB tray apps written in Electron/JavaScript just because there's no good and easy to use cross-platform UI toolkit.

And like @ylluminate mentioned, this is all going to be in pure V, with hot reload and cross-compilation, which is something none of the existing desktop toolkits offer.

ylluminate commented 4 years ago

@medvednikov is spot on here. The comic is apropos, but (strangely) sometimes this is okay. I've been a project manager for an engineering firm and software engineer for a long time. I understand this ecosystem and frankly the ecosystem is so horrifically painful.

This issue about memory could be likened to a massive infection upon the software industry. It's like the visible head on a massive pustulant cyst on someone's face or head that they're trying desperately to hide, but it keeps growing and growing. Google is a nightmare with their Chrome practices and the web devs who have adopted technologies such as Chromium/Electron are compounding the situation. This kind of insanity must stop.

I agree that this SEEMS like we're going to end up with a mess, but I believe Alex is right. I may not be excited about some things like like spending time on making a Discord replacement due my desire to see that time dedicated to V-UI and other pet features, but ultimately the UI (today) is as integral and inextricably connected to success as the language's innate stability and robustness itself... :s

gslicer commented 4 years ago

@dumblob perhaps we should give @medvednikov a chance to show what he has built until now and if this could be an option to go or better to offer V bindings to existing UI frameworks

btw: I consider GTK+ as one of the "native" GUIs under GNU/Linux (because it supports very well Wayland) - another one supporting this protocol is Enlightenment (might be worth to take a look into it)

dumblob commented 4 years ago

I do fully understand what @medvednikov, @ylluminate and others expressed here. I have to admit, it's my dream for almost two decades now. The one and only one obstacle which makes me rather pessimistic about the (current) plan for V UI is what @medvednikov wrote about V UI:

If we want to have a native toolkit, then we have no choice but to use retained UIs, because that's what Win32 and Cocoa are.

Which in stark contrast with what @ylluminate wrote:

Sometimes naivety and fresh perspective, as problematic as it can be, is the solution in this twisted metal wreck of computer science and software that presently exists.

and thus makes its way directly towards the 15. competing standard from the perfectly fitting xkcd comic.

It's fine to have V UI being the lowest common denominator across platforms. It's small, easy to maintain, fully native, fast. This'll then become a slightly less capable IUP but for V and not Lua. Originally I misunderstood and thought that V UI shall be more capable - therefore all my "warning" comments which you can ignore now :wink:.


.NET WinForms (Mono) is not native, the link you referenced mentions that...

Yeah, just the behavior is native (rendering isn't). Still, WinForms theming is better than in Qt and GTK and an average user wouldn't often probably notice.

libui is a one person project mostly that's still in alpha after more than 3 years of development. andlabs/libui#274

It's one person project, but as I linked above it got forked many times with many active contributors and active merging => it's far from being dead. Also the linked thread andlabs/libui#274 clearly states it's not dead at all plus defines a roadmap etc. Last thing is the "alpha" state. Well, in practice libui is well usable (even the number of GitHub issues underpins it - yeah, 139 for such a big project means "all is perfect") with hundreds/thousands of users. The libui author is underestimating a lot - compared to other about as complex projects it would already be 1.x. On the other hand, libui is IMHO not a good fit for V for other reasons.

with hot reload and cross-compilation, which is something none of the existing desktop toolkits offer.

The following is not meant to disappoint anyone, but this is simply by far not true - e.g. Red GUI is unbelievably capable and offers hot reload (even better than V as one can edit the underlying application pretty much like in smalltalk environments), full cross-compilation (done right) for Windows, macOS, Linux (GTK), Android (!), etc. and is super fast.

Let's stop comparing thuff and rather rationally discover what everything can be done with the lowest common denominator of retained UIs. If not capable enough for V's basic needs in stdlib, then rather skip this completely and don't make it into V's stdlib at all and take some existing promising lib like Quarks, accommodate it to V (in case of Quarks even a rewrite in V would be a sane solution), maybe even use some native widgets as backend for uses matching the lowest common denominator and finally add it to VPM.

gslicer commented 4 years ago

@dumblob one toolkit you referred to, catched my attantion: Nuklear - looks very minimal but flexible at the same time to me.

Aalthough not using native widgets, perhaps "native" is overrated and sometimes even boring and restrictive?

There are even Go bindings for it: Go-Lang UI and they show the architecture for such bindings can be realized.

In case you find Nulear too simplistic, there is one other interesting "non-native" toolkit called dear imgui having an impressive variety in its gallery

M4SSD35TRUCT10N commented 4 years ago

@medvednikov Stick to pure v. IMHO It's easier to learn. And with a third or first party visual tool the UI will be done in no time (one thing I liked on MacOS back then were their developer tools).

Easy language, clear way to implement something, then build tools on top of that to ease development process. I would like to see what you've achieved so far.

Keep up the good work!

priezz commented 4 years ago

+1 for SwiftUI/Flutter approach. It could be used, however, for both, native and non-native widgets. For non-native I would like to see the binding to Nuklear (as the smallest dependency-free cross-platform library I know), with the same sugar as for native counterpart. In many cases non-native UI is preferable. I mean games and other staff, which requires deeply customized look.

medvednikov commented 4 years ago

@priezz the graphics module (gg) is going to have a non-native UI toolkit for games, webassembly UI, and Linux UI (GTK is not going to be used on Linux).

priezz commented 4 years ago

@medvednikov , thank you, good to know! Is it gg, which is to be used for custom UI elements (like charts)? If so, the bindings to non-V libraries are really not necessary. Do you think of the unification of the use of native and non-native elements?

medvednikov commented 4 years ago

Yes, things like charts will be unified.

But ui.Button is a native Windows/Cocoa widget, and gg.ui.Button is a custom widget rendered via OpenGL/DirectX/Metal/Xlib

priezz commented 4 years ago

Actually, the question is, if it would be possible to use custom staff like gg.ui.Button together with the native elements, i.e. inside ui.Panel, or it will be necessary to replace the whole thing with the gg version?

ylluminate commented 4 years ago

I think one thing we'll want to do is to wrap this such that when we build an interface the system will be smart enough to choose ui.Button or gg.ui.Button based on whether or not the target has native components (ie on Mac and Windows it will use the native; while on WASM or Linux it will use non-native with the accompanying desire UI graphic definition, however that will be defined).

medvednikov commented 4 years ago

Yes, there will be a way to draw anything next to native controls, including gg.ui controls.

medvednikov commented 4 years ago

@ylluminate of course, if you use ui.Button on Linux, it uses gg.ui.Button behind the scenes. Same with WA.

tomByrer commented 4 years ago

I prefer the notation on the right side (V); it is closer to JSON which I'm used to.

IF you were to go with left side (VML), then please get rid of the brackets & just use a YAML format.

arnaudchenyensu commented 4 years ago

I really like the syntax and approach taken by elm-ui.

Might help you a bit for the syntax :)

ylluminate commented 4 years ago

@arnaudchenyensu your remark about elm-ui is interesting and this talk about that is also fun and really interesting: https://www.youtube.com/watch?v=Ie-gqwSHQr0

I don't know if it needs to be exactly like this since we're talking more about app UI design, BUT I could see this working for a web system... and maybe I'm just not able to completely associate this with app design since the video itself is more in the context of how crappy CSS is... LOL

I suppose that this could eventually (I don't necessarily know if @medvednikov has this as a priority right now) be used in a v-ui-web library to somehow take v-ui to the web also as an abstraction somehow... Or perhaps this could even be brought to UI design generally.

Mainly just thinking out loud after poking about...

arnaudchenyensu commented 4 years ago

@ylluminate

I believe that elm-ui is a good abstraction for UI design in general and not only web. It really shows how to handle layouts with simple and understandable words.

The adding benefit for V will be to have only one UI library that can be cross compatible.

tomByrer commented 4 years ago

The adding benefit for V will be to have only one UI library that can be cross compatible.

That would be nice, but my vote would be either the JSON-like V syntax above, YAML, or JSX. That elm-ui is too brackety IMHO.

M4SSD35TRUCT10N commented 4 years ago

As I posted before that JSON-like syntax is easy to understand and can be written by UI-based tool in no time. The easier to use the more will use it actually.

dumblob commented 4 years ago

I think the serialization format for persistence (JSON, YAML, elm, ...) is not important at the beginning. But the actual structure representing the state in memory (which closely relates to representation in V syntax) is the alpha and omega.

Anyway, elm-ui is just a carefully chosen subset of CSS written in a syntax with scoping rules different from CSS. elm-ui seems to be first and foremost just another layouting syntax (and even less capable than current mainstream - see e.g. Apple Auto Layout or Python ENAML etc. - all of them using at least the good old Cassowary). elm-ui has thus the same design flaws as CSS - namely it forces one to think of the layout as a strictly nested hierarchical trees. Cassowary per se doesn't impose this restriction at all (though majority of its implementations do model it like that for unknown reasons :cry:).

priezz commented 4 years ago

elm-ui is good and actually follows the same approach as Flutter, SwiftUI and React (w/o the use of JSX). I downvote for any kind of json and/or xml markup, mixed into the language. I have used both approaches for years and find Flutter to be the most suitable for apps with UI. Having everything in the same language brings lots of advantages. And for those who doubt, it up to you, if you want to split the models/logic from UI or keep them together (for some time, it really helps to prototype quickly).

gslicer commented 4 years ago

@medvednikov

It's nice to have only one language, but the "VML" approach looks cleaner to me.

It just "looks" cleaner, because you hide another abstraction layer that VLayout is part of the Window's "body" in V notation (if there were other parts than body e,g, decoration, the VML tree dept would be the same or not?)

Xananax commented 4 years ago

Would the pure V approach allow run-time building of interfaces? I like when interfaces can be augmented by visitors; it's a very useful pattern for exposing components that work as they are, but can acquire additional functionality without being completely replaced.

dhonx commented 4 years ago

VML more cleaner for me

dhonx commented 4 years ago

@dumblob there's no good cross platform native desktop UI library, this was one of V's main features. I've already written thousands of lines of UI code, I don't see a reason not to release my work :)

Go on ... !!! That is an impressive work ... !!! 👍 💪

Richiban commented 4 years ago

I'd also look to Kotlin's builders for inspiration: https://kotlinlang.org/docs/reference/type-safe-builders.html

Here's a snippet:

fun result() =
    html {
        head {
            title {+"XML encoding with Kotlin"}
        }
        body {
            h1 {+"XML encoding with Kotlin"}
            p  {+"this format can be used as an alternative markup to XML"}

            // an element with attributes and text content
            a(href = "http://kotlinlang.org") {+"Kotlin"}

            // mixed content
            p {
                +"This is some"
                b {+"mixed"}
                +"text. For more see the"
                a(href = "http://kotlinlang.org") {+"Kotlin"}
                +"project"
            }
            p {+"some text"}

            // content generated by
            p {
                for (arg in args)
                    +arg
            }
        }
    }

It works in Kotlin because the syntax html { ... } is actually a call to a higher order function, equivalent to something like: html(() => { ... }).

However, the lambda is a special kind of lambda with a receiver of the HTML type, meaning that inside the lambda body all the members of the HTML type are in scope. So,

html {
    head {
        title {
            ...
        }
    }
}

is the equivalent of:

html({ h -> 
    h.head({ hh ->
        hh.title({ t->
            ...
        })
    })
})

I think it's a wonderful and powerful syntax feature.

gslicer commented 4 years ago

V already supports higher order functions (see example below from the Docs)

fn sqr(n int) int {
        return n * n
}

fn run(value int, op fn(int) int) int {
        return op(value)
}

fn main()  {
        println(run(5, sqr)) // "25"
}
dumblob commented 4 years ago

@Xananax

I like when interfaces can be augmented by visitors; it's a very useful pattern for exposing components that work as they are, but can acquire additional functionality without being completely replaced.

Not exactly sure what you mean by "augmented by visitors", but pure "runtime dynamics" (as outlined above: "beginning with animations, going through canvas-like painting up until fully dynamic behavior of widgets & any visual objects including their size/shape/content/position and their creation and/or destroying on demand in reaction to e.g. user input") is only achievable with immediate mode UI libraries, but impossible with native cross platform (thus retained) UI libraries.

gslicer commented 4 years ago

interfaces augmented by visitors

Sounds to me as "inheritance" in OOP - you basically take a struct and add some additional attributes and maybe also additional "member functions"/"methods" (in V receiver functions) which extend the interface

Xananax commented 4 years ago

It's different enough from OOP to be unrelated.

Let's say I have this structure (pseudo-code, language agnostic):

{ element: 'post', children:[
  { element: 'input', name: 'title', type: 'text' },
  { element: 'input', name: 'body', type: 'text' }
] }

I could pass it to a visitor that produces:

{ element: 'post', children:[
-  { element: 'input', name: 'title', type: 'text' },
+  { element: 'input', name: 'title', type: 'hidden', value:'today()' },
-  { element: 'textarea', name: 'body', type: 'richtext' }
+  { element: 'input', name: 'body', type: 'text' }
] }

That's a modification.

I could do:

{ element: 'post', children:[
+ { element:'label', content:'title', children: [
    { element: 'input', name: 'title', type: 'text' }
+ ]},
+ { element:'label', content:'body', children: [
  { element: 'input', name: 'body', type: 'text' }
+ ]}
] }

That's an augmentation

I could do:

{ element: 'post', children:[
-  { element: 'input', name: 'title', type: 'text' },
  { element: 'input', name: 'body', type: 'text' }
] }

That's a removal.

It's important to note that the visitor:

  1. can have run-time custom logic; augments certain things, deletes others
  2. stays declarative: records are modifiable at anytime by any function, without hidden state
  3. are stackable: the same structure can go through a chain of modifiers, depending on final output
  4. are not linear: you can apply transforms in any order, or a custom order, or fork to different transforms according to complex logic

The usage is to display the same base record in different views with minimal logic.

post |> addLabels |> addHelp |> addRequired |> addAction |> toForm 

post |>  bodyToRichText |> hideLabel |> autoDate |> isAdmin 
    ? |> toForm
    : |> inputsToDivs |> addComments |> toStaticView
dumblob commented 4 years ago

@Xananax in your examples are all possible paths the visitor can take known in compile time. So that has actually nothing to do with runtime and is easy to implement disregarding language, syntax, logic, structures, data, abstractions, whatever - that's called "retained state" in UI terminology.

But if there are paths (for the visitor) which are not known in compile time (or it would be futile to find them in compile time - e.g. due to billions of them), then you really need something in runtime which is usually abstracted as "immediate mode" in UI terminology (imagine main loop of 3D games where one iteration of this main loop produces one image for your display).

Xananax commented 4 years ago

Of course my examples are trivial, they are examples, and as such, I've kept them minimal, in knowledge that people could infer more complex situations. The point being, if the API is declarative and can be augmented, then you (or the compiler) can choose which parts can be pre-compiled, and which need to be generated at run-time.

Also, I know we're currently discussing desktop UIs, but I disagree that we should adopt a graphical API terminology nonetheless. Widgets are widgets, and a declarative, manipulatable API allows widgets to be reused by different renderers. If a common API is agreed upon and entirely made of plain records with no hidden state or methods, then people are free to implement renderers for Curses, HTML, or whatever else they please.

dumblob commented 4 years ago

@Xananax it seems we're talking at cross purposes. The current situation:

  1. @medvednikov has a goal to use native GUI capabilities (incl. libraries, widgets, behaviors, styles, whatever) for each supported platform (at least Windows, macOS, Linux/BSD, Android)

  2. you @Xananax want and I quote If a common API is agreed upon and entirely made of plain records with no hidden state or methods, then people are free to implement renderers for Curses, HTML, or whatever else they please.

But because all native GUIs on all the above mentioned platforms use retained state (let's stick to the common terminology and not try to reinvent a wheel), there is no way to agree an API without hidden state or methods. All native UIs known to me implement nowadays just retained state UIs (they retain much/full state, have their own hidden state and hidden behavior/methods, etc.).

So the points (1) and (2) mutually exclude each other.

Xananax commented 4 years ago

My impression is that this thread is about the syntax, which has a much more global reach than what you're discussing, specially for languages that want "one way to do the right thing", in which one syntax used today for native UIs will certainly need to be also used of other type of interfaces later.

The opening statement in the issue asks:

Swift/Dart (using the same language for declarations) or Qt/QML (using a smaller cleaner different language)?

My answer to this is:

By staying entirely declarative & using plain objects, we open many more possibilities in terms of outputs. By not using a specific DSL, we can easily create transformers for this structure using the same paradigms and constructs we're using daily. By using language constructs, we can naturally evolve the shape of structures for new functionality, rather than patching a DSL until it loses all elegance.

Since this issue is actually not about the implementation, but the long term viability of one syntax over another, I believe there is no cross purpose here. Native UIs may be one immediate goal, but they are not the purpose of this very issue.
Scrolling back in history, it seems to me you veered the discussion several times implementation. It's a worthy discussion, no doubt, but I think it warrants its own issue, as it doesn't answer the question that's asked at the top of this page.

dumblob commented 4 years ago

@Xananax thanks for clarification and the nudge.

This will be a way longer post than I originally intended, but I felt that it'll significantly contribute to the disambiguation between "wish" and "reality".

TL;DR: Swift/Dart/Qt/QML/WPF/... all is trash; declarative yields retained state (i.e. verbose syntax, nearly no dynamics, difficult imperativeness); imperative yields immediate mode (i.e. terse readable syntax, maximum possible dynamics, easy declarativeness on demand)

Since this issue is actually not about the implementation, but the long term viability of one syntax over another, I believe there is no cross purpose here. Native UIs may be one immediate goal, but they are not the purpose of this very issue. Scrolling back in history, it seems to me you veered the discussion several times implementation. It's a worthy discussion, no doubt, but I think it warrants its own issue, as it doesn't answer the question that's asked at the top of this page.

My whole point is, that syntax doesn't matter if semantics (you're referring to semantics discussion as "veering discussion with implementation") has a totally contradicting definition (i.e. make immediate mode UI by using retained mode). That's exactly what I showed in my comment https://github.com/vlang/v/issues/2065#issuecomment-536182187 above. And that's why I first want to land at the desired and non-contradicting semantics before we'll discuss syntax.

Let me shed some light on the whole problem of this GitHub Issue and why it's actually a misleading question.

Imagine you have a purely declarative programming language like Prolog. Prolog can guaranteed solve any problem in the world as it's turing complete. You actually used such declarative approach so much that basically every single existing UI library is built around the declarative approach (because for simple UIs where there is nearly no dynamics and rather minor content changes in run-time it's easier to create such UI library and easier to grasp though verbose in syntax).

It just happens, that many cases (actually vast majority when it comes to the number of their kinds) are not feasible to describe in Prolog (see Fifth Generation Computer) which lead you to create the icing on the declarative cake of futile (infeasible) endeavor to make declarative UIs more capable - the web CSS.

Imagine also, there is a purely imperative programming language like C. C can guaranteed solve any problem in the world as it's turing complete. You didn't use C's imperativeness for UIs (except in 3D games) because it wasn't foreseeable UIs will evolve into highly dynamic stuff and you believed in the declarative mantra thus proceeding with mimicking UI declarativeness (btw. notice, that it's more or less easy to mimick declarativeness in an imperative language, but it's difficult to mimick imperativeness in a declarative language).

It just happens, that majority of cases are feasible to describe in C (see e.g. evolution of the TIOBE index).

Now, Swift/Dart, Qt/QML, WPF, etc. are all built around a declarative approach. Asking which of them to choose implies declarative UI. But wait, commenters here in the discussion do not only want declarative UI, but they also want fully dynamic behavior (not known in compile time). We just learned though, that it's futile (infeasible) to build dynamic UIs around declarative approaches. Oh no, we lost this battle (unless we all have schizophrenia).

Well, not exactly. We also learned, that it's more or less easy to mimick declarativeness using imperative style. Could we then maybe describe UIs imperatively (rather then declaratively) and just for the few cases where declarativeness makes actually sense use the opportunity to mimick it? Voila, we now discovered immediate mode UIs (defined imperatively like in 3D games) but extended with the ability to save & restore state (i.e. mimick declarative UIs, aka retained state UIs).

To sum up, combining Prolog and C syntax is a nonsense. Asking about declarative syntax for UI specification is nonsense and won't lead anywhere if the audience will bring in stuff which can't be supported by declarativeness (i.e. dynamics as described by pretty much all commenters here).

Historically it also proved to be a nonsense to enhance/extend/enrich retained state UIs (i.e. syntax originally built around declarative approaches) by imperative stuff. But it works vice versa (i.e. enhance/extend/enrich immediate mode UIs by retained state stuff) as e.g. Quarks shows. Btw. Quarks doesn't use any special syntax - it's all plain C99 with automated generation of C structs for retained UI (easy to read & write by UI design tools), so leaving aside the fact, that Swift/Dart are declarative (retained state), it's similar on the logical level.

ylluminate commented 4 years ago

This is an exceptionally interesting dialogue. Appreciate the discussion and clarifications @dumblob . There's an awful lot of detail here - so let's distill this down into a concise plan of action if you don't mind.

Obviously and initially you were very opposed to making a new UI toolkit.

@medvednikov clearly already has a lot of time and thought committed to V UI and so this will move forward.

Please correct me if I'm wrong @dumblob: But it seems that you're recommending essentially taking Quarks and converting it to V and integrating it into the gg library since gg handles the generic graphics functionality for Linux, games and so forth that will underpin v ui itself that will handle native graphics and then use gg as necessary for non-native UI components...

Xananax commented 4 years ago

I understand where you're coming from and I think it's valid from that point of view to discuss syntax and implementation together, however I don't understand what is your criticism of declarative UIs?

You mention Prolog and a link wikipedia article, but those simply show that the specific approach Prolog took was not successful for specific reasons. As a matter of fact, the very article you link says that the paradigm may have been "ahead of its time".

You then go on to use CSS to further your point, as if CSS was an evidence of declarative UIs being bad. However, it is not an evidence. I, as well as many colleagues of different expertise (not necessarily web) I've conversed with throughout the years, happen to think that HTML+CSS, while being quite bad, is still, by very far, the best UI language we've ever created.
In other words, I don't understand what arguments you base yourself on to say that declarative UIs are "nonsense". Gargantuan cross-platform apps running on millions of computers, that even newbies can write, but that also are able to satisfy the most demanding business UI needs, certainly, cannot be considered "nonsense" from any pragmatic point of view? "Not ideal", at best, but what ever is?

I also do not understand the link between declarative/dynamic. There's no fundamental difference between expressing logic in a declarative manner or an imperative one. As a matter of fact, a relatively simple parser could turn one into the other back and forth at will. They're both expressions of intent, and what matters for the discussion is how they're understood and manipulated by humans, not how they end up being compiled and used.

A declarative UI can be extended with behavior; this can happen at compile time, or at run-time. Visitors can consume the plain objects and spew out whatever is needed.

A declarative UI language does not preclude custom behaviour created in userland, unless it's a DSL, which is what I'm arguing against. If the language is a DSL, then it gets parsed by the compiler, and logic gets applied by the compiler, and extensions become hard to create. But if the language is just a data structure, then even the most beginner of users can apply some function to them.

From there, I do not actually think it matters overmuch if there are methods in there or whatever imperative syntax; purely declarative UIs are easier to extend (because function bodies are not modifiable), but it's not that huge of a difference.

As far as I'm concerned, this is a false dichotomy. You can have any mix of imperative and declarative as you want, leaning more into one or other of those extremes. The complexity is the same, it's just represented differently. It all depends where you prefer to slice your cake.

I think we are saying the same thing, but you say augmenting declarative UIs has been historically shown to not work, but don't provide any example of why. The languages you do mention as examples are all wildly successful, so I'm pretty confused by that.

I also want to clarify I just landed in this issue by pure happenstance and have no stake whatsoever, so I'm purely discussing this out of curiosity.

nodrygo commented 4 years ago

Hi @medvednikov V is very interesting thing congratulation

on the Gui side, a RedGui UI like should be really great ;-)
otherwise I find WxWigets a good candidate

medvednikov commented 4 years ago

@dumblob I decided to use imgui as the backend for V's ui for Linux.

It should be easy to optimize it and render things only when they need to be updated, like I did with my own renderer in Vid for example.