Stream: beginners

Topic: problem with pattern matching


view this post on Zulip Artur Swiderski (May 24 2023 at 17:23):

I have to put inside dict something like this

SomeTag   1.1     #  some  tag and Frac

later I am using dict.get to take this value out, I have to match it against (SomeTag _ ) but for some reason Frac matching does not work at all I am getting crashes or failures depending on what I do. The same logic work with integral numbers this is definitely compiler issue and serious one

view this post on Zulip Anton (May 24 2023 at 17:41):

Hi @Artur Swiderski,
I believe this behavior is on purpose, checking floats for equality is not recommended. I'll make an issue to make a nice example demonstrating best practices. We should however provide a nice error when the user tries to do this, can you share your code and error message?

view this post on Zulip Artur Swiderski (May 24 2023 at 17:55):

there are many errors sometimes compiler crashes I do not have access to the code on this specific computer. Anyway something is wrong ? I want to patter match mostly against this tag I provided because this pattern need to be serviced differently than others. Alternative would be to create map only for storing floats. btw I don't know how to match against set (only list and I need set here ).
Is there any syntax to mach record ?

view this post on Zulip Brendan Hansknecht (May 24 2023 at 18:02):

Would be useful to see code examples, but I will try and answer some without it.

Is there any syntax to mach record ?

yes:

record = { a: 1, b: 2 }
when record is
    { a : 1, b: 2 } -> "matches when a equals 1 and b equals 2"
    { a : 10, b } -> "matches when a equals 10. will bind b such that it can be used in this branch"
    { a: newNameA, b: newNameB } -> "binds a as newNameA and b as newNameB"

view this post on Zulip Brendan Hansknecht (May 24 2023 at 18:04):

btw I don't know how to match against set (only list and I need set here ).

there is no way to match against a set directly. If you know the exact order, you could match against the set converted to a list.
More likely, you could check if a set contains another set. or something of that nature. Would need to know more details to comment more.

view this post on Zulip Brendan Hansknecht (May 24 2023 at 18:06):

there are many errors sometimes compiler crashes

If you are willing, filing bugs as you hit crashes is helpful. Preferably with minimal triggering examples, but even larger repros are useful.

view this post on Zulip Brendan Hansknecht (May 24 2023 at 18:13):

Oh, also, for matching the tag with an F32 in it, you should be able to do something like this:

when Dict.get myDict myKey is
    Ok (SomeTag floatVal) ->
        # here I can use floatVal. I can compare it to values with epsilon and such.
    _ ->
        # deal with other tags and such

view this post on Zulip Brendan Hansknecht (May 24 2023 at 18:15):

Lastly, if you really want to check that a float is close enough to 1.1, you could do:

when Dict.get myDict myKey is
    Ok (SomeTag floatVal) if Num.absDiff floatVal 1.1 < epsilon ->
        # This only matches if we have a float that is close to 1.1
    _ ->
        # deal with other tags and such

view this post on Zulip Brendan Hansknecht (May 24 2023 at 18:26):

Oh, one extra note, if you want decimals with equality, you can use Dec explicitly (in the future, this should become the default).

Then you can do something like:

SomeUnion: [SomeTag Dec]

when Dict.get myDict myKey is
    Ok (SomeTag 1.1) ->
        # This matches when the Dec is exactly 1.1
    _ ->
        # deal with other tags and such

view this post on Zulip Artur Swiderski (May 24 2023 at 19:56):

https://github.com/roc-lang/roc/issues/5442 <- I created this, using matching I redirected float to other branch but still compiler expect it to have certain capability. I can overcome this but I have to redesign stuff and a lot of boilerplate code needs to be created

view this post on Zulip Ayaz Hafiz (May 24 2023 at 20:00):

Roc doesn't support equality of floating point numbers, which is why the code you linked doesn't compile.

view this post on Zulip Artur Swiderski (May 24 2023 at 20:02):

yes but I created path to divert float to other branch where equality of float is not needed

view this post on Zulip Artur Swiderski (May 24 2023 at 20:02):

so i t should work imho

view this post on Zulip Ayaz Hafiz (May 24 2023 at 20:02):

I see what you're intending. Do you want

        Ok someTag ->
            newSet = Set.remove  myset  someTag
            someTag

in this branch, someTag to have type [Tag1, Tag2, Tag3]?

view this post on Zulip Ayaz Hafiz (May 24 2023 at 20:03):

Unfortunately, Roc does not work this way (presently). In that branch, someTag is not narrowed from the tag of the first branch, so it has type [Tag1, Tag2, Tag3, Gang F32]

view this post on Zulip Artur Swiderski (May 24 2023 at 20:03):

I want to redirect float from above path using this Ok (Gang val ) -> Tag3

view this post on Zulip Artur Swiderski (May 24 2023 at 20:04):

it is not like useless feature, it would help me to create what I want

view this post on Zulip Ayaz Hafiz (May 24 2023 at 20:05):

I agree. It's not currently supported, but you can get around it for now by listing out each variant. So something like

        Ok (Gang val ) ->  Tag3
        Ok Tag1 ->
            newSet = Set.remove  myset  Tag1
            Tag1
        Ok Tag2 ->
            newSet = Set.remove  myset  Tag2
            Tag2
        ...

or

helper = \tag ->
  newSet = Set.remove myset tag
  tag

...
        Ok (Gang val ) ->  Tag3
        Ok Tag1 -> helper Tag1
        Ok Tag2 -> helper Tag2
        ...

view this post on Zulip Artur Swiderski (May 24 2023 at 20:06):

I had that before but it is getting unmanageable when I have a lot of tags and I want to group them somehow

view this post on Zulip Ayaz Hafiz (May 24 2023 at 20:07):

Yeah that's fair. #ideas > type narrowing discusses adding support for what you'd want here.

view this post on Zulip Brendan Hansknecht (May 24 2023 at 20:08):

Note: you can also make this work by just avoiding floats. Change Str.toF32 to Str.toDec.

view this post on Zulip Artur Swiderski (May 24 2023 at 20:11):

I will check but I am sure that I tried and failed with Dec

view this post on Zulip Brendan Hansknecht (May 24 2023 at 20:12):

Hmm. Maybe there is some other Dec issue. It definitely is less tested that floats. Seemed to work with your small example in my testing.

view this post on Zulip Artur Swiderski (May 24 2023 at 20:29):

toDec does not work for me there is some compiler crash I registered issue

view this post on Zulip Artur Swiderski (May 24 2023 at 20:49):

btw how to create stand alone Dec number , is there any suffix ?

view this post on Zulip Brendan Hansknecht (May 24 2023 at 23:23):

1dec looks to work


Last updated: Jul 05 2025 at 12:14 UTC