How to reason about code to avoid equality checks

I’m currently working through the Elm Guide.

On completing the Forms section, I wrote this code.

I then read this post and realised that I seem to be approaching elm incorrectly.

Elm-format makes the code difficult to read, see lines 109 to 118, which again leads me to the same conclusion.

Please advise how to reason through the code to avoid all the equality checks.

You don’t need equality checks for booleans, so you can simplify

model.password
        == model.passwordAgain
        && pwLength model.password
        == True
        && pwIsUpper model.password
        == True
        && pwIsLower model.password
        == True
        && pwIsDigit model.password
        == True

By

model.password
        == model.passwordAgain
        && pwLength model.password
        && pwIsUpper model.password
        && pwIsLower model.password
        && pwIsDigit model.password

If you need a boolean to equal false, then you can use thenot function.

I wouldn’t worry about the discussion in the post you linked to. In their case, they were working on an editor and I think the function was called thousands of times when the user wrote a text of thousands of lines long.

In your and almost every use case, Elm (or rather the underlying JS code) is fast enough and you won’t need to worry too much about performance. Start worrying about it when you do an operation thousands of times per second, but especially if you notice slowness in your application.

In addition to @jfmengels’ answer, the workaround to elm-formats quirky formatting is to add parentheses:

vSubmitButton : Model -> Html msg
vSubmitButton model =
    if
        (model.password == model.passwordAgain)
            && (pwLength model.password == True)
            && (pwIsUpper model.password == True)
            && (pwIsLower model.password == True)
            && (pwIsDigit model.password == True)
    then
        button [ disabled False ] [ text "Submit" ]

    else
        button [ disabled True ] [ text "Submit" ]

But in this case it is even better to remove the == True parts, as mentioned.

Thank you very much.

Is there any way to use the Elm syntax to shorten this code, as all four functions call the same argument?

model.password
        == model.passwordAgain
        && pwLength model.password
        && pwIsUpper model.password
        && pwIsLower model.password
        && pwIsDigit model.password

Thank you for the suggestion.

You can write it as List.all ((|>) model.password) [ (==) model.passwordAgain, pwLength, pwIsUpper, pwIsLower, pwIsDigit ]
You can read that code as “check if all the functions in this list of functions produce True when you give them the argument model.password

This code is using some infix functions in their regular function syntax. Another way to write it is:

List.all (\f -> f model.password) [ (==) model.passwordAgain, pwLength, pwIsUpper, pwIsLower, pwIsDigit ]

and

List.all (\f -> f model.password) [ \p -> p == model.passwordAgain, pwLength, pwIsUpper, pwIsLower, pwIsDigit ]

2 Likes

The best way to handle this however is to have the functions that check the password return a List String and concatenate them. In the view, you can check for the result of the error check and if it is different than [] display the error messages.

Check the validation in elm-spa-example for inspiration on how to do this.

Thank you very much.

One last question on this thread:

How would I use the Elm syntax to shorten the following code, as the same function calls two different arguments:

if pwIsLower model.password || pwIsLower model.passwordAgain then

List.any pwIsLower [model.password, model.passwordAgain]

1 Like

@pdamoc AFAIK && will stop if the previous one is False, but List.all does not.

Looking at the implementation, List.all will exit as soon as it will encounter a False value.

In any case, I would use if pwIsLower model.password || pwIsLower model.passwordAgain then because I like the simple nature of it. Performance wise, I doubt that it will make all that much of a difference unless this is in a tight loop of some logic.

1 Like

Ah… You are right. It makes sense to do so as well. I was not expecting the laziness here.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.