-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Proposal: Active Patterns #5718
Comments
This suggestion uses a number of hypothetical C# language features that it doesn't describe in enough detail to evaluate. We're going to continue working on specifying and prototyping the elements of the language one-by-one and evaluate those elements against the use cases. |
@gafter I just revamped the original proposal, so all of the previous assumptions went away. |
I don't know where these declared operators are proposed to be allowed. You appear to be declaring them without any enclosing type. I don't know what the scope of the names appearing in the returns clause is. You say they are classes, but then you return them as if they are expressions. As you say, "ouch". You're defining |
Inline records here are not a special kind, they will be translate to what #5757 suggests (depending on
You're saying that what have proposed in #206 can be written like this? public class Polar(double R, double Theta);
public class Cartesian(double X, double Y) {
public static implicit operator Polar(Cartesian c) =>
Polar(Math.Sqrt(c.X*c.X + c.Y*c.Y), Math.Atan2(c.Y, c.X));
}
var c = Cartesian(3, 4);
if (c is Polar(R, *)) Console.WriteLine(R); So what is the point of declaring Moreover, this is exactly a port of F# active patterns, so you don't have to explicitly declare a new type when you just want to use them as pattern on other types. |
There are many contexts in which types are implicitly declared in F#. We're not planning to do that. At least not right now. |
@gafter Using One advantage of using Yes, for methods like |
In C# as well; iterator and async methods, closures, anonymous types, to name a few. Although they are all internal but I had even suggested a way to make the latter more useful in this #3304 comment. It's inevitable if you want a robust language.
Actually I did describe it. In the 5th bullet. They are declared in the target type (like
Yes, they are record types and from examples in #206 you can create them without |
If we do that, they would be invocable without |
@gafter you mean I missed the parentheses for records without members like |
I don't know what you mean by "optional in record declarations". If you don't have parens in the declaration, then you don't have a record. You have an ordinary class declaration. |
That means a lot of parens should be added to the examples above? This can be still optional in
you won't be able to declare ordinary classes in there anyway. |
@alrz As I said, there are a lot of undescribed language proposals hidden in your examples. |
@gafter I'm just saying that // case 1
public sealed class RGB(double R, double G, double B);
public static implicit operator RGB(Color col) =>
RGB(col.R, col.G, col.B);
// case 2
public sealed class Integer(int value);
public static implicit operator Integer(string str) =>
int.TryParse(str, ref int value) ? Integer(value) : null;
public sealed class Polar(double R, double Theta);
public static implicit operator Polar(Cartesian c) =>
c.X != 0 || c.Y != 0 ? Polar(Math.Sqrt(c.X*c.X + c.Y*c.Y), Math.Atan2(c.Y, c.X)) : null;
// case 3
public abstract sealed class P {
public sealed class Even() : P;
public sealed class Odd() : P;
}
public static implicit operator P(int num) =>
num % 2 == 0 ? Even() : Odd();
// case 4
public abstract class N;
public sealed class One() : N;
public sealed class Two() : N;
public static implicit operator N(int num) =>
num match(case 1: One() case 2: Two() case *: null); So yes, they are pretty much like conversion operators. The advantages of using
Yes it can, but what if it doesn't at all (in case of a complete pattern)? Its possibility of failure (which must be determined at compile-time) is not based on the return value, it's based on the target record type completeness, in this case, |
Closing in favor of extension |
Background
Active patterns enable you to define custom patterns to be used either on record types or non-record types. Currently, according to #206 custom patterns will be supported through
is
operator:Which is very confusing already, because:
static
class (described in this #206 comment though)out
parameters which eventually came out asPolar
parameters. Ouch.Meanwhile, active patterns in F# are pretty powerful and interestingly implemented:
Case 1: complete, with one possibility, implemented as
't -> 'r
:Case 2: partial, with one possibility, implemented as
't -> 'r option
(this is the only case possible viais
operator):Case 3: complete, with up to 7 possibilities, implemented as
't -> Choice<'r1, 'r2, ...>
. Note that no new type will be created, pattern possibilities actually map to theChoice
members.where
't
is the target type and'r
is the return type.There is no case 4: partial, with multiple possibilities. But you can define multiple partial active patterns and combine them:
According to aforementioned issue, there is no support for pattern combination. (see #5154 comment)
Proposal
This proposal supports all four cases above. Active patterns will be defined as user-defined overloads of the operator
is
.Remarks
class
because if more than one record were defined then all of them implicitly inherit from a common compiler-generatedabstract class
.complete
patterns will be generated assealed class
with asealed abstract
base class, as proposed in Proposal: Add completeness checking to pattern matching draft specification #188.null
is used for whenpartial
patterns fail, so compiler would generate an error if anull
is returned throughout acomplete
pattern.String
they should be allowed to be defined as an extension operator.switch
statements ormatch
oris
expressions, just like F# AND and OR patterns.Examples
An example from here:
The text was updated successfully, but these errors were encountered: