back

by mpweiher·14d ago·view on hn ↗
Not just does the computer not do functional.

UI is also very much not functional, and in fact the lack of progress in UI the last 30-40 years can largely be traced to trying to create UI with procedural/functional programming languages, an instance of linguistic-architectural mismatch.

Further reading:

Programs = Data + Algorithms + Architecture: Consequences for Interactive Software Engineering -- Stéphane Chatty.

https://link.springer.com/chapter/10.1007/978-3-540-92698-6_...

Can Programmers Escape the Gentle Tyranny of call/return?

https://2020.programming-conference.org/details/salon-2020-p...

UIs Are Not Pure Functions of the Model - React.js and Cocoa Side by Side

https://blog.metaobject.com/2018/12/uis-are-not-pure-functio...

Beyond Procedure Calls as Component Glue: Connectors Deserve Metaclass Status

https://2024.splashcon.org/details/splash-2024-Onward-papers...

2 comments
Thanks for those links! Some of it was great reading.

What is your thesis then? What is UI?

"A view is a (visual) representation of its model. It would ordinarily highlight certain attributes of the model and suppress others. It is thus acting as a presentation filter."

https://web.archive.org/web/20090424042645/http://heim.ifi.u...

View and model are related, but neither is procedurally dominated by the other. The view is not a subroutine of the model, or vice versa.

They are related entities that communicate in order for the view to function as a representation of its model to the user, and for the model to be manipulated by the user.

To get the details I really recommend the Chatty paper. It is a bit hard to read, but delivers the goods.

Interesting, will check that out!

My working thesis is that UIs are basically video games. Just a gut feeling I can't really 100% put in words.

But essentially they're the same thing: Read input, update model, render view.

That's pretty much where immediate mode GUIs and to a less extent React came from. (Though for React the provenance is probably closer to the HTML web-app: send request - update model - return HTML with complete and completely new UI.)

The difference is that for most games, throwing away the complete rendered graphics and re-rendering from the world model is often the right approach.

For most UIs, it isn't, unless they really are very close to video games, for example mostly passive feed readers, video players etc.

> The difference is that for most games, throwing away the complete rendered graphics and re-rendering from the world model is often the right approach.

Well, that is what "retained mode" GUIs (i.e. those using control/widget trees and such) do too.

The immediate mode GUI to me always felt like an approach came up by people who do not really want to bother doing GUIs. In terms of games it is like mixing logic and presentation in a game like, e.g.

    int x, y;
    while (game_running) {
        draw_sprite(player, x, y);
        if (key_down(LEFT)) x -= 1;
        // etc
    }
basically like in a game that doesn't have a world model with entities etc, just draws sprites directly, handles input directly, etc. Which is very simple for simple stuff but doesn't scale as complexity increases.

Same with immediate mode GUIs and i don't think it is a coincidence that the more complex an imgui gets, the more it starts looking like a "retained mode" GUI and the gnarlier the code becomes.

> Well, [throwing away the complete rendered graphics] is what "retained mode" GUIs (i.e. those using control/widget trees and such) do too.

That turns out not to be the case.

The widget tree is retained.

When changes come in, the resulting damage from those changes is assessed and then the damaged parts are redrawn in an optimized fashion.

https://developer.apple.com/documentation/AppKit/NSView/draw...

This is an optimization that some GUI systems do but it is not inherent to "retained mode" GUIs, does not apply to all systems nor all systems use it. I remember GUI systems even from late 90s/early 2000s composing their widget trees afresh when needed (and in games it was pretty much always the norm for GUI systems to work like that after engine started taking GPUs for granted). Some would limit the refresh to widgets overlapping the damage region reported by the OS (if a compositor was not running, for OSes since Vista) but even that is just an optimization.

On the other hand immediate mode GUIs are inherently like that because that is their core premise.

> For most UIs, it isn't

Why? Genuinely asking, this topic is very interesting to me.

Because the UI is supposed to be stable.
Isn't that the Controller part in MVC
Common misconception, but nope.

The quote is from the original definition by Trygve Reenskaug, the inventor of MVC (see link above).

https://en.wikipedia.org/wiki/Trygve_Reenskaug

Here some more on that misconception:

https://blog.metaobject.com/2015/04/model-widget-controller-...

Declarative–reactive. Like SwiftUI.
> UI is also very much not functional,

I disagree, and I believe that the complete stagnation of GUIs is due to ignoring this.

There is no good reason why a GUI system isn't:

Description->Pack->Apply events->Generate assets->Render assets.

At each point you reify the result into an artifact that is everything the next stage needs. This has a couple of nice properties. One property is that everything is deterministic and testable. Another property is that after the pack and apply, everything is now embarrassingly parallel. Another good property is that you have an artifact that the accessibility people can latch onto before you bury it under pixels.

That would be a very functional way to deal with GUIs.

However, we continue inheriting properties and single main threading everything like we're still on 33MHz machines with 8MB of RAM.

You are applying a one way arrow to events where in real life events do change state and can completely change UI (and functions) itself. Which makes imperative always the superior mode.

What you described works only in super simple scenarios. Whink Web 1.0, when Javascript was used for basic form validation at best, and didn't change DOM that much.

>> UI is also very much not functional,

> I disagree, and I believe that the complete stagnation of GUIs is due to ignoring this.

I disagree with your assessment.

>Description->Pack->Apply events->Generate assets->Render assets.

1. What does that even mean? I don't see a UI in there at all, at best some graphics (Render).

2. That's not "functional". If anything, it looks like a pipeline, so dataflow. But then again, see (1)

3. Not sure why reification, that is turning things into objects, is functional to you. Reification, that is turning things into objects, is object-oriented.

4. MVC was actually created on 5.8 MHz machines with 128KB of RAM (including the display buffer). And still works beautifully today.

https://en.wikipedia.org/wiki/Xerox_Alto

Functional is all about reification. You take a set of things in, you apply/map/collect/fold/whatever, you eject a set of things out. That is 100% functional--every time you supply the same inputs you get exactly the same outputs. The point of functional programming is that you avoid mutation and hidden state.

And, um, side note: dataflow programming is almost always considered functional programming.

Object oriented, by contrast, is all about hidden state and mutation. I send a message or call a function on that object over there and fingers wiggle and magic happens. But I don't know what or when or even if it actually happened.

And increasing evidence suggests that MVC doesn't work beautifully today because it doesn't parallelize, and it scatters state between uncooperative things. Just ask every single GUI that exists--every single one hangs because somebody made an oops and put too much work on the single, blessed primary thread. Or they have janky scroll. Or resizes leave gunk on the screen. Or your system flashes and jiggles because it's too busy reflowing everything in the universe. Or ...

You obviously have some very non-standard definitions at work here. apply/map/collect are just higher order operations, they have nothing to do with reification, except that you need the functions that are arguments to be first class.

> dataflow programming is almost always considered functional programming

That turns out not to be the case. Dataflow programming shares some aspects with functional programming, they are not the same at all.

> Object oriented, by contrast, is all about hidden state and mutation.

That also turns out not to be the case at all. Heck, there were even object-functional programming languages.

> And increasing evidence suggests that MVC doesn't work beautifully today because it doesn't parallelize,

What does MVC have to do with parallelization, in your humble opinion?