“This is not a record”-Error when trying to sort a list

I want to sort my list descended but when I use the keyword .sort I get an error:

This is not a record, so it has no fields to access!

106|       { model | teams = List.sort.map (\p -> {p | activated = True}) model.teams, activatedOutput = True} 
                             ^^^^^^^^^
This `sort` value is a:

    List comparable -> List comparable

But I need a record with a map field!

This is the line I have modified and with which I want to sort the list.

    Submit -> 
          { model | teams = List.sort.map (\p -> {p | activated = True}) model.teams, activatedOutput = True} 

sort is not a keyword, it is a function that takes a list of comparable items and returns a new list of the sorted comparable items. You can’t combine it like that with the List.map function.
What you can do is to create a pipeline of functions that each use take and return a List, like
{ model | teams = model.teams |> List.sort |> List.map (\p -> {p | activated = True}) }.

This wont like that directly, because your teams List contains records, which are not comparable. There is List.sortBy to the rescue, see https://package.elm-lang.org/packages/elm/core/latest/List#sortBy
You would use it in pipeline style like that
{ model | teams = model.teams |> List.sortBy (\p -> tooSomeComparableValue p) |> List.map (\p -> {p | activated = True}) }.

2 Likes

There is also a nice shortcut version when sorting on a key in record:

model.persons
  |> List.sortBy  .lastName

So if these are my records and I want to sort it for players. I should insert “player” for “tooSomeComparableValue”. But if I do so I get an error

I cannot find a `player` variable:

119|       { model | teams = model.teams |> List.sortBy (\p -> player p) |> List.map (\p -> {p | activated = True}) } 
                                                               ^^^^^^
These names seem close though:

    poster
    always
    clamp
    class

Hint: Read <https://elm-lang.org/0.19.0/imports> to see how `import`
declarations work in Elm.

Code

 -- MODEL
    type alias Player =
      { player : String
      , strength : Int
      --, number : Int
      --, playernumber : Int
      --, placeholder : String
      --, counter : Int
      , activated : Bool
      }


    type alias Model =
      { content : String
      , teams : List Player
      , currentNumber : Int
      , currentPlayernumber: Int
      , currentPlayer : String
      , currentStrength : Int
      , placeholderPlayer : String
      , placeholderCounter : Int
      , placeholderStrength: Int
      , activatedOutput : Bool
      }


  


init : Model
init =
  { content = ""
  , teams = []
  , currentNumber = 0
  , currentPlayernumber = 0
  , currentPlayer = ""
  , currentStrength = 0
  , placeholderPlayer = ""
  , placeholderCounter = 1
  , placeholderStrength = 0
  , activatedOutput = False

   }

p.player rather than player p is the correct syntax here, so you can use @Atlewee’s suggestion.

Since teams : List Player, p in this context is one Player in the list.

The correct one is:

{ model | teams = model.teams |> List.sortBy (\p -> p.player) |> List.map (\p -> {p | activated = True}) }

You should probably find better names… Its easy to get confuesd when both the record and the field is refered to as player…

And it can be made more readable like this:

{ model | teams = 
  model.teams 
    |> List.sortBy .player          -- (This is sorting by player.player)
    |> List.map (\playerRecord -> { playerRecord | activated = True } )
}

You can also make it ultra readable like this:

activatePlayer : Player -> Player
activatePlayer p =
    { p | activated = True } 

model.teams 
    |> List.sortBy .player
    |> List.map activatePlayer
1 Like

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