dotnet / vblang

The home for design of the Visual Basic .NET programming language and runtime library.
290 stars 66 forks source link

Tuple-Like For Each Iteration #557

Open VBAndCs opened 4 years ago

VBAndCs commented 4 years ago

I suggest this syntax to allow foreach loops to operate on more than one collection:

For Each (aItem := 0, bItem := 0) in (A, B)
   C.Add(aItem + bItem)   
Next

Note that I am using the := syntax to set the default value to be used when the loop exceeds the length of one of the collections. If this part is omitted, VB will use the default value of the collection type. The syntax is very close to tuples, so if should be familiar to us.

gilfusion commented 4 years ago

I like the idea, and I think we could do this if we could deconstruct tuples (#278, #346). We can already write extension methods for GetEnumerator(), and For Each will use them.

I just tested with some quick-and-dirty code and got this to work:

Dim leftArray = {1, 2, 3, 4, 5}
Dim rightArray = {1, 4, 9, 16, 25}
For Each item As (left As Integer, right As Integer) In (leftArray, rightArray)
    Console.WriteLine($"{item.left}, {item.right}")
Next

Throw in a decent deconstruction syntax, and we're close to your proposal.

(I may post the code I wrote for GetEnumerator itself once it is cleaned up.)

hartmair commented 4 years ago

This is already possible today (except for the tuple syntax)

Dim A = {1, 2, 3, 4, 5}
Dim B = {1, 4, 9, 16}
Dim C = A.Zip(B, Function(aItem, bItem) aItem + bItem).ToList() ' { 2, 6, 12, 20 }
Dim C = A.ZipDefault(B, Function(aItem, bItem) aItem + bItem).ToList() ' { 2, 6, 12, 20, 5 }

' see https://github.com/dotnet/runtime/blob/master/src/libraries/System.Linq/src/System/Linq/Zip.cs
<Extension>
Public Iterator Function ZipDefault(Of TFirst, TSecond, TResult)(first As IEnumerable(Of TFirst), second As IEnumerable(Of TSecond), resultSelector As Func(Of TFirst, TSecond, TResult)) As IEnumerable(Of TResult)
  Using e1 = first.GetEnumerator(), e2 = second.GetEnumerator()
    Do
      If Not e1.MoveNext() Then
        Do
          Yield resultSelector(Nothing, e2.Current)
        Loop While e2.MoveNext()
        Return
      End If
      If Not e2.MoveNext() Then
        Do
          Yield resultSelector(e1.Current, Nothing)
        Loop While e1.MoveNext()
        Return
      End If
      Yield resultSelector(e1.Current, e2.Current)
    Loop
  End Using
End Function
hartmair commented 4 years ago

When I first read this, I assumed Cartesian product by (A, B). I would prefer an extension method so you must write Zip or Cartesian to indicate what happens.

pricerc commented 4 years ago

1) As always, this is an interesting idea, but what problem is it trying to solve? And what's the desired output? The comments so far indicate that it is a little ambiguous.

When I first read this, I assumed Cartesian product by (A, B). I would prefer an extension method so you must write Zip or Cartesian to indicate what happens.

2) That's what I would have guessed, too. It's easy to forget that BASIC has its roots as a programming language for mathematicians. Many of the symbols used for things like sets have their roots in mathematical theory that is decades (if not centuries) old. So those symbols have specific meanings that should really not be messed with, or you risk confusing people that you don't want to confuse.

So yes, if you're going to use a (A, B) syntax when talking about sets (collections), it should match the syntax and semantics of mathematical set theory.

VBAndCs commented 4 years ago

I am not trying to solve anything, but the question of the language existence itself: VB ot not VB; this is the problem! In fact, VB6 does it all. Even a 14-keyword language like small basic does it all, without even having a Not keyword nor a For each loop! What I am trying to do, is to re-design VB as a modern smart language with compact yet readable syntax. This is a must to do if we want to revive VB again. And these proposals are what I will implement if I forked the lang. I don't care about math nor should VB syntax. It must be clear by now that I am a fan of tuples, and see it can be used to do amazing things. There are many proposals regarding Tuples I posted here and in C# and CoreFx repos, and you can say I am tending to create a tupled-syntax language :). Tuples an tuple-like syntax can make code more compact and efferent. In short: VB compiler must regain its historical reputation for simplicity, smartness and compactness.

Happypig375 commented 4 years ago

But with more syntax, you lose IntelliSense. Also, you make multiple ways to do the same thing (LINQ Zip) and results in more things to learn for beginners, so simplicity is lost.

VBAndCs commented 4 years ago
  1. VB.NET are hard for beginners as is.
  2. Beginners should start with Small Basic not VB.NET. It lakes a form designer with a few set of controls to a VB6 alternative for beginners. We should help in adding this feature to give VB.NET a future.
  3. Zip doesn't belong to VB.NET (there are tons of things to learn in the class library anyway).
  4. Zip is less efficient than my proposed syntax, since it involves lambdas and method calls.
  5. My whole set of proposals aims to make the syntax less size and clearer.
pricerc commented 4 years ago

To be clear: I like the idea of improving set handling in VB.

I work a lot in SQL, so thinking in sets comes naturally to me, and it would be good to have 'native language' support for sets. LINQ helps, but feels a bit "added on" and not as natural as I'd like.

BUT: in no particular order:

I still haven't seen what the desired output from the sample code would be, so I still don't know what it's supposed to do.

  1. VB.NET are hard for beginners as is.

I disagree. In my experience it's much easier to explain VB code to beginners than it is to explain C-family code.

As a high-level structured language that has many concepts in common with Pascal (which was designed for teaching), it makes an excellent education tool.

2. Beginners should start with Small Basic not VB.NET

I disagree. That kind of elitist thinking is a 'C#' attitude that I didn't expect from you. VB should be accessible to all levels of developer. As beginners' skills grow, they can use more of the language, but should not preclude access for new or part-time developers.

5. My whole set of proposals aims to make the syntax less size and clearer.

That's a noble goal, but until you address my first point (what is the output expected), then I can't judge whether your proposal is clearer.

I should also point out that 'less size' and 'clearer' are two separate and not necessarily related goals. IL code is often smaller but seldom clearer.

I don't care about math nor should VB syntax

I don't care a lot about math either, but a lot of VB syntax is already based on math, and it doesn't really make sense to me that we should be inventing new syntax for mathematical constructs, when there is already syntax for them, and that syntax would fit into VB quite easily. So if you're going to introduce set-based logic into VB (which I think has a lot of merit), then it should at least be consistent with the existing constructs in the language.

Also, if you want to get beginners interested, why not give school children who have probably been learning about sets in math classes, a nice syntax they can apply their knowledge to in a programming language? It might make the language more appealing to teachers, who are the people we really want advocating for it.

I refer again to wikipedia. "Collection" and "Array" are just different words for "Set".

So, we already have the 'roster' notation for set initialization, which has come to VB as : Dim A = {1,2,3,4}

What we're missing is a "Set-builder" notation. I think this would be close to 'canonical' while still looking like VB: Dim F = {n As Integer Where 0 <= n And n <= 19}.

Then for operating on collections (sets), there are well-defined operations that need to be catered for: unions, intersections , complements and products.

As described, in the absence of any decoration to the contrary, it is not clear which of these your proposal is performing. Union and Product being the two that have already been mentioned in this thread.

So I'd say you need some kind of additional operator to remove ambiguity.

some ideas that try to resemble the math constructs, but still look like VB:

Dim A = {1,2,3}
Dim B = {3,4,5}
Dim AunionB = {A + B} ' union; A ∪ B  = {1,2,3,4,5}
Dim ABproduct = {A * B} ' product; A × B = {(1,3),(1,4),(1,5),(2,3),(2,4),(2,5),(3,3),(3,4),(3,5)}
Dim AintersectB = {A ^ B} ' intersection; A ∩ B= {3}
Dim AminusB = {A \ B} ' complement; A \ B = {1,2}
Dim BminusA = {B \ A} ' {4, 5}
pricerc commented 4 years ago

P.S. It would also be very helpful to have an example of a common "everyday" problem that programmers encounter that would be made easier by this proposal.

pricerc commented 4 years ago

What I would like from my programming language, and VB 2019 comes close, is that, when writing a program for a customer:

90% of the code is "trivial". 8% of the code is "easy". 1.5% of the code is "not too hard". 0.5% of the code is "hard, but possible".

The 98% will take 10% of the time and should be easily understood by a business consultant.

The 2% will take the other 90% of the time, and is what we get paid for.

The 8% and 1.5% are where language improvements will be most valuable.

The 90% has very little room left for practical improvement, and the last 0.5% is the part that is application-specific and will always be difficult for a general-purpose compiler to generalise.