dotnet / vblang

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

[Proposal] Syntax Expressions Aliases. #528

Open VBAndCs opened 4 years ago

VBAndCs commented 4 years ago

[Proposal] Syntax Expressions I want to shorten long expressions. Sometimes using with or assigning the expression to a variable is not a solution. For example:

If type1.Assembly.Location.Length =  type2.Assembly.Location.Length Then

End If

I suggest to rewrite it as:

using Len = of(Type).Assembly.Location.Length

If type1.Len =  type2.Len Then

End If
  1. I am suggesting Using so we can use it locally. Another version can use Imports at the file level.
  2. No need for end using. The scope is to the end of the block.
  3. The (Of T) defines the type the expression belongs to, so we can have Intellinsense and Vb can check the syntax of the expression.
  4. The original expression should be shown in a tool tip when hovering over Len word.

This is useful if the expression Len appears many times in the scope, and also it can shorten LinQ and lambdas so they become more readable.

gilfusion commented 4 years ago

This isn't too much longer:

Dim Len = Function(x As Type) x.Assembly.Location.Length
If Len(type1) = Len(type2) Then

End If

And maybe local functions and the making local functions and/or lambdas extension methods would fill the gap to what you're looking for.

VBAndCs commented 4 years ago

Lambda is less efficient, since if involves 2 method calls in this example. The expression alias is a direct inline substitution, besides, it gives a bitter intellisence tips. expression aliases can open new possibilities in writing code. I am still exploring.

VBAndCs commented 4 years ago

Not that inline substitution means replacing the len with the expression in build time. This adds zero overhead in loops and LinQ, which is not the case in calling lambdas inside loops and LinQ.

gilfusion commented 4 years ago

True, but I wonder if it wouldn't be easier to get lambda inlining as a compiler optimization than to get a whole new language feature.

VBAndCs commented 4 years ago

lambdas can be passed to other methods as a param. You can't inline this.

gilfusion commented 4 years ago

Of course, I wasn't expecting lambdas to always be able to be inlined, but, for cases like yours, it might be possible (and, for all I know, it might already be happening at JIT-time).

I'm mostly recalling how a more efficient conversion to Integer was dropped in favor of optimizing the CInt(Fix(...)) pattern, and I wonder if something like that might be an option here.

CyrusNajmabadi commented 4 years ago

wouldn't it make more sense to just be a local function lke this:

function len(x as type) x.Assembly.Location.Length

?

That woudl also match c# local functions.

CyrusNajmabadi commented 4 years ago

True, but I wonder if it wouldn't be easier to get lambda inlining as a compiler optimization than to get a whole new language feature.

Yes. It would be easier for a compiler optimization versus any language features. See the current plan on the VB language here: https://devblogs.microsoft.com/vbteam/visual-basic-support-planned-for-net-5-0/

VBAndCs commented 4 years ago

@CyrusNajmabadi I don't see any benefit of local functions over lambdas. VB6 had GoSub, and we were glad to get rid of in VB.NET, as it makes a macaroni code. My motivation here is the very long expressions I see in today's code, which makes it difficult to read the code, even when separated into multilines (which is unpleasant in VB sense we can't start a line with a dot, se we heave it at the end of the prev line!) So, to make the code easier to read and write, we need to use aliases that don't affect the runtime anyway, but makes the code nicer in the editor. This is why I suggested generic aliases to refer to complex generic types, and here suggesting expression aliases to refer to long dot chain of members. Maybe I think of more aliases tomorrow. I will keep hoping for gathering repeated long code spans together. If we don't do that, we will lose beginners after one glimpse to such complicated hard to comprehend codes. VB.NET specially, has to maintain its readability as an English like text easy to understood by non programmers. This is why I once said: Not for beginners. Not for professionals: VB.NET is in indeterminate state!

VBAndCs commented 4 years ago

@CyrusNajmabadi

See the current plan on the VB language here:

I am aware of this plan. In fact I am raining proposals here since this plan :). We share our vision here for the next VB generation, regardless its creator: MS, another company, a community fork, or even myself tampering with a self edition :)

AdamSpeight2008 commented 4 years ago

Regarding local functions https://github.com/dotnet/vblang/issues/221#issuecomment-350854031

gilfusion commented 4 years ago

@VBAndCs

My motivation here is the very long expressions I see in today's code, which makes it difficult to read the code, even when separated into multilines (which is unpleasant in VB sense we can't start a line with a dot, se we heave it at the end of the prev line!)

I think this is one of the reasons that subroutines and functions were invented in the first place, though, them and macros in C/C++. Your proposal looks a little more like a macro with some type information included and dot notation instead of function notation, which is fine, but, again, it doesn't appear to do anything that a function with sufficient inlining support can't do.

gilfusion commented 4 years ago

Also, @VBAndCs, looking back, we have both written aliasing suggestions before (#168 and #442). How do you think this compares to those?

pricerc commented 4 years ago

... and macros in C/C++. Your proposal looks a little more like a macro with some type information included and dot notation instead of function notation, which is fine, but, again, it doesn't appear to do anything that a function with sufficient inlining support can't do.

I wasn't sure what was bothering me about this proposal until this comment.

This does look like a C/C++ macro.

They can be incredibly powerful. But that power can be used for good or bad. And that's what can make them dangerous. If you ever had to maintain some old C/C++ code, you will know that macros can make it incredibly challenging to figure out what code is doing.

Now I do recognise that you could do some quite cool things with it. I'm just not sure that "being able to do cool things" is a good justification for a language feature.

Also, for the use case described in the proposal, there is no reason why one of the compilers (VB or JIT) can't inline the lambda/local function if it is a simple de-reference to an instance method or property.

As an aside, the alias 'Len' in the proposal's example is (I think) a poor choice of alias. If I was looking at a bit of code for the first time that had

If type1.Len =  type2.Len Then

End If

I would assume that Len refers to the size of type1 and type2, not the length of the filename of the assembly their types are located in.

Getting back to the topic; I'd rather see private extension methods being available within a class. They could achieve a similar result and have a wider use-case.

e.g.

Class Foo

  <Extension()>
  Private Function Len(this As Type) As Integer
    Return this.Assembly.Location.Length
  End Function
...
  Private Sub Bar
...
    If type1.Len =  type2.Len Then

    End If
  End Sub
...
End Class

I still don't like the name Len

VBAndCs commented 4 years ago

So you prefer to write 4 lines instead of one? In a method that doesn't really do anything except call a chain of members? You seem insisting on using a wrong tool for the job. This is just an alias, no less, no more. And pleas get rid of the busy team thinking methodology, which prefer zero effort on the expense of keeping user uncomfortable. There is no team any more. We should now thing as designers of a perfect language, that we will carve by our hands. So, let your minds out of the box. The galaxy is the limit.

CyrusNajmabadi commented 4 years ago

So you prefer to write 4 lines instead of one?

Less lines does not make things better.

There is no team any more.

Yes there is. :)

This is just an alias, no less, no more.

But what is an alias? Why do we need it?

pricerc commented 4 years ago

So you prefer to write 4 lines instead of one? In a method that doesn't really do anything except call a chain of members?

Actually, if I was only going to use the alias twice inside one method, then I would prefer no alias:

If type1.Assembly.Location.Length =  type2.Assembly.Location.Length Then

End If

I would know exactly what I was looking at.

If it is going to be useful more than once, or in more than just the specific case inside that specific method, then yes, I'd rather have 4 lines that I can then use many times in many places than one line I can only use twice in one place.

And pleas get rid of the busy team thinking methodology

With respect, I'd suggest you need to think less like a solo developer and a bit more outside your own box. Two things you don't consider with that comment:

1) today, I code only for myself. But when my workload increases, then I need to hire a developer to help me. If I've written bad, hard to maintain code, then that developer is going to cost me more because he takes longer to understand what my code does.

2) I wrote some code for a customer 10 years ago. Then last year, they asked for some changes. It may have been me that wrote the original code, but it might as well have been someone else, because I've forgotten about the code years ago, and my coding style has changed since then.

I always code assuming that someone else might need to maintain my code, and assuming that I will need to maintain it in years to come. If you focus on just the short-term saving of a few keystrokes, then you increase the later maintenance burden.

VBAndCs commented 4 years ago

@pricerc

  1. Why type1.len is readable and maintainable when len is an extension method than when it is an alias?
  2. Why Len(type1) is readable and maintainable than type1.len?
  3. Why type1.Assembly.Location.Length is readable and maintainable than type1.len while a mouse hover over the last will show exactly type1.Assembly.Location.Length?
  4. Why do you think a file with 1000 lines with average 100 chars per line, is readable and maintainable than being rewritten with 250 lines with average 30 chars per line?

Sorry, I can't understand your argument. I faced these issues in practice while I was translating some Roslyn and ASP.NET Core source code from C# to VB.NET, where I got the longest , widest, and most complicated VB.NET code I ever seen. It was hard to read and comprehend. So, what is the benefit of keeping long reputable fragments of code, that is not a function in nature? And what why should I create functions for them to make the file longer? And why should you use every feature of the lang? I myself don't use With blocks but others do. If you don't like aliases others may prefer them better. I see the best tools for this issue.

pricerc commented 4 years ago

@pricerc

  1. Why type1.len is readable and maintainable when len is an extension method than when it is an alias?
  2. Why Len(type1) is readable and maintainable than type1.len?

I didn't say or suggest either of these things.

I did suggest that a private extension method could achieve a similar result and have more general purpose use. But only if it was going to be used more than once or twice.

  1. Why type1.Assembly.Location.Length is readable and maintainable than type1.len while a mouse hover over the last will show exactly type1.Assembly.Location.Length?

Because I'm not always holding a mouse when I'm looking at code. I still sometimes print out code onto paper(!) to review it with particularly complicated code. Intellisense doesn't work there. And sometimes I'm looking at code in GitHub or Azure DevOps, and there is no intellisense there either.

  1. Why do you think a file with 1000 lines with average 100 chars per line, is readable and maintainable than being rewritten with 250 lines with average 30 chars per line?

It would completely depend on the the code. As mentioned by someone else, less code doesn't make it better, and doesn't make it easier to understand.

Some of the smallest programs in the world are the most difficult to read. Have you ever looked at the entries for the International Obfuscated C Code Contest ( https://www.ioccc.org/years.html )? There are one-line programs that do amazing things, but can take hours to decipher.

Sorry, I can't understand your argument. I faced these issues in practice while I was translating some Roslyn and ASP.NET Core source code from C# to VB.NET, where I got the longest , widest, and most complicated VB.NET code I ever seen. It was hard to read and comprehend.

Without looking at the code to which you refer, I am reluctant to comment. But having used various C#-VB converter tools, and having converted a lot of code by hand, I know that a lot of C# is not coded the way I would consider VB-compatible, which I can see leading to the kind of thing you're referring to.

For some reason, many C# programmers seem to believe that less code is better than readable code. I honestly think some of them believe that the fewer characters in their programs, the faster it runs.

I think in the end, this translates to translators having trouble with producing good VB code.

I myself don't use With blocks but others do.

I also don't use with blocks, except in initializers. Where I think they should have an 'End With' instead of { and }. But that's another topic.

I see the best tools for this issue.

Ahh, but the point of this forum is to debate what constitutes the 'best tools'. What you think would be a good enhancement to the language may not be seen that way by most people.

In this case, you think local property/method aliases are a good idea.

I'm not so sure. I don't think they're a bad idea, but I do think they come with risks (similar to the risks they share with macros in C and other languages).

VBAndCs commented 4 years ago

Because I'm not always holding a mouse when I'm looking at code. I still sometimes print out code onto paper(!) to review it with particularly complicated code. Intellisense doesn't work there. And sometimes I'm looking at code in GitHub or Azure DevOps, and there is no intellisense there either.

Then You will face the same exact issues with every sub call or extension method, as you will look it up in the paper or Github. This can't be solved with printed functions, but it can easily solved with aliases, as we can add an option to substitute aliases when printing. And Github should add links to methods and types. I feel that every time I read a code on it. So, your argument still out of the case. It is not particularly about aliases.

VBAndCs commented 4 years ago

It would completely depend on the code. As mentioned by someone else, less code doesn't make it better, and doesn't make it easier to understand.

This is a personal preference. In fact we are standing here on the grave of a dying language, which is always accused of being verbose, and this is why many of the new developers went to C#. I want to maintain VB readability and make it less verbose in same time. This is how new generations prefer things: Quick, short and powerful. Otherwise you will not find anyone to read your code anymore.

CyrusNajmabadi commented 4 years ago

And what why should I create functions for them to make the file longer?

You have the argument reversed. It's not up to others to justify why they're ok with the status quo. You need to provide a suitable argument as to why that needs to change.

For me, you haven't shown enough value with your proposal for it to be worthwhile. it seems like something we already have suitable solutions for that are well understood by everyone.

CyrusNajmabadi commented 4 years ago

. I want to maintain VB readability and make it less verbose in same time.

This doesn't seem to help. It actually just seems as verbose as a lambda, while not providing any additional value. :-/