Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern matching #747

Open
emil14 opened this issue Nov 3, 2024 · 5 comments
Open

Pattern matching #747

emil14 opened this issue Nov 3, 2024 · 5 comments

Comments

@emil14
Copy link
Collaborator

emil14 commented Nov 3, 2024

In this issue we discuss how #726 and #725 might handle incoming data comparing to some patterns, regardless what's the outcome of the executed branch (selecting or routing)

  1. What are use-cases we might and need to cover?
  2. How it could look and work in Nevalang?
  3. Should out pattern matching be exhaustive (require explicit handing of all possible cases for enums, result and maybe types)?

(Besides equality check)

@emil14
Copy link
Collaborator Author

emil14 commented Nov 3, 2024

Guard

UPDATE: Everything is much simpler:

true -> match {
    (2 > 2): 'a'
    (2 < 2): 'b'
    default: 'c'
}

This example shows match but also translates to switch:

true -> switch {
    (2 > 2) -> a
    (2 < 2) -> b
    default -> c
} -> println

We don't need anything to support this, besides "normal" form of the non-guard match/switch


Here's a snapshot of my old reasoning about this, concluding that we do need special syntax/semantic form for this kind of switch/match

Guard won't have incoming -> (and thus won't be used in chained connection). Semantics also different - instead of comparing some :data to set of options, it (awaiting for all condition messages, just like "normal" match/switch) checks (in order) if some of conditions is true and executes corresponding branch:

Match

match {
    :a: 1
    :b: 2
    :c: 3
} -> ...

Switch

switch {
    :a -> ...
    :b -> ...
    :c -> ...
}

Should this be match/switch?

So both API and behaviour is different, so under the hood it 100% will be different component. The question is should this be the same syntax construct?


Related to #731 #725 #726 #747

This was referenced Nov 4, 2024
@emil14
Copy link
Collaborator Author

emil14 commented Nov 5, 2024

Handling maybe<T>

In Rust handling of Option<T> with match is not a special case, because option is just an enum.
However, it's not the case for Nevalang, where maybe<T> is "base" type (it's not explained in terms of other types).

It means that this syntax that looks obvious for match:

maybeValue -> match {
    some: ...
    none: ...
}

Collides with its existing semantics, that should compare values by equality - in this case compare maybeValue with other values of type maybe.

Same things goes for switch:

maybeValue -> switch {
    some -> ...
    none -> ...
}

Both API and behaviour of underlaying components are different. E.g. match that we need for this looks like this

def MatchForMaybe<T>(data maybe<T>) (some T, none struct {})

There are no [case] we need to match with

Possible Implementation

If maybe is a special case at the level of stdlib, so maybe it should also be at the level of compiler.

The idea is that compiler checks if incoming message is of type maybe and in that case threats match differently - checks that "senders" it uses are portless "port-addresses" (fake node refs) with node names "some" and "none", threats them as T and struct {} correspondingly. Desugarer knows that these some and none are outports of match/switch self

Shadowing

It's possible that user might have nodes some and none.

Should this be match/switch?

Just like with guards question is shouldn't these be separate consturcts?

Alternative (no syntax)

Existing way of doing it is not that cumbersome

maybeValue -> unwrap
unwrap:some -> ...
unwrap:none -> ...

It's just less abstractions with just match

@emil14
Copy link
Collaborator Author

emil14 commented Nov 5, 2024

Multiple values?

Problem

How do we support case when several patterns lead to same branch? Example (v-lang):

enum Color {
	red
	blue
	green
}

fn is_red_or_blue(c Color) bool {
	return match c {
		.red, .blue { true } // comma can be used to test multiple values
		.green { false }
	}
}

Proposal

Just reuse existing syntax for multiple senders

true -> match {
  [2==2, 0==0]: ...
}

If match is set of connections, semantically, then constraints will - multiple senders are allowed on the left, but multiple receivers are not allowed on the right

@emil14
Copy link
Collaborator Author

emil14 commented Dec 14, 2024

Related to #802

@emil14
Copy link
Collaborator Author

emil14 commented Dec 14, 2024

This issue is to broad and should be decomposed into several smaller onces

  • working with tagged unions
  • other kinds of pattern matching

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant