nevalang / neva

🌊 Dataflow programming language with static types and implicit parallelism. Compiles to native code and Go
https://nevalang.org
MIT License
91 stars 7 forks source link

Required outports #582

Open emil14 opened 5 months ago

emil14 commented 5 months ago

Current semantics is this - at least one outports must be used. This has some problems.

Problem

Unhandled Errors

First of all errors could be unhandled. If component has e.g. res T, err error outports then compiler will be fine with you using just res. Yes, this is how Go works but it's not like e.g. Rust works. Go isn't perfect language in that regard IMO.

Yes, there're situations where you sure you be fine. Well, I guess you use Must then? This is especially not a big deal if we implement ? error bypass operator.

Unhandled Defaults

If you match or mod or anything that case something you can actually avoid using :else (or whatever they have for "otherwise".

Might be related to #202.

Proposed Solution: ! Exclamation Mark Operator

Just add ! at the end of the port (not port's data-type because that's info about port, not it's type) and make it required. Compiler will force you to use it. If you only need one port - that will be required one.

component ReadAll(filename string) (res! string, err! error)

In this example all ports of ReadAll are required. It's inport is required because all inports are always required (or because if it doesn't have default value in case we will implement #564). It's outports are both required because they both have !. They both have it because it doesn't make sense not to use result and because the error must be handled.

For components with array-ports (like Match especially - "router" components) the syntax will be what you probably expect it to be:

component Match<T>(data T, [case] T) ([case]! T, else! T)

Again, it only make sense if you use case (at least one slot) and you also have to handle default case.

emil14 commented 5 months ago

We can maybe add rule that outport of type error must always have ! except that's the only one port.

And vice versa - if there's only one outport is shouldn't have ! because it's required anyway.

Catya3 commented 5 months ago

Any example where it could be useful other than err ports?

Here's how I would mark up some examples:

component ParseInt(s str) (res! int, err! error)

Here's a component which finds the index of a one of a set of [substr] in the input str and returns its index and which it found, and whether any string was found.

Which port would you mark as required here?

component Find(str string, [substr] any) (idx int, found string, ok bool)

Perhaps none because it depends on how the user wants to use it.

Catya3 commented 5 months ago

Besides some single output port components, are there any types in std today that should add ! on one of their ports?