Given I've got a string that looks like this
"123x123x123
234x123x987
567x987x123"
I'd like to transform this into something like [{a: 123, b: 123, c: 123}, {a: 234, b: 123, c: 987}, {a: 567, b: 987, c: 123}].
Without access to the lsp right now, I'm somehow confused.
I'd have assumed something like:
inputDetails =
inputs
|> Str.split "\n"
|> List.dropIf Str.isEmpty
|> List.map parseLine
parseLine = \singleLine ->
lineParts = Str.split singleLine "x"
if List.len lineParts == 3 then
a = List.get? lineParts 0 |> Str.toI8
b = List.get? lineParts 1 |> Str.toI8
c = List.get? lineParts 2 |> Str.toI8
Ok { a, b, c }
else
Err InvalidInputFormat
Yet this is a list of results with properties of a result type which I can't seem to use in further functions requiring numbers. What would I need to do in order to work further with these properties?
You'll be looking for mapTry, of type List elem, (elem -> Result ok err) -> Result (List ok) err
I'd recommend something like:
inputDetails =
inputs
|> Str.split "\n"
|> List.dropIf Str.isEmpty
|> List.mapTry parseLine
parseLine = \line ->
parsedNums =
line
|> Str.split "x"
|> List.mapTry Str.toI8
when parsedNums is
Ok [a, b, c] -> Ok { a, b, c }
Ok _ -> Err WrongAmountOfNums
Err InvalidNumStr -> Err InvalidNum
This could help avoid the repetition in parseLine
The output of that would be Result (List { height : I8, length : I8, width : I8 }) [InvalidNum, WrongAmountOfNums]
right? Given I'd need to pass this into a further function, just calling
` |> List.map \element -> someFunction element.a element.b element.c
wouldn't work, right?
@Tobias Steckenborn yes, we can't with the above code just use inputDetails
, as errors have potentially occurred. My code changes inputDetails
from List (Result { ... } [...])
to Result (List { ... }) [...]
, but there is still a Result
being returned
If you want to access the values inside, you could either put a question mark on |> List.mapTry? parseLine
to propagate the potential error up to the result of the function these variables exist within, or call something like |> Result.withDefault []
to handle the result in-place.
Otherwise, there's not much to be done while the Result is as-of-yet "wrapped" around the useful value (that may or may not exist).
After that point, you could do what you're suggesting:
inputDetails =
inputs
|> Str.split "\n"
|> List.dropIf Str.isEmpty
|> List.mapTry? parseLine
|> List.map \element -> someFunction element.a element.b element.c
# ALTERNATIVELY
inputDetails =
inputs
|> Str.split "\n"
|> List.dropIf Str.isEmpty
|> List.mapTry parseLine
mappedDetails =
inputDetails?
|> List.map \element -> someFunction element.a element.b element.c
Are you sure that the alternative version should work?
I'm getting:
UNRECOGNIZED NAME
Nothing is named `inputDetails` in this scope.
Last updated: Jul 06 2025 at 12:14 UTC