[Info-vax] BASIC (and Horizon)
Arne Vajhøj
arne at vajhoej.dk
Wed Jan 31 10:20:35 EST 2024
On 1/30/2024 11:28 PM, Dave Froble wrote:
> On 1/30/2024 9:40 AM, Chris Townley wrote:
>> On 30/01/2024 07:06, Dave Froble wrote:
>>> I'm amused every time the GoTo bashing begins.
>>>
>>> Not only is there nothing wrong when using a branch operation, when
>>> appropriate, just look at the assembler listings after compilation.
>>> Branching
>>> is just about all assembler does, as required.
>>>
>>> Now, I won't defend what I and most consider improper use of the poor
>>> misunderstood GoTo statement.
>>>
>>
>> But unless used very carefully, it can create horrible spaghetti like
>> code, and
>> is also easy to screw up.
>>
>> Using proper structured constructs is much better - easier to read as
>> well,
>> hence better maintainability.
>
> Prey tell, what structured construct will perform cleanup and exit? I
> always expected a return from routines and such.
Let me try and show some examples.
In VB.NET.
Te first two examples could be done in VMS Basic (obviously
procedural not object oriented) but the last can not.
First with goto:
Imports System
Namespace GoToDemo
Public NotInheritable Class Luck
Private Shared rng As New Random()
Public Shared Function InLuck() As Boolean
Return rng.NextDouble() > 0.2
End Function
End Class
Public Class X
Private id As String
Private Sub New(id As String)
Me.id = id
Console.WriteLine("X {0} created", id)
End Sub
Public Shared Function Create(id As String) As X
If Luck.InLuck() Then
Return New X(id)
Else
Return Nothing
End If
End Function
Public Sub Close()
Console.WriteLine("X {0} closed", id)
End Sub
End Class
Public Class Program
Public Shared Sub Main(args As String())
Dim o1 As X = X.Create("A")
If o1 Is Nothing Then
Console.WriteLine("Error creating A")
GoTo lbl_done
End If
Dim o2 As X = X.Create("B")
If o2 Is Nothing Then
Console.WriteLine("Error creating B")
GoTo lbl_close1
End If
' 20 lines
Console.WriteLine("Part 1")
If Not Luck.InLuck() Then
Console.WriteLine("Error during execution")
GoTo lbl_close2
End If
' 20 lines
Console.WriteLine("Part 2")
lbl_close2:
o2.Close()
lbl_close1:
o1.Close()
lbl_done:
Console.ReadKey(True)
End Sub
End Class
End Namespace
It is with goto, but I don't think it is a bad use of goto. It just
jumps down to the cleanup code in case of an error.
Next traditional blocks:
Imports System
Namespace BlocksDemo
Public NotInheritable Class Luck
Private Shared rng As New Random()
Public Shared Function InLuck() As Boolean
Return rng.NextDouble() > 0.2
End Function
End Class
Public Class X
Private id As String
Private Sub New(id As String)
Me.id = id
Console.WriteLine("X {0} created", id)
End Sub
Public Shared Function Create(id As String) As X
If Luck.InLuck() Then
Return New X(id)
Else
Return Nothing
End If
End Function
Public Sub Close()
Console.WriteLine("X {0} closed", id)
End Sub
End Class
Public Class Program
Public Shared Sub Main(args As String())
Dim o1 As X = X.Create("A")
If o1 IsNot Nothing Then
Dim o2 As X = X.Create("B")
If o2 IsNot Nothing Then
' 20 lines
Console.WriteLine("Part 1")
If Luck.InLuck() Then
' 20 lines
Console.WriteLine("Part 2")
Else
Console.WriteLine("Error during execution")
End If
o2.Close()
Else
Console.WriteLine("Error creating B")
End If
o1.Close()
Else
Console.WriteLine("Error creating A")
End If
Console.ReadKey(True)
End Sub
End Class
End Namespace
No goto's. But I do not consider the code more readable than the
version with goto's. It sort of unnecessarily stretch out the
core logic.
And now the modern way with exceptions:
Imports System
Namespace ExceptionsDemo
Public NotInheritable Class Luck
Private Shared rng As New Random()
Public Shared Function InLuck() As Boolean
Return rng.NextDouble() > 0.2
End Function
End Class
Public Class XException
Inherits Exception
Public Sub New(msg As String)
MyBase.New(msg)
End Sub
End Class
Public Class X
Implements IDisposable
Private id As String
Public Sub New(id As String)
If Luck.InLuck() Then
Me.id = id
Console.WriteLine("X {0} created", id)
Else
Throw New XException("Error creating " & id)
End If
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Console.WriteLine("X {0} closed", id)
End Sub
End Class
Public Class Program
Public Shared Sub Main(args As String())
Try
Using o1 As New X("A")
Using o2 As New X("B")
' 20 lines
Console.WriteLine("Part 1")
If Not Luck.InLuck() Then
Throw New XException("Error during execution")
End If
' 20 lines
Console.WriteLine("Part 2")
End Using
End Using
Catch ex As XException
Console.WriteLine(ex.Message)
End Try
Console.ReadKey(True)
End Sub
End Class
End Namespace
Which I think is pretty nice. No goto's but still a compact
core logic.
For the not VB.NET knowledgable:
Using o1 As New X("A")
...
End Using
calls o1.Dispose() when the block is exited no matter how it
is exited - normal or exception does not matter Dispose is
always called.
Arne
More information about the Info-vax
mailing list