Page 10 of 52 FirstFirst ... 7891011121320 ... LastLast
Results 361 to 400 of 2075

Thread: TwinBasic

  1. #361
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,671

    Re: TwinBasic

    Quote Originally Posted by WaynePhillipsEA View Post
    I would say mostly optional/obsolete. There will be edge cases, e.g. if a procedure is named the same as a syntax keyword, then the call prefix can still help to disambiguate between the keyword and the procedure name. But in the majority of cases it should be considered obsolete/optional.
    OK, good .

    About brackets (and anything that don't have a function), I prefer not to be required, if the reason is just "because it is required in other languages".
    Better other languages learn from BASIC and not BASIC to be polluted with nosense requirements from other languages.
    But to optionally accept the syntax (the parentheses without Call) if there is no harm is welcomed IMO.
    So people coming from other languages can keep their habits.

  2. #362
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: TwinBasic

    I have no problem with brackets being optional. I just want the compiler to not complain when I use them.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  3. #363
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: TwinBasic

    Quote Originally Posted by WaynePhillipsEA View Post
    You could put the IsObject check into the SetVarValue call to switch between the two types of assignments, and that should satisfy the compiler and be correct.
    Ok I just tested this and it doesn't work. Whenever Set is used to perform an assignment to a ByRef argument, the value doesn't propagate back to the variable that was passed through that ByRef argument. Guess it's back to the drawing board.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  4. #364
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: TwinBasic

    Ok I decided to revisit all the fancy point tricks I rejected yesterday and combine it with this idea of using ByRef parameters and came up with this:-
    Code:
        Private Sub SetVarValue(Of T)(ByRef varToSet As T, ByVal value As T)
            If IsObject(value) Then
                '*********************************
                'Set varToSet = value
                '---------------------------------
                'The above Set statement is what the code below ultimately does.
                'however the compiler refuses to compile it because it sees
                'that type T can also be a String or a Long because this function
                'is also used with those types. It assumes that I might be using Set
                'to perform assignments between these non-object types and refuses to
                'compile as a result. We get around the compiler by using pointers
                '*********************************
    
                Dim obj As object
                Dim obj2 As object
                dim zero as long=0
                
                'Create an illegal object reference
                memcpy(varptr(obj),varptr(value),4)
                
                'AddRef    
                Set obj2 = obj
                
                'Assign the object to ByRef parameter
                memcpy(varptr(vartoset),varptr(value),4)
                
                'Prevent refrence count of object from being decremented when the object
                'variable goes out of scope
                memcpy(varptr(obj),varptr(zero),4)
                memcpy(varptr(obj2),varptr(zero),4)
            Else
                varToSet = value
            End If
        End Sub
    This method adds the extra burden of needing an API call but at least it's a Win32 API call so no worries about it not being on a Windows system. It's also why I didn't use the function that wqweto showed me yesterday to call AddRef. I do not want to depend on the VB6 runtime being installed for this to work. Also this solution doesn't use Variants and it doesn't require me to refactor generic classes. I think I'm running with this solution. I doubt I will come up with a better way. I have exhausted all options at this point.

    Here is the full test code:-
    Code:
    Module MainModule
        
        public declare sub MemCpy Lib "kernel32" Alias "RtlMoveMemory"(byval dest as LongPtr,byval src as LongPtr,byval count as Long)
        
        ' This project type is set to 'Standard EXE' in the Settings file, so you need a Main() subroutine to run when the EXE is started.
        Public Sub Main()
            
            Dim objVal As TestClass = New TestClass
            Dim strVal As String = "BOO!"
            Dim lngVal As Long = 29
            
            Dim objVar As TestClass
            Dim strVar As String
            Dim lngVar As Long
            
            SetVarValue(objVar, objVal)
            SetVarValue(strVar, strVal)
            SetVarValue(lngVar, lngVal)
            
            Debug.Print objVar.Value
            Debug.Print strVar
            Debug.Print lngVar
            
        
        End Sub
    	
        Private Sub SetVarValue(Of T)(ByRef varToSet As T, ByVal value As T)
            If IsObject(value) Then
                '*********************************
                'Set varToSet = value
                '---------------------------------
                'The above Set statement is what the code below ultimately does.
                'however the compiler refuses to compile it because it sees
                'that type T can also be a String or a Long because this function
                'is also used with those types. It assumes that I might be using Set
                'to perform assignments between these non-object types and refuses to
                'compile as a result. We get around the compiler by using pointers
                '*********************************
    
                Dim obj As object
                Dim obj2 As object
                dim zero as long=0
                
                'Create an illegal object reference
                memcpy(varptr(obj),varptr(value),4)
                
                'AddRef    
                Set obj2 = obj
                
                'Assign the object to ByRef parameter
                memcpy(varptr(vartoset),varptr(value),4)
                
                'Prevent refrence count of object from being decremented when the object
                'variable goes out of scope
                memcpy(varptr(obj),varptr(zero),4)
                memcpy(varptr(obj2),varptr(zero),4)
            Else
                varToSet = value
            End If
        End Sub
        
    End Module
    
    Private Class TestClass
        
        Public Sub new()
            
        End Sub
        
        Public Property Get Value() As String
            Return "Class Property Value"
        End Property
        
    End Class
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  5. #365
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: TwinBasic

    @WaynePhillipsEA

    One more thing. About what I mentioned earlier about ByRef not working with Set. I'm not sure if there is a bug here but here is some code reproducing the behavior:-
    Code:
    Module SecondMain
    	
    	Public Sub Main()
    		
    		Dim tc1 As TestClass = New TestClass
    		
    		Dim tc2 As TestClass
    		
    		Assign(tc2, tc1)
    		
    		If tc2 Is Nothing Then
    			'This program compiles with no problems but at run time, the assignment
    			'will fail by simply not propagating the value of 'dest' inside the Assign sub
    			'to the 'tc2' variable that was passed in
    			Debug.Print "Failed to assign"
    		Else
    			
    			'The only way it succeeds is if either 'tc1' is also a Variant or if
    			'the 'dest' parameter in Assign is of type TestClass.
    			Debug.Print "Success"
    		End If
    		
    		
    	End Sub
    
    	Public Sub Assign(ByRef dest As Variant, ByVal obj As TestClass)
    		Set dest = obj
    	End Sub
    		
    	' add your procedures here
    End Module
    This is a little above my pay grade so I can't even begin to understand what is really happening here. Maybe it's something, maybe it's nothing either way I found it interesting and thought you may want to take a look at it.

    I haven't tested this in VB6 btw so I don't know if this is expected behavior.

    EDIT:

    Just tested it in VB6 and the value propagates so this is definitely a bug or at the very least an oversight since it's violates the aim of backward compatibility with VB6.
    Last edited by Niya; Aug 18th, 2021 at 08:51 PM.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  6. #366
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,844

    Re: TwinBasic

    Quote Originally Posted by WaynePhillipsEA View Post
    Upon reflection, I think you're spot on, and I've rejected other proposed features for those exact reasons. I was purely trying to think of alternatives we hadn't considered, but you are right that this one is not BASIC-esque.
    Indeed, it is not appropriate to use ":=" instead of the Set keyword.

    Some people say that ":=" is not "BASICish" syntax, but in fact, ":=" is an existing syntax in VB6, which is used in function parameter calls.
    Last edited by SearchingDataOnly; Aug 18th, 2021 at 09:28 PM.

  7. #367
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,844

    Re: TwinBasic

    For the sentence "For Each P As cPerson In Persons", my thinking is this:

    (1) In "For Each P As cPerson In Persons", P is "Function-Scoping"

    (2) In "For Each (P As cPerson) In Persons", P is "For Block-Scoping"

    --- Or ---

    Provide "#Region ... #End Region" syntax. If "For Each P As cPerson In Persons" is within the Region, then P is "Region-Scoping", otherwise, P is "Function-Scoping"

    Code:
    #Region
    For Each P As cPerson In Persons
    
    Next
    #End Region
    Last edited by SearchingDataOnly; Aug 18th, 2021 at 09:27 PM.

  8. #368
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: TwinBasic

    Quote Originally Posted by SearchingDataOnly View Post
    (1) In "For Each P As cPerson In Persons", P is "Function-Scoping"

    (2) In "For Each (P As cPerson) In Persons", P is "For Block-Scoping"
    I like that actually...
    The brackets in (2) kind of underline the "isolated state" of the iterator-variable from the surrounding code.

    Olaf

  9. #369
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: TwinBasic

    Quote Originally Posted by SearchingDataOnly View Post
    For the sentence "For Each P As cPerson In Persons", my thinking is this:

    (1) In "For Each P As cPerson In Persons", P is "Function-Scoping"

    (2) In "For Each (P As cPerson) In Persons", P is "For Block-Scoping"

    --- Or ---

    Provide "#Region ... #End Region" syntax. If "For Each P As cPerson In Persons" is within the Region, then P is "Region-Scoping", otherwise, P is "Function-Scoping"

    Code:
    #Region
    For Each P As cPerson In Persons
    
    Next
    #End Region
    I'm not a fan of that approach. Like I said before, I'm big fan of consistency in programming languages. It's not consistent because scoping in BASIC languages is usually denoted by an opening keyword and an End [Keyword] statement. For example, End Sub, End Function, End With, End If. The only exceptions are loops, For...Next and Do...Loop. Brackets are used for array indexing, and grouping expressions and using it for block scoping just doesn't fit. A more consistent approach would be to simply add another compiler directive alongside Option Explicit. Maybe we can call it Option Block On. This would be a very VB way of doing things.

    Another more VB way of doing it would be using Function modifiers. This would be somewhat consistent as VB as plenty of those. Friend, Private, Public. However, it's a little less consistent I'm comfortable with since function modifiers typically tell you something about the function's relationship to the everything outside of the function. There is no modifier who's effects are confined only to what's inside the function.

    Another very VB way could be to add another declarative keyword in the family of Dim. It's consistent because we already have Dim, Private and Public for declaring variables and these are directly related to variable scoping. One extra would be very consistent with VB's design. Perhaps we could call it DimBlock and when used to declare a variable inside a block it would be block scoped.

    These are just a few ideas off the top of my head. I don't know that much about language design so don't think of any of this as a right or wrong thing. These are just my opinions.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  10. #370
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,671

    Re: TwinBasic

    Quote Originally Posted by SearchingDataOnly View Post
    Some people say that ":=" is not "BASICish" syntax, but in fact, ":=" is an existing syntax in VB6, which is used in function parameter calls.
    Yes, that syntax was already used by MS for that purpose. It does not mean that it was a good idea, IMO.
    Perhaps being so strange to BASIC is a reason why that feature is hardly used.

  11. #371
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: TwinBasic

    Oh I just remembered, TwinBASIC also has attributes which can act as compiler directives only far more powerful. Attributes could be introduced for block scoping.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  12. #372
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,892

    Re: TwinBasic

    What about:

    Function Scope:
    Code:
    For Each P As cPerson in Persons 
       If True Then Exit For
    Next P
    
    MsgBox P.Name ' Shows Name of First Enumerated cPerson in Persons
    Block Scope:
    Code:
    With Each P As cPerson in Persons 
       If True Then Exit With
    Next With
    
    MsgBox P.Name ' Error - Variable Not Defined OR Object/With Variable Not Set?
    OR perhaps:

    Function Scope:
    Code:
    Dim P As cPerson   ' Dimmed outside For Block
    
    For Each P in Persons 
       If True Then Exit For
    Next P
    Block Scope:
    Code:
    For Each P As cPerson in Persons ' The "As cPerson" Dims the var inside the block, outting it in block scope
       If True Then Exit For
    Next P

  13. #373
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: TwinBasic

    Oh yea, before I forget again. Wanted to mention this a long time ago. A proper sizeof operator would be nice. It's a tad bit annoying having to declare a variable just to measure the size of a structure:-
    Code:
    	Dim b As MyStruct
    	Dim sz As Long = LenB(b)
    Would be lovely if we could just do this:-
    Code:
    Dim sz As Long = sizeof(MyStruct)
    Like we could in C/C++. Even VB.Net can do it through Type objects. This comes up a lot when you need to allocate memory for a structure but don't actually intend to use the structure at that moment. You just want to know it's size.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  14. #374
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: TwinBasic

    Quote Originally Posted by jpbro View Post
    What about:

    Function Scope:
    Code:
    For Each P As cPerson in Persons 
       If True Then Exit For
    Next P
    
    MsgBox P.Name ' Shows Name of First Enumerated cPerson in Persons
    Block Scope:
    Code:
    With Each P As cPerson in Persons 
       If True Then Exit With
    Next With
    
    MsgBox P.Name ' Error - Variable Not Defined OR Object/With Variable Not Set?
    OR perhaps:

    Function Scope:
    Code:
    Dim P As cPerson   ' Dimmed outside For Block
    
    For Each P in Persons 
       If True Then Exit For
    Next P
    Block Scope:
    Code:
    For Each P As cPerson in Persons ' The "As cPerson" Dims the var inside the block, outting it in block scope
       If True Then Exit For
    Next P
    Hmmm.....the problem I'm seeing that it only considers For...Each blocks. What about If....Then, Do...Loop and With...End With blocks?
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  15. #375
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,892

    Re: TwinBasic

    One more idea:

    Function Scope:
    Code:
    For Each P in Persons 
    Next
    Block Scope:
    Code:
    For Each Private P in Persons ' Private keyword dims variable with block scope. Maybe "Local" would be better?
    Next

  16. #376
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: TwinBasic

    Dim P instead of Private might a little better. Private affects scoping at the project level. It would be a bit confusing using it for block level scoping.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  17. #377
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,671

    Re: TwinBasic

    My opinion is not to introduce many variants to do more or less the same thing.

    Code:
    For Each P As Person In Persons
    seems something good to introduce, but not with several similar possibilities.

    The only discussion IMO would be if the scope should be of procedure level or block level.
    But there isn't such thing as block level in VB (and tB) right now, so the discussion of introducing block level variable scope should be a separate and previous discussion I think.

  18. #378
    Lively Member IndicSoftware's Avatar
    Join Date
    Aug 2017
    Location
    India
    Posts
    86

    Re: TwinBasic

    Quote Originally Posted by WaynePhillipsEA View Post
    How about a slightly different operator to control that behaviour instead of LetSet/Assign?

    Code:
    MyObject1 := MyObject2
    This is a perfect solution. I like it!
    --
    From,
    Indic Software


    Revolutionary Visual Programming IDE.

  19. #379
    Hyperactive Member
    Join Date
    Dec 2020
    Posts
    314

    Re: TwinBasic

    @Niya, I've just released v0.10.4617, the Set-assignment on byref-Variants semantics are now fixed. So this should work for you:

    Code:
    Private Sub SetVarValue(Of T)(ByRef varToSet As Variant, ByVal value As T)
        If IsObject(value) Then
            Set varToSet = value
        Else
            varToSet = value
        End If
    End Sub

  20. #380
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,844

    Re: TwinBasic

    Quote Originally Posted by Niya View Post
    I'm not a fan of that approach. Like I said before, I'm big fan of consistency in programming languages. It's not consistent because scoping in BASIC languages is usually denoted by an opening keyword and an End [Keyword] statement. For example, End Sub, End Function, End With, End If. The only exceptions are loops, For...Next and Do...Loop. Brackets are used for array indexing, and grouping expressions and using it for block scoping just doesn't fit. A more consistent approach would be to simply add another compiler directive alongside Option Explicit. Maybe we can call it Option Block On. This would be a very VB way of doing things.

    Another more VB way of doing it would be using Function modifiers. This would be somewhat consistent as VB as plenty of those. Friend, Private, Public. However, it's a little less consistent I'm comfortable with since function modifiers typically tell you something about the function's relationship to the everything outside of the function. There is no modifier who's effects are confined only to what's inside the function.

    Another very VB way could be to add another declarative keyword in the family of Dim. It's consistent because we already have Dim, Private and Public for declaring variables and these are directly related to variable scoping. One extra would be very consistent with VB's design. Perhaps we could call it DimBlock and when used to declare a variable inside a block it would be block scoped.

    These are just a few ideas off the top of my head. I don't know that much about language design so don't think of any of this as a right or wrong thing. These are just my opinions.
    Your opinion is very valuable. As long as no emotional language is used, any discussion of technology is valuable. Looking at problems from different angles, there will be different opinions, which has nothing to do with right or wrong.

    I'm a strong supporter of "BASICish" syntax. In my opinion, there are two forms of "BASICish", one is "BASICish" from the perspective of syntax, and the other is "BASICish" from the perspective of design patterns. E.g:

    You posted an example of "generics", which is a very good example. But in my opinion, "generics" is not a "BASICish" design pattern, and the example in Olaf's post#342 is a more "BASICish" design pattern than "generics".

    In order not to hijack this thread, if I have time, I'll create another thread to discuss "what is really BASICish".
    Last edited by SearchingDataOnly; Aug 19th, 2021 at 05:29 AM.

  21. #381
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,844

    Re: TwinBasic

    Quote Originally Posted by jpbro View Post
    One more idea:

    Function Scope:
    Code:
    For Each P in Persons 
    Next
    Block Scope:
    Code:
    For Each Private P in Persons ' Private keyword dims variable with block scope. Maybe "Local" would be better?
    Next
    I prefer Local. However, in order to reduce ambiguity, I think we should cancel "block-scoping variables"

  22. #382
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,844

    Re: TwinBasic

    Quote Originally Posted by Schmidt View Post
    Quote Originally Posted by SearchingDataOnly View Post
    For the sentence "For Each P As cPerson In Persons", my thinking is this:

    (1) In "For Each P As cPerson In Persons", P is "Function-Scoping"

    (2) In "For Each (P As cPerson) In Persons", P is "For Block-Scoping"
    I like that actually...
    The brackets in (2) kind of underline the "isolated state" of the iterator-variable from the surrounding code.

    Olaf
    In order to reduce ambiguity, I think we should cancel "block-scoping variables". In other words, we should always just use the following traditional syntax:

    Code:
    Dim P As cPerson
    For Each P in Persons 
       
    Next P
    If twinBasic decides to support "block-scoping variables", then the best of both worlds should be: adopt (2), prohibit (1).
    Or, change (2) to jpbro's method:
    Code:
    For Each Local P As cPerson in Persons 
    
    Next
    Last edited by SearchingDataOnly; Aug 19th, 2021 at 05:34 AM.

  23. #383
    Frenzied Member
    Join Date
    Aug 2020
    Posts
    1,844

    Re: TwinBasic

    Quote Originally Posted by WaynePhillipsEA View Post
    Quote Originally Posted by SearchingDataOnly View Post
    @WaynePhillipsEA,

    I'd like to know how twinBasic implements JavaScript-like inline-functions(Callback), for example:

    Code:
    //Basic forEach
    function forEach(array, action) {
        for (var i = 0; i < array.length; i++) {
    	action(array[i])
        }
    }
    
    // Test forEach
    forEach(["Pear", "Apple"], function(name) {
        console.log(name);
    });
    
    // Implement reduce
    function reduce(combine, base, array) {
        forEach(array, function(element) {
    	base = combine(base, element);
        });
        return base;
    }
    Another famous example is C++ qsort.
    Yes, Delegate-style function pointers are planned: https://github.com/WaynePhillipsEA/twinbasic/issues/79
    I just browsed that link and the discussion inside is very valuable.

    My purpose is to find a more "BASICish" design pattern to implement function-pointers or Callbacks, but I haven't found the best solution yet.

  24. #384
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: TwinBasic

    Quote Originally Posted by SearchingDataOnly View Post
    For Each Local P As cPerson in Persons

    Next
    I like this as well (to distinguish between "function-level" and "local For-Block"-scope).

    As for "other local block-scopes" (as If-Blocks, Do while, etc.)...
    here the "localness" could easily be ensured via "normal Dim Statements within a given Block"
    (if one wants to go there at all, with "full block-scoping").

    For Each is a different animal IMO (as far as "code-blocks" are concerned),
    because any "Opener-Line of a For-Block" always requires the specification of an Iterator-Variable.

    And with Option Explicit in place (which goes without saying...), there's therefore always
    the necessity of "extra-Dimming-efforts" in a separate Line...

    And that's what we could avoid, when such an "implicit Dimensioning" would be possible in the future
    (in the Opener-Line of the For-Block itself).

    Don't know, how "other brains work" in this regard -
    but the current "extra-Dim requirement of a For-Iterator-Variable" throws me off quite often.

    Especially when I'm "in the flow"... these iterator-critters are "somehow implicit in thinking" (secondary to the real problem) -
    and a new syntax like the above would "get rid of that secondary problem" in the very same line of code, that addresses "the real task"...
    <shrug>

    Olaf
    Last edited by Schmidt; Aug 19th, 2021 at 07:38 AM.

  25. #385
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    3,560

    Re: TwinBasic

    Code:
    For Each P As cPerson in Persons ' The "As cPerson" Dims the var inside the block, outting it in block scope
       If True Then Exit For
    Next P
    This looks good to me and I like the idea of block scoping and I am sure it could be shoe-horned into other loop structures with some fiddling. In truth though, I just want TwinBasic to do what VB6 does at the moment, archaic, insane, stupid or otherwise, just so we can move on and get TwinBasic functioning. If this gets us past a sticking point let Wayne choose one.

    An alternative would be to set up a committee like the ECMA group and determine BASICs future direction. I'll nominate Niya and Olaf on that committee and we'll see how it goes.
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  26. #386
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,892

    Re: TwinBasic

    Block-level variables can be useful in some circumstances, but if we can choose only one then function-level is more useful.

    I agree with Niya that the "Dim" keyword is probably the best choice if we can have block-level scoped variables, but I'm also fine with "Local". I definitely prefer English keyword approaches to the non-English syntax (parentheses or :=).

    I can see potential backwards compatibility problems with Olaf's idea to treat variables dimmed in If/Do blocks as local scope. Some of us haven't been perfectly disciplined in this regard and may have Dims inside blocks that we're actually relying on to be function-level scoped (looks around nervously). So perhaps an "Option Local Scope" would be useful to turn this feature on? Or maybe a new "Local" keyword will dim a variable with block-level scope. So:

    Code:
    Sub Test
       Dim MyVar As Long
    
       MyVar = 10
    
       If MyVar > 0 Then
          Local MyVar As Long
    
          MyVar = MyVar + 1
    
          Debug.Print MyVar
       End If
       
       Debug.Print MyVar
    Will output:

    Code:
    1
    10
    I do subscribe to Olaf's idea of being able to dimension new vars within the For Each construct though, so I'm fine with any of the constructs that don't require and extra "Dim Foo As Bar" line.

    Another thought since we are on the topic. I'm not sure if this is possible, but it would be great For Each with a strongly typed variable would skip Collection members of other types when looping. Consider the following code

    Code:
    Option Explicit
    
    Sub Test()
       Dim c As New Collection
       
       c.Add New Class1
       c.Add New Class1
       c.Add New Class2 ' Different Class
       c.Add New Class1
       c.Add New Class1
      
       For Each c1 As Class1 In c   ' Only enumerate the Class1 members of the Collection.
          Debug.Print c1.Id
       Next c1
    End Sub
    Right now this will raise a Type Mismatch Error in VB6 when the loop hits Class2. It would be great if it just skipped the non-Class1 members of the collection, basically performing this code on your behalf:

    Code:
    Option Explicit
    
    Sub Test()
       Dim c As New Collection
       Dim c1 As Class1
    
       c.Add New Class1
       c.Add New Class1
       c.Add New Class2 ' Different Class
       c.Add New Class1
       c.Add New Class1
      
       For Each cx As Object In c   ' Enumerate all members of the Collection.
          If TypeOf(cx) Is Class1 Then
             ' We found a Class1 member, so let's use it
             Set c1 = cx
    
             Debug.Print c1.Id
          End If
       Next c1
    End Sub

  27. #387
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: TwinBasic

    Quote Originally Posted by jpbro View Post
    Or maybe a new "Local" keyword will dim a variable with block-level scope. So:

    Code:
    Sub Test
       Dim MyVar As Long
    
       MyVar = 10
    
       If MyVar > 0 Then
          Local MyVar As Long
    
          MyVar = MyVar + 1
    
          Debug.Print MyVar
       End If
       
       Debug.Print MyVar
    Will output:

    Code:
    1
    10
    I'd subscribe to that idea of "Local instead of Dim" for block-scope vars.
    It'd help, to avoid a new "Option Local Scope" - and the special case of: For Each Local P As cPerson In Persons
    would make for a "consistent read and meaning" over all.


    Quote Originally Posted by jpbro View Post
    Another thought since we are on the topic. I'm not sure if this is possible, but it would be great For Each with a strongly typed variable would skip Collection members of other types when looping.

    Code:
    Option Explicit
    
    Sub Test()
       Dim c As New Collection
       
       c.Add New Class1
       c.Add New Class1
       c.Add New Class2 ' Different Class
       c.Add New Class1
       c.Add New Class1
      
       For Each c1 As Class1 In c   ' Only enumerate the Class1 members of the Collection.
          Debug.Print c1.Id
       Next c1
    End Sub
    My own usage of such "mixed bag-contents" is pretty rare.
    When it comes to (plain-data-holding) List- and Container-Objects - these usually have "only one type of Value" (or Key).

    Sure, there's of course the Controls (or Widgets) Collections - but that's GUI-hierarchy-stuff
    (where you have no real choice, stuffing different Class-Types into them).

    IMO such filtering should better be handled in the Enumerator (IEnumVariant)- returning "right most part" of a For Each Loop.
    E.g. I could imagine, to enhance the cWidgets-Class of the RC6-GUI about an additional Enumerator-returning method like:

    Code:
    For Each B As cwButton In MyForm.WidgetsByType("cwButton")
    
    Next
    Instead of the current:

    Code:
    Dim oW As Object, B As cwButton
    For Each oW In MyForm.Widgets 
      If TypeOf oW Is cwButton Then
        Set B = oW
        ...
      End If
    Next
    Olaf

  28. #388
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    3,560

    Re: TwinBasic

    Quote Originally Posted by jpbro View Post
    Some of us haven't been perfectly disciplined in this regard and may have Dims inside blocks that we're actually relying on to be function-level scoped (looks around nervously).
    Yes, can't break existing functionality.
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  29. #389
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,892

    Re: TwinBasic

    Quote Originally Posted by Schmidt View Post
    I'd subscribe to that idea of "Local instead of Dim" for block-scope vars.
    It'd help, to avoid a new "Option Local Scope" - and the special case of: For Each Local P As cPerson In Persons
    would make for a "consistent read and meaning" over all.
    Agreed that the consistency of the keyword "Local" is a good idea, and avoiding another Option is nice too. That said, I guess the votes are in and it's up to Wayne to decide what to do (if anything).



    Quote Originally Posted by Schmidt View Post
    My own usage of such "mixed bag-contents" is pretty rare.
    When it comes to (plain-data-holding) List- and Container-Objects - these usually have "only one type of Value" (or Key).
    Yes, it's rare for me also, and while it's not of huge importance it would be a "nice to have" in those rare cases. For my part, I have a paper form designer that can have different types of objects for drawing on the page (textboxes, lines, shapes, images, etc...). I stuff each of these in a PageObjects collection. All of the different classes have interfaces implemented for shared features (like IDrawable, IBox, IShape2D, etc...) but there are cases where I just want to enumerate a specific type of object. It's easy enough to add a method that returns only the CTextBox classes, or the CImage classes though, I just thought it would be a bit easier to do it without all that. I'm not worried much either way, just throwing some ideas out there.


    Quote Originally Posted by Schmidt View Post
    IMO such filtering should better be handled in the Enumerator (IEnumVariant)- returning "right most part" of a For Each Loop.
    E.g. I could imagine, to enhance the cWidgets-Class of the RC6-GUI about an additional Enumerator-returning method like:

    Code:
    For Each B As cwButton In MyForm.WidgetsByType("cwButton")
    
    Next
    The only thing I don't like about that is the use of a string. If we create our own Widgets and then later change the class name, then that could be a point of failure if we miss any text replacements. What about:

    Code:
    For Each B As cwButton In MyForm.WidgetsByType(New cwButton)
    
    Next
    Or if B gets dimmed before WidgetsByType gets called, then even better:

    Code:
    For Each B As cwButton In MyForm.WidgetsByType(B)
    
    Next
    Last edited by jpbro; Aug 19th, 2021 at 01:14 PM.

  30. #390
    Hyperactive Member
    Join Date
    Aug 2013
    Posts
    266

    Re: TwinBasic

    Quote Originally Posted by yereverluvinuncleber View Post
    Yes, can't break existing functionality.
    VB6 to twinbasic is a one way street (at least if you start taking advantage of the latter's extra functionality?)
    That being so it seems like a fairly easy transformation to move all existing lines starting with "Dim " in a procedure to the top
    when opening a VB6 project in twinbasic for the first time.

  31. #391
    PowerPoster
    Join Date
    Feb 2017
    Posts
    5,671

    Re: TwinBasic

    Quote Originally Posted by vbrad View Post
    VB6 to twinbasic is a one way street (at least if you start taking advantage of the latter's extra functionality?)
    That being so it seems like a fairly easy transformation to move all existing lines starting with "Dim " in a procedure to the top
    when opening a VB6 project in twinbasic for the first time.
    The ability to declare variables at any point in code is not merely semantic, but to my understanding there are minor optimizations by not declaring unneeded variables if a condition (that use the variable) is not met. (Anyway I don't know very much about how that issue works.)

  32. #392
    Fanatic Member
    Join Date
    Jun 2019
    Posts
    579

    Re: TwinBasic

    In the forbidden land, the forbidden language supports this - variable is automatically declared as For Each scope one if it is not declared before in the procedure:
    VB.NET Code:
    1. Private Sub ProcessPersons(persons As List(Of Person))
    2.     For Each p in persons        ' p type is found by the compiler as List(Of T) is explicitly declaring (Of Person)
    3.         ' p is declared scope only as no declaration exists before
    4.         DoSomething(p)
    5.     next
    6.     ' Using p here will not compile
    7.     DoSomething(p)      ' or it will crash if compiler can't catch the problem
    8. End Sub

    But if the variable p is declared before For Each, then the function level declaration works:
    VB.NET Code:
    1. Private Sub ProcessPersons(persons As List(Of Person))
    2.     Dim p As Person
    3.     For Each p in persons
    4.         DoSomething(p)
    5.     next
    6.     ' Using p here will work fine
    7.     DoSomething(p)
    8. End Sub

    If variable is already declared you cannot re-declare (and change its type):
    VB.NET Code:
    1. Private Sub ProcessPersons(persons As List(Of Person))
    2.     Dim p As Person
    3.     For Each p as Customer in persons        ' Compile time error as p is already defined
    4.         DoSomething(p)
    5.     next
    6. End Sub

    Another example is:
    VB.NET Code:
    1. Private Sub ClearAllTextBoxes(frm as Form)
    2.     For Each ctl in frm.Controls.OfType(TextBox)
    3.         ctl.Text = ""
    4.     next
    5. End Sub

    OfType(object) in the forbidden language is extension method and it gets the type of the object and filters all items in the collection so it returns only the required type ones. This is more generic as it can be used for any type of objects:
    VB.NET Code:
    1. For Each ev in events.OfType(CustomerCreated)
    2.     SendNotification($"New customer. Guid={ev.AggregateGuid}")
    3. Next

    I know it is bad to step into the forbidden land as people there are cursed, but sometimes they have good ideas :-)

  33. #393
    Member
    Join Date
    Nov 2018
    Posts
    62

    Re: TwinBasic

    Quote Originally Posted by jpbro View Post
    ...

    OR perhaps:

    Function Scope:
    Code:
    Dim P As cPerson   ' Dimmed outside For Block
    
    For Each P in Persons 
       If True Then Exit For
    Next P
    Block Scope:
    Code:
    For Each P As cPerson in Persons ' The "As cPerson" Dims the var inside the block, outting it in block scope
       If True Then Exit For
    Next P
    This is how .Net does it, and seems to me to be the least-friction way of doing it. For function-scoping, the existing VB6 syntax is exactly the same. If you want the new twinBASIC block-scoping, just add an "As X" caluse to the For.

  34. #394
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,892

    Re: TwinBasic

    I'm just thinking out loud a bit here, so excuse me if this is a bad idea(tm).

    I think another nice convenience feature would be a Nothing-safe If statement. I have some nested objects where it is possible that one or more of the nested objects are not set, requiring boilerplate short-circuiting code like this:

    Code:
    If obj1 Is Nothing Then Exit Sub
    If obj1.obj2 Is Nothing Then Exit Sub
    If obj1.obj2.obj3 Is Nothing Then Exit Sub
    If obj1.obj2.obj3.obj4 Is Nothing Then Exit Sub
    
    ' All objects are set, continue work
    If obj1.obj2.obj3.obj3.someProp > 0 Then
       ' Do Something
    End If
    or perhaps this:

    Code:
    Dim myObj4 As Class4
    
    On Error Resume Next
    Set myObj4 = Nothing ' In case I've used it before
    Set myObj4 = obj1.obj2.obj3.obj4   ' May error if any obj* ref is Nothing, but we've trapped it
    On Error Goto 0
    
    If Not myObj4 Is Nothing Then 
       ' If we get here, myObj4 is set, so we can do something useful with it
    End If

    It would be nice if we could shorten this:

    Code:
    IfSafe obj1.obj2.obj3.obj3.someProp > 0 Then ' If any of the obj* variables are Nothing then IfSafe evaluates to False
       ' Do Something
    End If
    Thinking about it a bit more though, maybe that approach would open up a can of worms requiring "Safe" versions of Do...While, For...Next, etc... so another approach might be a Safe "Set" keyword:

    Code:
    Dim myObj4 As Class4
    
    SetSafe myObj4 = obj1.obj2.obj3.obj4 ' If any nested object ref is Nothing, then myObj4 will be Nothing. If all object refs are something, then myObj4 will be the object returned by .obj4
    If Not myObj4 Is Nothing Then 
       ' If we get here, myObj4 is set, so we can do something useful with it
    End If
    Lastly, I'm not sure I like the "Safe" keyword, there's probably a better option, but I hope it's enough to illustrate the point.

  35. #395
    PowerPoster PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Pontypool, Wales
    Posts
    2,958

    Re: TwinBasic

    [QUOTE=jpbro;5532586]I'm just thinking out loud a bit here, so excuse me if this is a bad idea(tm).

    I think another nice convenience feature would be a Nothing-safe If statement. I have some nested objects where it is possible that one or more of the nested objects are not set, requiring boilerplate short-circuiting code like this:

    Code:
    If obj1 Is Nothing Then Exit Sub
    If obj1.obj2 Is Nothing Then Exit Sub
    If obj1.obj2.obj3 Is Nothing Then Exit Sub
    If obj1.obj2.obj3.obj4 Is Nothing Then Exit Sub
    
    ' All objects are set, continue work
    If obj1.obj2.obj3.obj3.someProp > 0 Then
       ' Do Something
    End If
    C#, not sure about VB.Netthough, has a nice syntax for this. The ?. is used when you want the kind of behaviour you suggest but a normal . is the usual null behaviour.

    Code:
    if (ob1?.obj2?.Property > 2)
    {
    //will get here only if ob1 and obj2 aren't null and the Property is greater than 2
    }
    It is a massive help for writing clearer code, especially when calling members on potentially null objects.

  36. #396
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,892

    Re: TwinBasic

    Quote Originally Posted by mansellan View Post
    This is how .Net does it, and seems to me to be the least-friction way of doing it. For function-scoping, the existing VB6 syntax is exactly the same. If you want the new twinBASIC block-scoping, just add an "As X" caluse to the For.
    Yeah, I think that way does make a lot of sense, but I also see Olaf's point re: the benefits of being able to skip the extra Dim line (which the Local keyword would eliminate). I'm leaning towards preferring the Local keyword since it could be used inside blocks as well to limit scope, but I'm not feeling incredibly strongly about it one way or another.

  37. #397
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,892

    Re: TwinBasic

    Quote Originally Posted by PlausiblyDamp View Post
    C#, not sure about VB.Netthough, has a nice syntax for this. The ?. is used when you want the kind of behaviour you suggest but a normal . is the usual null behaviour.

    Code:
    if (ob1?.obj2?.Property > 2)
    {
    //will get here only if ob1 and obj2 aren't null and the Property is greater than 2
    }
    It is a massive help for writing clearer code, especially when calling members on potentially null objects.

    Well it's good to know other languages have had a need (and found a solution) for this too! For a BASIC language, I'd prefer something more natural language based then the somewhat esoteric looking "?." but I can also see advantages for that kind of notation. I'm assuming you could mix and match "?." and "." in the same line for references that you don't care a Nothing and for ones where you do, which might be good for certain scenarios. It does start to look a bit "nasty" to my eyes though!

    Code:
    if (obj1?.obj2.obj3?.obj4.Property > 2 ) ' Mix of "?." and "."
    Last edited by jpbro; Aug 19th, 2021 at 07:24 PM.

  38. #398
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    9,017

    Re: TwinBasic

    Ah. Lots of discussion here I see. A lot to unpack here.

    Something came up today and now I have to go play with Xamarin for a bit for some kind of "proof of concept" work. Basically someone wants an Android application so I have to go prove we can do it so we can get that job. I've played with Xamarin in the past but actually writing something useful is an entirely different thing. I have to go dig into it. So I might be scarce from this thread for a while. I don't anticipate that this will take long and when I'm done, I want to get back to this.

    Quote Originally Posted by WaynePhillipsEA View Post
    @Niya, I've just released v0.10.4617, the Set-assignment on byref-Variants semantics are now fixed. So this should work for you:

    Code:
    Private Sub SetVarValue(Of T)(ByRef varToSet As Variant, ByVal value As T)
        If IsObject(value) Then
            Set varToSet = value
        Else
            varToSet = value
        End If
    End Sub
    Nice. When I'm done with my hopefully short adventure in the world of Xamarin, we can continue.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  39. #399
    Fanatic Member
    Join Date
    Jun 2019
    Posts
    579

    Re: TwinBasic

    [QUOTE=PlausiblyDamp;5532590]
    Quote Originally Posted by jpbro View Post
    I'm just thinking out loud a bit here, so excuse me if this is a bad idea(tm).

    I think another nice convenience feature would be a Nothing-safe If statement. I have some nested objects where it is possible that one or more of the nested objects are not set, requiring boilerplate short-circuiting code like this:

    Code:
    If obj1 Is Nothing Then Exit Sub
    If obj1.obj2 Is Nothing Then Exit Sub
    If obj1.obj2.obj3 Is Nothing Then Exit Sub
    If obj1.obj2.obj3.obj4 Is Nothing Then Exit Sub
    
    ' All objects are set, continue work
    If obj1.obj2.obj3.obj3.someProp > 0 Then
       ' Do Something
    End If
    C#, not sure about VB.Netthough, has a nice syntax for this. The ?. is used when you want the kind of behaviour you suggest but a normal . is the usual null behaviour.

    Code:
    if (ob1?.obj2?.Property > 2)
    {
    //will get here only if ob1 and obj2 aren't null and the Property is greater than 2
    }
    It is a massive help for writing clearer code, especially when calling members on potentially null objects.


    VB.NET supports same null checks: ?. and ?() null-conditional operators (Visual Basic)

    Example where Disconnect() method is called if _client is not null:
    VB.NET Code:
    1. _client?.Disconnect()

    The question mark is just used as human question: is the object null (nothing). Or in the example above: is _client nothing?

    I think it is more "basic-ish" than other complicated proposals that may arrive.

    P.S. Sorry that I use the forbidden starting underscore in variable names in the good old land thread, but it is allowed in the forbidden land :-)

  40. #400
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,169

    Re: TwinBasic

    Quote Originally Posted by PlausiblyDamp View Post
    C#, not sure about VB.Netthough, has a nice syntax for this. The ?. is used when you want the kind of behaviour you suggest but a normal . is the usual null behaviour.
    TB has true IF ternary operator already using syntax similar to this

    If(Not obj1 Is Nothing, _
    If(Not obj1.obj2 Is Nothing, _
    If(Not obj1.obj2.obj3 Is Nothing, _
    If(Not obj1.obj2.obj3.obj4 Is Nothing, _
    obj1.obj2.obj3.obj4.someProp, 0), 0), 0), 0)


    . . . so above expression must be working fine at run-time.

    Btw, if ?. is considered then ?! (an "optional bang" operator) and ?? (optional "shortcut ternary") must be considered as well and probably return Empty (instead of Null) for both Null and Nothing values in its LHS.

    cheers,
    </wqw>

Page 10 of 52 FirstFirst ... 7891011121320 ... LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width