Syntax-directed editors were all the rage in the late 70s early 80s...and a huge failure, because they were a lot more annoying than any text editor has a chance of ever being.
It's one of those things that, like visual programming, is absolutely and obviously The Right Thing™ until you try to implement it and use it.
That said, we have made progress in both areas, and maybe we will figure them out in the future.
Yes, it’s definitely not a trivial problem. But parinfer shows it can be done mostly non-annoyingly at least for lisp; what is less clear is whether it would generalize to languages with more syntax.
> Some languages just feel incredibly natural and frictionless for certain things, and nobody has really nailed UIs yet.
Emphatically yes. If you look at books written about the problem in the early 90s[1], they are still applicable today.
> The current solutions, although I find it hard to describe precisely, are always tantalizingly lacking in one way or another.
The best analysis of this I have seen so far is in Chatty's Programs = Data + Algorithms + Architecture: consequences for interactive software engineering [2]. It's a bit hard to get through, but absolutely worth it.
As a short summary, the problem is architectural, or more specifically linguistic/architectural mismatch: the architecture our "general purpose" programming languages induces, which is the call/return architectural style, does not match the architecture required for user interfaces, but rather conflicts with that style.
I also wrote about it in Can Programmers Escape the Gentle Tyranny of call/return?.
My current approach is to first build a programming language that can easily express alternative architectural styles: Objective-Smalltalk [4].
With that I am now working an a UI framework I call interscript, including HTMXNative and other goodies.
Interesting that you still stand by that, even after Apple moved to the exact same model with Swift UI.
Narrowmindedly worrying about syntactical differences is contributing nothing to the conversation. The point is relinquishing control of state to the framework (be it via props, hooks or @State), and drawing the UI as a pure representation of whatever the framework tells you. Hence ui = f(state). This gets you a metric ton of advantages, which is why every modern framework is doing it.
Classes, by themselves, are inadequate as containers for state unless that state must only exist in memory and never be observed, synchronized or serialized. You can attempt to patch that with decorators, ORMs or whatever, but now you're doing the same thing as React is doing with functions.
Interesting that you would think Apple introducing Swift UI would have any bearing on the correctness of that blog post.
Why do you think it would?
Did you misread my post as "ha ha, Apple does it differently and therefore react is wrong"?
If so, you certainly misread it a lot, and you have the wrong person. I have tons of posts about Apple getting things wrong.
Anyway, did you miss the following part?
I also think that despite all the flaws, react.js and react.native are currently eating native development's lunch.
Clearly I made the point in my post that this approach has a lot of mindspace, despite the obvious flaws, so not sure how you pointing out that this approach has a lot of mindspace invalidates my post.
> Hence ui = f(state).
Every UI is always some mapping of the state. Otherwise it isn't really a UI, is it? What would it be, in your opinion, if it didn't map the state?
> pure representation
What does "pure representation" mean to you? I covered in the post that it sure as hell isn't a pure function of the state. And cannot be.
Did you miss the part where David Abramov conceded that point?
To elaborate a bit, React components aren’t always “pure” in strict FP sense of the word. They’re also not always functions (although we’re adding a stateful function API as a preferred alternative to classes soon). Support for local state and side effects is absolutely a core feature of React components and not something we avoid for “purity”.
> This [ui=f(state)] gets you a metric ton of advantages,
Well, yes. Like being a working UI, for example, which is why MVC is also structured this way.
But can you elaborate the specific advantages you believe the react approach gives us over, say, MVC?
The post elaborates that it would be really nice if UI were a pure function of the state. But it just isn't. And trying to pretend that it is might seemingly buy you some of those advantages, but at a huge cost.
Maybe it's a me-thing, but when I see the creators of a system I trust basically deprecate it, then I try to re-evaluate my viewpoint. Also, when I read the post a few years back, I honestly thought that it must have been a product of its time.
> Every UI is always some mapping of the state.
Sure, but it previously wasn't described as such. It was described as a list of imperative operations "if x do that" (unless the developer just gave up and had a giant refreshEverything() function).
IIRC, at the time, MVC had a common problem of controller bloat, precisely because it was trying to perform the reconciliation between view and model imperatively rather than simply describing it as a function. MVVM solved this partially with data-binding, but depending on the framework, you still had lackluster handling of derived state inside the view-model.
> What does "pure representation" mean to you?
I mean that, the render function of the component is a 100% pure function of the state that the framework injects. By "render function" I mean everything except the statements beginning with `use...`. Those are just React's syntax for defining the component. Another framework such as SwiftUI might have defined them outside the function.
> But can you elaborate the specific advantages you believe the react approach gives us over, say, MVC?
There are so many resources on this, so I don't know what I can say to convince you, but I'll try:
* The Compiler. Regardless of whether you think it’s self-inflicted complexity (I don’t), functional patterns generally are easier to statically analyze and transform.
* Transitions, concurrent rendering, suspense, & time-slicing. All of these are possible by rendering components with outdated state. A low priority update may trigger a loading state and defer its commit. Meanwhile, high priority updates can continue to work as usual. In the past ~2 years, this is easily where I've seen the most UX & DX gains in frontend.
* Most importantly: readability. Even if components are only 90% pure, I still see side-effects and state clearly marked. Even in MVVM, I've seen so much spaghetti from my coworkers. In React & post-React frameworks, when debugging a component, I have a much narrower range of things I need to check. For example, I don't have to worry that an object I'm reading from is being mutated by a component on a completely different route.
Overall, the reason why this post rubs me the wrong way, is that you took a theoretical design document, misunderstood it for the actual, practical implementation and snarked at the authors for not going with the "obviously correct" solution of OOP. Not seeing the bigger picture in 2018 is understandable, but now it's... interesting.
> IIRC, at the time, MVC had a common problem of controller bloat,
Nope. Non-MVC implementations had the problem of controller bloat, because they didn't actually implement MVC.
> the render function of the component is a 100% pure function of the state that the framework injects.
Except, as I've correctly pointed out: it's not.
[Advantages]
None of this is in any way specific ("The compiler". Seriously?) or clearly an advantage that can be tied to this type of framework. So yes: you're not even close to convincing me. Because there's no "there" there.
> the reason why this post rubs me the wrong way, is that you took a theoretical design document, misunderstood it for the actual, practical implementation
You misunderstood the post. Completely. The document claims "pure function". This is laughably false. The question is what is left when you remove "pure" from "pure function". And the answer to that is: nothing.
That doesn't mean there are no benefits, but the benefits cannot be "what you get from being a 100% pure function", because it ain't.
Just like the benefit of butter can't be "it's 100% fat free". Because it ain't.
And if you keep insisting that those are the benefits, then I don't know how to help you.
And again, it doesn't mean there are no benefits, but they are both smaller than and quite different from what you claim. And with the benefit being fairly small, the other question is what the cost is of pretending this is so when it is not. And the answer is: pretty high.
And it's funny that on the one hand you go with the same "well, you're taking the "100% pure" thing too literally", when just a few lines above, you yourself made "100% pure function" the defining characteristic.
So which is it? Make up your mind. It appears to be Schröding-important.
Any UI that actually is a UI is some sort of function of the state. Otherwise it is not a UI but random graphics and/or decoration.
With strong justification, as one of the reasons their earlier bid for secession from the UK was squashed was the argument that secession from the UK would also automatically kick them out of the EU.
The issue with JS is that each page gets its own execution context so they don’t share any memory. I am actually curious what does the WebView do to save on RAM here?
It doesn't have to "do" anything special if you just use it for rendering HTML, and not for running gargantuan layers of JS frameworks.
If you run gargantuan layers of JS frameworks in a WebView it will perform just as badly as a full browser. After all, a browser is (more or less) just a process wrapped around a WebView.
You’re correct. I meant to say textures, but even that isn’t completely accurate.
AppKit used to generate the bitmap directly through CoreGraphics (PDF model). Now it uses Core Animation and Metal and no longer draws the bitmap directly.
Code that is easy to test tends to be well-structured.
Code that is badly structured tends to be hard to test.
TDD is not a QA methodology, it is a design methodology. It also tends to help quality out a lot, but that's a secondary effect.
reply