Hacker News new | past | comments | ask | show | jobs | submit login

Elm is fascinating since it shows that with the right architecture functional programming for GUI is possible without hatches like monads or hiding state in closures or green thread stacks.

Another things is that in Elm the state of the whole application is very visible. Typically just by looking at data structures and message types one gets how things work. The code just fills details.




I understand what you are saying, but - the whole point of abstractions is to "hide state". For example, what is nicer to write/read? Pseudocode -

    // Stateful
    state = {buttonClicked: false}
    render() {
      if(!state.buttonClicked) {
        return button({text: "Click Me", onClick: {state.buttonClicked=true}})
      } else {
        return text("Thanks!")
      }
    }
vs.

    // Implicit state
    render() {
      yield button({text: "Click Me", onClick})
      yield text("Thanks!")
    }


What is nicer to test and maintain?

To test render() in the clicked state with the explicit state I can call it with the corresponding state. With the implicit state at the very least I have to write a driver to run render() into the clicked state and then test the next state transition.

To understand the effects of the code on other parts of the application with the explicit state it is sufficient to look at the definition of the state. The implementation of render is only relevant if one wants to look at details. With the implicit state I have not only understand what render() is doing, but also understand how to properly call it from other parts of application. I.e. what happens when the render is called the third time?


Testing could be much easier for the implicit state version. I've not defined it, but you are assuming things about how the render function or the implicit state behaves.

In my hypothetical implicit state framework - A widget is composed of a sequence of steps, each of which is an independent widget. So it's easy to write invariant properties for each step -

For (text "String") it's guaranteed that the widget never returns a value or raises an event. i.e. the type is

    forall a. Widget a.
So the issue of calling render a third time never arises.


The explicit version we can understand how it works just by looking at it. The implicit version we need knowledge about how your hypothetical framework works.


Of course you need to understand how the framework works. But that's a fixed cost vs. having to understand a program from scratch everytime when your framework is not clear or powerful enough.

Would you also say using "goto" is easier because it's a simple jump, vs. having to understand how while/for loops work?


Hum... No. Abstractions can hide anything.

Besides, your example get much of its gains by hiding the behavior of that 'if' statement than by hiding that 'buttonClicked' stores the button data.


> Hum... No. Abstractions can hide anything.

Sure, I'm not going to argue the meaning of "state". You know what I mean. Hiding internal state is good for abstraction.

> Besides, your example get much of its gains by hiding the behavior of that 'if' statement than by hiding that 'buttonClicked' stores the button data.

The if statement is intrinsically linked to the boolean state. If your render function forgets its implicit state on every update, then it needs to painstakingly analyse an external state and recreate its internal state. That's a cost which can be avoided.


JS is very bad at this analyses of the external state. With Elm syntax it is less an issue.

The biggest drawback of the explicit state is that the separated GUI stages has to be named so the code can refer and match on them. This naming requires to spend mental energy when writing the code and is the reason behind complains about extra boilerplate in Elm.

In implicit state the stages are anonymous and hidden behind a semicolon (yield statements in your example). So it is faster to write code. Yet these nameless yet present states exist and makes much harder to grasp the code. One has to recover the states from the code, not from declarative description as with the explicit state.


No, I don't know what you mean.

You've used an example similar to a continuation, what is explicitly about flow control. Unless you are suggesting appropriating flow control into data (because you will need an interpreter) means that everything is "state".

I don't think that 'buttonClicked' value will make into the page state of an Elm program.


To me, the second is smaller but less clear for hiding the logic. I'd assume both button and text are output always.


It might seem like that, but javascript generator semantics mean that execution pauses at the first yield, and awaits external input before it resumes computation.

Also, the framework I described is only partially "hypothetical". [Concur-js](https://github.com/ajnsit/concur-js) gives you almost the same syntax and semantics. So you can try it out yourself :)




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: