2

When you look at this excerpt of "An Elm introduction":

subscriptions : Model -> Sub Msg
subscriptions model =
  Time.every 1000 Tick

The model parameter passed to the function subscriptions must correspond to the current model of the app, i.e. if the model has changed in less that 1 second, the argument model passed to the function subscriptions must have taken into account this modification.

As in JS, there are 3 different ways to make a variable calculated in one function update msg model visible in another subscriptions model:

  1. make it a global,
  2. make it an object property,
  3. pass it as a parameter when calling B from A.

But only 2 if you have async code as in the function subscriptions to keep your model 'sync':

1- make it a global variable, then by reassignment, update the value of the current model:

function app() {
  const currentModel = initModel

  function update(msg, model) {
    const newModel = doSomething(msg, model)
    // REASSIGNMENT
    currentModel = newModel
  }

  function subscriptions() {
    doSomethingEveryOneSecond(currentModel)
  }
}

2- make it an object property

  function app() {
  const model = initModel

  function update(msg, model) {
    // MUTATION
    model.value = doSomething(msg, model)
  }
  // model ALWAYS represents the current model  
  function subscriptions(model) {
    doSomethingEveryOneSecond(model)
  }
}

My question is how does it work “under the hood” in The Elm Architecture to keep the model sync between the update and the subscriptions functions?

Thanks a LOT!

glennsl
  • 28,186
  • 12
  • 57
  • 75
germain
  • 148
  • 9
  • 1
    Afaik ever time a subscription fires, the `update` function is called on the model and then new `subscriptions` are calculated which will fire the next event. There is no "magic `model` variable that always refers to the current model object". – Bergi Sep 28 '18 at 16:17
  • Sorry, I don't really understand. You mean every time the `update` function is called, the `subscriptions` function is also invoked with the updated model passed to it ? – germain Sep 28 '18 at 16:33
  • 2
    Yes, if I remember correctly. – Bergi Sep 28 '18 at 16:34
  • Let's imagine you fire in the `subscriptions` an HTTP GET request every 10 seconds (you want to keep up to date the world population :-). You make the request but haven't got the response, at this time the model changes: you have just changed the background color of the website (sic) How the callback of the HTTP GET request could be aware of that modification if there is no `magic model variable` that always refers to the current model object ? Invoking the `subscriptions` function with the new model isn't gonna help... – germain Sep 29 '18 at 14:08
  • 1
    You don't "fire an HTTP GET request every 10 seconds" in the subscriptions. You can subscribe to a timer that will "wake you up" every ten seconds by sending you a message. You can then have your "update" function generate a "Cmd" that initiates an HTTP request (and the results will come back in another message). So there is no "callback" either, just a stream of messages being sent to update. – Thilo Oct 06 '18 at 13:40
  • Thanks @Thilo, the elm architecture is very well depicted in one comment ;-), I could not do better ! – germain Oct 07 '18 at 13:28

1 Answers1

1

This is part of the what I like about elm and how it steps around the fact that a pure function can't have side effects.

An elm program to run in a browser defines a main something like:

main =
  Browser.document { init = init, update = update, view = view, subscriptions = subscriptions }

Nowhere in one's own code does one make a call to any of the functions you pass as parameters in the above, that is all handled by the generated code.

So yes, however you want to think about it, there is somewhere a representation of the current state of the "model" that is being maintained for you and its this that is passed to the update function to generate the next version of the of the model and to the view function to generate a view and so on. Which means that you write pure functions and something else manages the side-effects.

For the most part you shouldn't worry about this (about the implementation) - that's the responsibility of the framework and the if it changes it won't matter so long as the behaviour remains consistent. That said, the generated code (javascript) is there to read if you want to explore more.

Murph
  • 9,985
  • 2
  • 26
  • 41
  • 1
    It should be stressed that the "current state of the model" is just what your previous update function produced. It is only passed along to the next update call, there is not much "maintainance" involved. In particular, it won't be changed in any way outside of your update method and nothing "acts on it" either. – Thilo Oct 06 '18 at 13:43