Impressions from a new user

275 views
Skip to first unread message

barmin

unread,
Jun 23, 2016, 10:15:57 AM6/23/16
to Elm Discuss
Hello,

This is my first post on this list. I've been experimenting with elm for the last few days and this is a very pleasant experience.

First I want to thank Evan and the community for the excellent documentation. The guide and other docs allowed me to get into the language much quicker than I was expecting.

I spent some time finding what elm-package incantations I had to do to make the examples work, though. I think the guide should include some up-to-date information about this.

Some other impressions:

- I was kind of expecting to find list comprehensions in the language. Did I miss something or are they not there?

- Some object "toString" representations are not so informative. Example from the repl:

> s = Date.fromString "2016-06-17T11:15:00+0200"
Ok {} : Result.Result String Date.Date

To be honest, I first thought something had gone wrong... Is there a reason it does not display something like

Ok {2016-06-17 11:15:00} : Result.Result String Date.Date

- It's a pity that the repl does not support multiline definitions. It would be soooo much easier if I could copy-paste code from my editor to test it. (I know, I can add \'s at the end of lines, but this is not a quick copy-paste...)

- I would expect that it is much easier to include an external css file in the html generated by elm. I know I can compile to js and include it in a custom html file, but for a quick test it would be much easier to be able to specify a css file to use (and I'm not yet convinced that I want to write my CSS in elm...)

- As an exercise, I'm migrating a small app I first wrote in python. One thing I really miss is string interpolation. For instance I had the following code in python:

'%02d:%02d' % (t.hour, t.minute)

that became

(String.pad 2 '0' <| toString (hour date)) ++ ":" ++ (String.pad 2 '0' <| toString (minute date))

- Coming from python I'm maybe a little biased towards dicts, but I would have appreciated a native syntax for writing dicts instead of using Dict.fromList.

- I find the elm code I'm writing quite verbose as compared to the original python code. But that might be because I'm not using elm to its full potential yet.

- Although I understand more and more of what I'm doing, it's still a lot of trial and error. But having a very helpful compiler makes me confident that if it compiles, I'm not that far from what I wanted to do... This is very refreshing after some years of python as my main language!

These are my first impressions after a few hours exploring the language. But globally I'm very happy with my first experiences in elm, and if I find the time I'm going to go on exploring elm during the next weeks!

I do have a few more questions but I will make separate threads.

Thanks again for the great project,

Matthieu

Janis Voigtländer

unread,
Jun 23, 2016, 10:47:35 AM6/23/16
to elm-d...@googlegroups.com
To answer two of your questions:

There are no list comprehensions in Elm. 

The thing with printing Date is a known issue. See https://github.com/elm-lang/core/pull/442.
--
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...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

barmin

unread,
Jun 23, 2016, 11:14:15 AM6/23/16
to elm-d...@googlegroups.com
Thanks for the answers and sorry that I raised a known issue. I'll try to avoid that in the future.

Matthieu

Le 23. 06. 16 à 16:47, Janis Voigtländer a écrit :

Ian McCowan

unread,
Jun 23, 2016, 11:27:45 AM6/23/16
to Elm Discuss
Little suggestions on your no-string-interpolation example:

(String.pad 2 '0' <| toString (hour date)) ++ ":" ++ (String.pad 2 '0' <| toString (minute date))

1. You could try http://package.elm-lang.org/packages/mgold/elm-date-format/1.1.4/ if you're not opposed to using a third party package.
2. Or pull the duplicate code out into a function:
formatTime : Int -> String
formatTime time
=
   
String.pad 2 '0' <| toString time

and do
   
String.join ":" [formatTime (hour date), formatTime (minute date)]

That's still not quite as tidy as string interpolation but I've found it's a good habit to get into to pull anything you do more than once out into its own function, especially in Elm; in Python my threshold tends to be three uses :)

barmin

unread,
Jun 23, 2016, 1:06:28 PM6/23/16
to elm-d...@googlegroups.com
Thanks Ian for your suggestions!

As for pulling the common code into another function, my threshold is probably still the python one ;-)

But I finally adopted your solution with the helper function defined in a let expression. That's already much better than my initial code!

let
formatTime time =
String.pad 2 '0' <| toString time
in
String.join ":" [formatTime (hour date), formatTime (minute date)]

Thanks,

Matthieu

> 1. You could try http://package.elm-lang.org/packages/mgold/elm-date-format/1.1.4/ if you're not opposed to using a third party package.
> 2. Or pull the duplicate code out into a function:
> |
> formatTime :Int->String
> formatTime time =
> String.pad 2'0'<|toString time
>
> anddo
> String.join ":"[formatTime (hour date),formatTime (minute date)]

Matthew Griffith

unread,
Jun 23, 2016, 4:37:21 PM6/23/16
to Elm Discuss
Hi Matthieu,

Welcome to elm!  I too have a background in Python and here are some things I've learned as I've written projects in elm.

You're right it is more verbose in a lot of cases.  What you get in a lot of cases is that it's very clear what's going on while in python there can be a decent amount of 'hiding the magic'.

As for Dicts, I would say double check to make sure you don't actually want a record.  Basically if you know all the fields at compile time...you probably want a record, not a dict. 

(as previous people have noted)  a few of your issues are definitely on the community radar.  There's a recent post about proposed string interpolation, stuff like that.  So, there's actually a good amount of work going on to cover the cases you mention.  It's a young language.


The list comprehension thing is interesting.  In elm the focus is on the List module as opposed to a specific syntax for list comprehensions.  I've found it to be very expressive.

So for something like `[i +5 for i in range(20)]`  in python, you could do something like `List.map ((+) 5) [0..20]`

Cheers and again, welcome to elm.

-Matt

barmin

unread,
Jun 24, 2016, 9:09:42 AM6/24/16
to elm-d...@googlegroups.com
Hi Matt,

Thanks for your nice answer!

> As for Dicts, I would say double check to make sure you don't
> actually want a record. Basically if you know all the fields at
> compile time...you probably want a record, not a dict.

I may have an habit of using dicts too often... (in python, almost everything is a dict anyway ;-) )

What do you think? in my code I have

type alias Model =
{ lines : Dict String Line
, from : String
, to : String
[...]
}


type alias Line =
{ name : String
, from : String
, to : String
[...]
}

The Dict content is static, but I chose a Dict in order to be able to iterate over it, as in

getTimes : Model -> Cmd Msg
getTimes model =
Cmd.batch <| List.map getLineTimes (Dict.values model.lines)

I also need to find a line from its name because each line has its own Http.get and needs to get the value back

type Msg
= FetchSucceed String (List String)
| ...


update : Msg -> Model -> ( Model, Cmd Msg )
update action model =
case action of

FetchSucceed name times ->
{ model
| lines =
let
line =
case Dict.get name model.lines of
Just l ->
l

Nothing -> -- should never occur!
Line name "" "" [] [] Nothing
[...]
in
Dict.insert name newLine model.lines


It seems to me that if I replace my Dict by a record I'll have to deal with each line separately. But maybe I'm missing something?

One thing that bothers me is that I must provide some code for the case when the key is not in the dict, although I know by design that it will not happen. This could be avoided by using records, of course.

> So for something like `[i +5 for i in range(20)]` in python, you could do something like `List.map ((+) 5) [0..20]`

Right, but I still like how python comprehensions allow to combine map, filter and cartesian product in a simple, short syntax!

> Cheers and again, welcome to elm.

Thanks :-)

Matthieu

Matthew Griffith

unread,
Jun 24, 2016, 9:56:53 AM6/24/16
to Elm Discuss
Ah, I see now :)

Yeah, elm requiring exhaustiveness for things like dict lookups can be a pain, but it will really save you on large codebases.  I use Maybe.withDefault quite a bit in those cases.  You could define emptyLine somewhere in your code and just do Maybe.withDefault emptyLine (Dict.get name model.lines)

Using dicts in how you're using them makes sense.  You might be able to use just a list instead of a dict, though I'm not sure how much (if anything) that would gain you.  It might be cleaner, it might not.  You might want to take a look at the Extra packages which add more functions to the standard library.  So, http://package.elm-lang.org/packages/elm-community/list-extra/2.0.1/List-Extra

On a separate note, one thing that took me a bit to discover in elm (and you may already be aware of) was using 'pipeline' style using |>.

[0..20]
|> List.map ((+) 5)
|> List.filter (\x -> x `rem` 2 == 0)
|> List.intersperse 5
|> List.foldl (+) 0


For me this is very powerful because its so easily extensible and readable.  I think if you converted the above to a list comprehension it'd be a bit of a beast :)  That being said, for small stuff list comprehensions are nice for sure.

I use the same pipeline style in my animation library as a way to specify keyframes.


-Matt

barmin

unread,
Jun 24, 2016, 11:42:31 AM6/24/16
to elm-d...@googlegroups.com
> You could define emptyLine somewhere in your code and just do Maybe.withDefault emptyLine (Dict.get name model.lines)

Oh yes, that's great! Adopted!

Thanks for the others pointers. I obviously still have quite a lot to discover in the language and its ecosystem! (although I was already aware of the |> notation, which is very convenient!)

Cheers,

Matthieu
Reply all
Reply to author
Forward
0 new messages