Open VBAndCs opened 4 years ago
Or perhaps:
If obj Matches String Into s AndAlso s.Length > 0 Then
End If
Two keywords, no parentheses, and doesn't repurpose an existing keyword for wildly different behavior:
Dim o As Object = 5
Dim result1 = CType(o, Random) ' throws a runtime exception
Dim result2 = CType(o, rnd As Random) ' returns a boolean
A side benefit is avoiding the unclear mess that is the TypeOf syntax.
Matches is a new keyword (a breaking change) in a wrong context. It refers to regular expressions and doesn't indicate types. Besides, this a bad usage of a new keyword. I would suggest:
obj Matches s As String
I hate to use the word Into in this matter.
I first thought of:
obj CastsTo s As String
but this quickly brings up CType, and I found that:
CType(obj, s As String)
is the perfect one for the job. It has a form of a function, but it is a keyword and this can allow us to modify the syntax as we want adding a declaration part. I fall in love with it in a glimpse.
I see no deal of have two formulas of CType. It will not break anything, and we have many keywords with different usages, such as conditional If and ternary If.
Matches is a new keyword ... in a wrong context. It refers to regular expressions and doesn't indicate types.
When you work with regular expressions, you write a pattern (using regular expression syntax) and check if a string matches the pattern; you can optionally capture parts of the string that match subpatterns. That is precisely the model for pattern matching (note: not just type-check-and-cast) -- does the subject of the Select
match any of the Case
patterns? And if it does, optionally extract all or some into a new variable or variables.
But you seem to conflate generalized pattern matching with type-check-and-cast (as evidenced by the title of this issue). VB.NET already has a limited form of pattern matching, unrelated to type checks:
Dim i = 17
Select i
Case 1
Case 5 To 20 ' range pattern
Case < 0, > 100 ' OR pattern
End Select
and in the context of generalized pattern matching, I think it more sensible to put the pattern before the (optional) variable introduction/extraction.
I am against the C# type-b4-var style, period. It is not a VB style and must not be. We are not writing an essay here to think what should comes first. A programming language is a set of rules that programmers learn and use. My suggestions follows the VB.NET common sense, and this is how I would like to have this feature. In fact I hate most of C# new syntax, esp switch expression and decided not to ever use it! I will not contaminate my code with such abomination syntax. So, the only logic here is the VB.NET lang logic. We should understand the meaning from our general knowledge about the language. Matches will not satisfy that, but CType will.
I am against the C# type-b4-var style, period. It is not a VB style and must not be.
You're not alone. Eric Lippert lists the C# variable declaration style as one of the 10 worst C# features (see # 5).
But Into
is no less a part of VB.NET syntax.
We need to clarify what the goal is here:
Is the goal only to simplify this idiom?
Dim o As Object If TypeOf o Is String Then Dim s = CType(o, String) Console.WriteLine(s.Length) End If
Then we can adjust the language to not require a separate variable (#172):
Dim o As Object If TypeOf o Is String Then Console.WriteLine(o.Length)
and extended to Select
:
Select o Case String Console.WriteLine(o.Length) Case Integer Console.WriteLine(o * 5) End Select
Is the goal to provide a generalized pattern matching syntax, for different kinds of patterns, not just type-checking-and-variable? Then every usage of patterns has two parts:
For this, it makes more sense to put the pattern first, because the pattern test is the first step; which information goes into which variables is invariably secondary to the pattern match itself.
This has nothing to do with VB.NET-style variable declaration vs C#-style variable declaration. The pattern could be unrelated to type checking, such as:
Dim s As String Select s Case "a" To "z" Into lowercase, "A" To "Z" Into uppercase End Select
or checking for public properties, without checking the type of the object itself:
Dim o As Object Select o Case With {.LastName Matches String Into lname, .FirstName Matches String Into fname} Console.WriteLine($"Last name = {lname}, First name = {fname}") End Select
So, the only logic here is the VB.NET lang logic.
And VB.NET already has a model for generalized pattern matching, albeit a severely limited one: the various patterns that can follow each Case
clause in a Select Case
. Applying a similar model to any boolean context (If ... Then
, Do ... While
) seems worth a single new keyword.
Matches will not satisfy that, but CType will.
As noted, if the goal is a generalized pattern matching syntax, CType is almost irrelevant.
As I said about C#, this is a kind of contaminating the language! Yesterday, I brought up the C# complexity issue in csharp room on gitter, and I want to quote @mikernet reply to me:
I'm used to C# syntax and although I relatively regularly have to read or convert snippets of code in VB I always struggle a bit with it because I just don't use it enough. I'm sure I could become just as comfortable as I am with C# but it's just a matter of familiarity with a particular syntax.
I can empathize with people learning C# somewhat recently and thus haven't been using it for the last 20 years. I've had the opportunity to start at the beginning with a slow and progressive build-up to the point where the language is now. C# is waaaaay harder to start learning now and has become a bit of a nightmare for newer developers - my onboarding time for a student intern to become somewhat capable of contributing effectively to our projects has increased very dramatically over the years and I can only see that getting worse. At this point, my intern placements are just fun charity work for the local community.
The C# language team has decided the things it values and making the language simple to reason about is definitely not a top priority. For better or worse, performance and other factors take the front seat.
I have more to say in next reply: ....
When any language wants to add a new feature, it must follow these rules:
So, this is why I hate most of pattern matching in C# and will never use them in my code.
My vision of VB in all my proposals is to achieve the above goals, so any beginner takes the first look at the language finds it:
Any feature that breaks these expectation must be avoided. For example:
Dim s As String
Select s
Case "a" To "z" Into lowercase, "A" To "Z" Into uppercase
End Select
What can I do with two different vars in one case? Obviously I will need to write If statement on lowercase and uppercase (in fact they have to be nullable to have control over them) So, the smart thing to do is to have two cases, and then we can use s directly in each case with no need for additional vars:
Dim s As String
Select s
Case "a" To "z"
Case "A" To "Z"
End
So, why we have to contaminate the language with such complexity? All I want to save the programmer's time in writing and reading the code, without making the language harder for beginners and maintainers. We should all hold this goal in our proposals, and not be rush to copy new features from C#. VB as it is today can do every thing without any more features. Any language with variables, arithmetic operations, conditions, loops and Functions can do it all. I have no problem with freezing VB.NET, but the real problem is that MS is keeping it away from all new technologies, which takes it out of the market.
It would be better if we can use TryCast instead of CType in my proposal:
If TryCast(Obj, s As String) AndAlso s.Lenght > 0 then
End If
but TryCast(Obj, s As String)
should return a boolean. It will not break since the part s As String
is not valid today, but it can be a bit confusing! In fact this is how should TryCast invented from beginning to avoid having to use nullable values instead of value types, and have the cast and the check in one step.
What's stopping you implementing it in your own fork?
I didn't master the source yet. It is huge. I am studying Small basic source code now, and will use it as a test lab. It is a very small lang, and I will enjoy completing it and building my VB on top of it, before tampering with Roslyn.
【Thus】 is a good word (idea)
Dim o As Object
If TypeOf o Is String Thus s Andalso s.Length>0 Then
Console.WriteLine(s.Length)
End If
Dim o As Object select o case 1,2 thus A Console.WriteLine(A) case "1","2" thus B Console.WriteLine(B.Length) end select
Why not "As"?
I suggest a new usage of the CType operator to be used in pattern matching like this:
The CType here returns true if obj is not nothing and the cast is possible otherwise false. The second operand must contain a var declaration. Comparing
CType(Obj, s As String)
(2 keys words: CType, As) toTypeOf Obj Is s As String
(3 keys words: TypeOf, Is, As) and:TypeOf Obj Is String Into s
(3 keys words: TypeOf, Is, Into)In my opinion, it is the most readable, meaningfull and shortest syntax possible, without the need of any new keyword.
Note: If we omit the
var As
part, we will have the old CType operation, with a possible invalid cast exception:Note also I suggest to apply the same syntax everywhere needed, such as in0-place out params:
Dim I = Integer.TryParse(x, n As Integer)