With for BUOY

A proposal
In X you often write code like

   if thing isa OtherThing then
        var x as OtherThing = OtherThing( thing )
       ... more code that deals with x since its now an OtherThing
  end if

OR

 select case true
         case thing isa otherType
                .. cast to other type & work with the variable
         case thing isa yetAnotherType
                .. cast to yetAnotherType & work with the variable
    end select

it sure would be nice to get rid of that boiler plate
not sure what other languages might have

Maybe some thing like

   with thing as otherType
            .. all the code that treats thing as an otherType
            AND NO CAST REQUIRED HERE !!!!!!
   end with

or

   with thing as otherType
       ... thing is an otherType
         NO CAST REQUIRED HERE !!!!!!
        
   else with thing as yetAnotherType
       ...  else thing is yetAnotherType
         NO CAST REQUIRED HERE !!!!!!

   else with

   end with

I suppose there’s pros & cons

Thoughts ?

“if thing isa OtherThing” sounds like thing is an Object (or in X terms, IIRC, Variant) boxing something and you have to figure out what it is? And the possibilities aren’t necessarily in the same inheritance tree or at least implementing the same interface?

I don’t recall X having generics and IIRC Buoy will, so … maybe there would, with proper design, be less need for this kind of thing to begin with.

But there are still situations where you can’t escape it. Still, something about having a variable name morph to a new type and back makes me a little bit uneasy in terms of code readability. Also it’s only buying you one less line of code per sub-block, if I’m understanding your scenario correctly.

I suppose the scenario might be something like examining every control on a window
In that case while they are all subclasses of UI Control or something like that you might want to treat each different based on type

for each ctrl as Control in Windows.Controls

select case true 

   case ctrl isa PushButton
        dim pb as PushButton = pushbutton(ctrl)
        ... pb specific code ...

   case ctrl isa CheckBox
        dim cb as CheckBox = CheckBox(ctrl)
        ... cb specific code ...


... etc

in a long case like this ( assuming you handle may controls) while you save one line per block you could save a lot of lines overall

The other case I run into is Dictionaries in X
Or other similar code where what’s stored is some hierarchical arrangement of very generic data

I don’t expect it would save a lot of code though

Ah well this sounds like a use case for the GUI you’re designing. In line of business desktop apps I can’t remember the last time I had to iterate through controls for any purpose that would require me to access anything that’s not on the parent Control class API.

My thought in your shoes would likely be to ask myself how many users care about this and if it’s non-trivial to implement, I’d prioritize other features that will be of interest to the most users, particularly the target product audience and their core use cases.

OTOH I have my own pet ideas and wish lists, so I certainly understand how cool it is to get rid of little constant niggling pain points. They do add up!

So it turns out that this is not terribly hard to do. The compiler just needs to synthesize a shadowed variable inside the block for the original one. Using Norman’s original example, what happens under the hood is this:

 with thing as otherType
     dim thing as otherType = thing
       ... thing is an otherType
         NO CAST REQUIRED HERE !!!!!!
        
 else with thing as yetAnotherType
      dim thing as yetAnotherType = thing
       ...  else thing is yetAnotherType
         NO CAST REQUIRED HERE !!!!!!

 else
     // thing is the original type here

 end with

If you’re just looking for how other languages do things, C# does basically what I think you want like this:

private async void Header_OnDoubleTapped(object? Sender, TappedEventArgs E)
    {
        if (Sender is TextBlock textBlock) 
        {
            // Now textBlock is a TextBlock
            Console.WriteLine(textBlock.Text);
        }

        // Or if you want to get the tag property of a textblock into a variable         
        if (Sender is TextBlock { Tag: string tag })
        {
            // Now tag is a string, but there is no TextBlock variable defined
            Console.Writeline(tag);
        }
    }

Am I understanding?

If you look at build 0.20.0, we introduced a new keyword “treat”

treat thing as otherType
     // thing is othertype in this block
       ... thing is an otherType
         NO CAST REQUIRED HERE !!!!!!
        
 else treat thing as yetAnotherType
      // thing is yetAnotherType in here
       ...  else thing is yetAnotherType
         NO CAST REQUIRED HERE !!!!!!

 else
     // thing is the original type here

 end treat

Ah, you nailed it – that is much clearer semantics than with. (No offense Norm, I couldn’t come up with a better alternative myself, lol)

Just so ya know, “treat” was Norman’s idea.