Let's take a step back, here.

Conceptually, the `init` function is meant to say how to jumpstart your 
application. So what it should do, is provide the initial state of your 
model, and - optionally - telling the runtime to start executing some 
asynchronous task right away (a good example would be fetching some remote 
resource), as a Cmd.

When the runtime receives such a Cmd, it will do what your commanded it to 
do, and then call your `update` function with the current state of the 
model and the Msg that resulted from your Cmd.

Using `Task.perform` with a "no op" task to "trick" the runtime into 
calling your update feels wrong, as you say yourself. I'd argue that it's 
definitely abusing the the runtime, too.

So, let's have a look at what you are trying to accomplish: you want to 
execute a function on your model, before declaring it "final". You could do 
that by calling `update` with the appropriate Msg from your init function, 
*or* you could split off that branch into a proper function that transforms 
your model.

What you'd end up with, then, is something like this:

```
init : (Model, Cmd msg)
init =
 ( initialModel |> transformIt, Cmd.none)
```

Your update function would call that exact same function - which means you 
could think of the update function like a sort of "translation" from 
messages to function calls that transform your model, rather than the one 
central place to bundle all your logic.

Hope this helps :)

Kr,

Ilias

Op woensdag 8 maart 2017 22:50:00 UTC+1 schreef Duane Johnson:
>
> Preface: while I've been using Elm for a while, I've only just begun using 
> messages and commands, so it's ok to treat me like a newbie here. This is a 
> capture of my experience of Elm while trying to figure out how to send an 
> initial message.
>
>
> I find the `Cmd` type a little confusing, especially in the init function. 
> Conceptually, I want to "kick off" an initial fetch of data from client to 
> server, and it would make intuitive sense if I were permitted to do this:
>
> ```
> init : (Model, Msg)
> init =
>     { initialModel, FetchStatus 0 }
> ```
>
> But instead, the type of `init` is required to be this:
>
> ```
> init : (Model, Cmd Msg)
> init =
>     { initialModel, ... }
> ```
>
> When I get to this point, I need to look up the documentation on Cmd. 
> Having read the guide several months ago, I have a vague impression that I 
> may need to "perform" something to get my message into a Cmd type. I look 
> at the `Platform.Cmd` documentation, and I see there's a `Cmd` type which 
> looks like a constructor. So I try this:
>
> ```
> init : (Model, Cmd Msg)
> init =
>     { initialModel, Cmd (FetchStatus 0) }
> ```
>
> But I get an error: "Cannot find variable `Cmd`". Having some experience 
> with Elm, I believe this may mean although Cmd is a type, its constructor 
> is not exposed.
>
> At this point, the `map` function looks a little promising, because it 
> takes some things that are not Cmd and produces `Cmd msg`, i.e. precisely 
> the type I'm looking for. However, it's not clear to me what the first 
> parameter to map is (a function that takes `a` and produces `msg`?) There's 
> no documentation on this `map` function.
>
> Then I peruse the docs some more ("maybe this is so common a thing that it 
> belongs in Basics? or maybe I missed something in Platform, since Cmd is a 
> submodule of Platform?") and arrive at the Task documentation, where I see 
> the "perform" signature:
>
> perform 
> <http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Task#perform> : 
> (a -> msg) -> Task 
> <http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Task#Task> Never 
> <http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Basics#Never> a 
> -> Cmd 
> <http://package.elm-lang.org/packages/elm-lang/core/5.1.1/Platform-Cmd#Cmd> 
> msg
>
> This looks promising as well, because it takes some things and produces a 
> `Cmd msg`. But the example in the documentation shows how to use `perform` 
> with `Time.now` which further confuses things because I just want to pass a 
> Time value to my FetchStatus, like it was meant to receive (not necessarily 
> a "now" value). If I try this:
>
> ```
> init : ( Model, Cmd Msg )
> init =
>     ( initialModel, Task.perform FetchStatus 0 )
> ```
>
> I get
>
> ```
> Function `perform` is expecting the 2nd argument to be:
>     Task.Task Never Time
> ```
>
> So finally I realize that I need to pass a "succeed" task to my `perform` 
> call so I can create a `Cmd msg` of the type I need:
>
> ```
> init : ( Model, Cmd Msg )
> init =
>     ( initialModel, Task.perform FetchStatus (Task.succeed 0) )
> ```
>
> Subjectively, this all feels more convoluted than it needs to be. At a 
> basic level, I want to communicate an initial model and an initial "kick 
> off" message. It's confusing that Task types are involved in constructing 
> Cmd types. This makes finding the right documentation difficult. In 
> addition, it isn't clear why a Cmd is needed at all--why not a Msg, or a 
> List Msg? Conceptually, this would be a lower barrier to entry.
>
> This is just a running journal of my experience trying to do a basic Elm 
> task (no pun intended). I hope it helps make the Elm experience better in 
> some way for others.
>
> Best,
> Duane
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to