1. 26
  1.  

  2. 11

    Stores are globally accessible and can be connected to components.

    It’s interesting how this pattern has now permeated the frontend world so thoroughly that languages are being designed with global shared state as the language-blessed one-true-way to manage state.

    I wonder if this is, as my knee-jerk reaction wants to think, just inexperience with the issues this causes, or an actual discovery that the lessons learned about global state are not applicable in the programming model currently in use in browsers?

    1. 11

      The lessons of global state are really about shared mutable state. The ‘connect stores to components’ model provides components with access to shared immutable state instead.

      Specifically, the state is built via reduce (in the FP sense). The initial state, and an array of state-change-events, are reduced to a final state. This is a pure function; the only way for a component to vary the state is to add a new event to the array.

      This approach frequently means a load of boilerplate and cognitive overhead, and I’m ambivalent about how its benefits stack up against that drawback, but I’m happy enough with the pattern for now.

      1. 2

        I think what I am getting caught up on is that this is explicitly not a pure function, right? Or maybe I’m misunderstanding what they mean by “Stores are globally accessible”.

        If components were pure functions, then they would yield the same results for the same inputs. But they don’t, because in this model all components also have a hidden global variable that affects them.

        Ie. a pure function model would look like this:

        let myState = SomeStoreLibrary({
          title: "Hello, world!",
        });
        
        function MyWebPage(state) {
          return <span>state.title</span>;
        }
        
        render(MyWebPage(myState));
        

        The result of MyWebPage is wholly defined by its arguments, and it has no side-effects, ie. it’s a pure function.

        but the pattern I see used, and thought mint was endorsing, would be more like this:

        let myState = SomeStoreLibrary({
          title: "Hello, world!",
        });
        
        function MyWebPage() {
          return <span>myState.title</span>; // Global store access here, rather than taking state as an arg
        }
        
        render(MyWebPage());
        

        Now, the result of MyWebPage depends on the global state, and it’s no longer a pure function.

        1. 4

          But that’s just how closures work: in \x -> \y -> x, the result of inner function, \y -> x very much depends on x, which is not an argument. Referential transparency means not the absence of free variables, it means that, called with the same arguments, the function returns the same result.

          In more practical terms, there are two pure functional “fixes” for a global variable problem: either wrap the entire program into an immediately invoked function with a store argument, or (lambda lifting) just pass the store as a first argument to every function. The free versions are essentially just different syntaxes for the same program. The important thing is that, store being read-only during rendering, this doesn’t create mutable aliasing.

          What might be problematic is that each function has access to “too much” data, as it (together with all transitive callees) will inspect only a part of the store. One can imagine that passing views into sublimes of store would lead to a better architecture. I personally doubt it, as indeed it seems that UIs are inherently non-local (https://blog.royalsloth.eu/posts/the-complexity-that-lives-in-the-gui/), and projecting store will just create busy work.

      2. 2

        Generally it’s not an issue because that global state is not supposed to be mutated directly, usually you’ll have something like Redux sitting in the middle which ensures mutation happens in a controlled way.

      3. 8

        Is there any noun more overloaded than “mint”? Off the top of my head there’s the financial service (still around?), the Linux distro, and now this.

        1. 2

          I still think of “MiNT is now TOS”.

          1. 1

            Maybe, but as counterevidence, here’s an Elixir HTTP client that qualifies. https://github.com/elixir-mint/mint

          2. 3

            Can anyone offer a brief rundown on why one might want to use this rather than svelte?

            1. 4

              Probably because with svelte one still has to write actual javascript, with mint you can write mint-lang (whether this is better or worse is another question). See also: https://www.mint-lang.com/guide

              1. 0

                I was thinking the same thing

              2. 2

                This looks quite brilliant. I love that state updates are explicitly grouped into transactions via the next keyword. I love that promises are automatically awaited. I love that there’s strong static typing, algebraic data types, and pattern matching. I love that styling is first-class and scoped (as it is in svelte). I love that routing is built-in.

                My only concerns are over 1) cancelation, which seems like it could be handled by the compiler, and 2) interop with npm packages, which could be difficult to give up. I understand and commend the break from npm, but it introduces significant risk for real-world use. I will definitely be giving this a go for any future web front-end side projects, though.

                1. 1

                  This looks pretty cool, many parts remind me of Ur/Web. I wonder how much this was influenced by it.

                  1. 1

                    Global state as the dominant paradigm? “JavaScript interoperability”? Sounds like today is a Fuck You Friday.

                    Stories with similar links:

                    1. Mint: a programming language for writing single page applications via btbytes 1 year ago | 24 points | 12 comments