[Info-vax] BASIC (was Re: 64-bit)

Arne Vajhøj arne at vajhoej.dk
Fri Jan 12 14:56:15 EST 2024


On 1/12/2024 12:40 AM, Dave Froble wrote:
> On 1/11/2024 2:42 PM, Dan Cross wrote:
>> In article <unpa1b$3316l$2 at dont-email.me>,
>> Dave Froble  <davef at tsoft-inc.com> wrote:
>>> On 1/10/2024 9:28 PM, bill wrote:
>>>> On 1/10/2024 7:02 PM, Arne Vajhøj wrote:
>>>>> The world has evolved.
>>>>
>>>> Exactly.  BASIC also evolved, but better languages have passed it by.
>>>
>>> I confess to curiosity.  In what ways has other languages passed by 
>>> Basic?
>>
>> Usually the answer to this is going to be some combination of
>> better abstraction facilities, better safety properties, more
>> capable and ergonomic libraries, etc.
> 
> Which then asks the question, are such really better?  Perhaps some of 
> that is more opinion than fact.

It is not so much Basic vs other languages but a 70's/80's language
vs a modern languages.

But yes progress has been made.

>> VSI BASIC appears to have a few useful things like static type
>> definitions, functions, etc, and it frees the programmer from
>> _having_ to specify e.g. line numbers.  But it doesn't seem to
>> have a lot of support for other abstraction facilities like
>> modules, classes, or anything of that nature.
> 
> What amuses me about that is that when people talk about "classes", I 
> don't have a clue what they are talking about.  Perhaps I do, if the 
> case is new names for old concepts.  That is something I didn't like 
> about Microsoft, they seemed to like re-naming concepts.

Think of classes as record definition with both data and subs/functions.

Bundling the subs/functions with the data they are working on usually
give cleaner code and you have the ability to restrict access to data
to the subs/functions within the class.

Let me produce an example in VMS Basic and VB.NET.

$ type datarec.bas
option type = explicit

record datarec
     string created = 20
     integer counted
end record
$ type vms.bas
program main

%include "datarec.bas"

declare integer nrec
declare datarec alld(1 to 1000)

external datarec function init_datarec(integer)
external sub dump(integer, datarec dim())

print "VMS Basic"
nrec = 0
nrec = nrec + 1
alld(nrec) = init_datarec(37)
sleep(1)
nrec = nrec + 1
alld(nrec) = init_datarec(32)
sleep(1)
nrec = nrec + 1
alld(nrec) = init_datarec(19)
sleep(1)
nrec = nrec + 1
alld(nrec) = init_datarec(50)
call dump(nrec, alld())

end program
!
function datarec init_datarec(integer c)

%include "datarec.bas"

external sub lib$date_time(string by desc)

declare datarec res

call lib$date_time(res::created)
res::counted = c
init_datarec = res

end function
!
sub dump(integer nrec, datarec lstd())

%include "datarec.bas"

declare integer i

external string function tostring(datarec)

for i = 1 to nrec
     print tostring(lstd(i))
next i

end sub
!
function string tostring(datarec d)

%include "datarec.bas"

tostring = "[" + d::created + ": " + str$(d::counted) + "]"

end function
$ bas vms
$ link vms
$ run vms
VMS Basic
[12-JAN-2024 15:38:18: 37]
[12-JAN-2024 15:38:19: 32]
[12-JAN-2024 15:38:20: 19]
[12-JAN-2024 15:38:21: 50]

vs

Imports System
Imports System.Collections.Generic
Imports System.Threading

Namespace Modern
     Public Class Data
         Public Property Created() As DateTime
         Public Property Counted() As Integer
         Public Sub New(c As Integer)
             Created = DateTime.Now
             Counted = c
         End Sub
         Public Overrides Function ToString() As String
             Return String.Format("[{0}: {1}]", Created, Counted)
         End Function
     End Class
     Public Class Program
         Public Shared Sub Dump(lstd As List(Of Data))
             For Each d As Data In lstd
                 Console.WriteLine(d)
             Next
         End Sub
         Public Shared Sub Main(args As String())
             Console.WriteLine("VB.NET")
             Dim alld As New List(Of Data)()
             alld.Add(New Data(37))
             Thread.Sleep(1000)
             alld.Add(New Data(32))
             Thread.Sleep(1000)
             alld.Add(New Data(19))
             Thread.Sleep(1000)
             alld.Add(New Data(50))
             Dump(alld)
             Console.ReadKey()
         End Sub
     End Class
End Namespace

VB.NET
[1/12/2024 2:44:53 PM: 37]
[1/12/2024 2:44:54 PM: 32]
[1/12/2024 2:44:55 PM: 19]
[1/12/2024 2:44:56 PM: 50]

And if we spice it up by extending the data structure:

$ type datarec.bas
option type = explicit

record datarec
     string created = 20
     integer counted
end record
$ type extdatarec.bas
%include "datarec.bas"

record extdatarec
     datarec main
     integer verified
end record

declare integer constant VERIFIED = 1
declare integer constant NOT_VERIFIED = 2
$ type vms2.bas
program main

%include "extdatarec.bas"

declare integer nrec
declare extdatarec alld(1 to 1000)

external extdatarec function init_extdatarec(integer, integer)
external sub dump(integer, extdatarec dim())

print "VMS Basic"
nrec = 0
nrec = nrec + 1
alld(nrec) = init_extdatarec(37, VERIFIED)
sleep(1)
nrec = nrec + 1
alld(nrec) = init_extdatarec(32, VERIFIED)
sleep(1)
nrec = nrec + 1
alld(nrec) = init_extdatarec(19, VERIFIED)
sleep(1)
nrec = nrec + 1
alld(nrec) = init_extdatarec(50, NOT_VERIFIED)
call dump(nrec, alld())

end program
!
function extdatarec init_extdatarec(integer c, integer v)

%include "extdatarec.bas"

declare extdatarec res

external datarec function init_datarec(integer)

res::main = init_datarec(c)
res::verified = v
init_extdatarec = res

end function
!
function datarec init_datarec(integer c)

%include "datarec.bas"

external sub lib$date_time(string by desc)

declare datarec res

call lib$date_time(res::created)
res::counted = c
init_datarec = res

end function
!
sub dump(integer nrec, extdatarec lstd())

%include "extdatarec.bas"

declare integer i

external string function tostring(extdatarec)

for i = 1 to nrec
     print tostring(lstd(i))
next i

end sub
!
function string tostring(extdatarec d)

%include "extdatarec.bas"

declare string VERTEXT(VERIFIED to NOT_VERIFIED)

VERTEXT(VERIFIED) = "Verified"
VERTEXT(NOT_VERIFIED) = "Not verified"
tostring = "[" + d::main::created + ": " + str$(d::main::counted) + " (" 
+ VERTEXT(d::verified) + ")]"

end function
$ bas vms2
$ link vms2
$ run vms2
VMS Basic
[12-JAN-2024 15:42:38: 37 (Verified)]
[12-JAN-2024 15:42:39: 32 (Verified)]
[12-JAN-2024 15:42:40: 19 (Verified)]
[12-JAN-2024 15:42:41: 50 (Not verified)]

vs

Imports System
Imports System.Collections.Generic
Imports System.Threading

Namespace Modern2
     Public Class Data
         Public Property Created() As DateTime
         Public Property Counted() As Integer
         Public Sub New(c As Integer)
             Created = DateTime.Now
             Counted = c
         End Sub
         Public Overrides Function ToString() As String
             Return String.Format("[{0}: {1}]", Created, Counted)
         End Function
     End Class
     Public Class ExtData
         Inherits Data
         Public Property Verified() As Boolean
         Public Sub New(c As Integer, v As Boolean)
             MyBase.New(c)
             Verified = v
         End Sub
         Public Overrides Function ToString() As String
             Return String.Format("[{0}: {1} ({2})]", Created, Counted, 
If(Verified, "Verified", "Not verified"))
         End Function
     End Class
     Public Class Program
         Public Shared Sub Dump(lstd As List(Of Data))
             For Each d As Data In lstd
                 Console.WriteLine(d)
             Next
         End Sub
         Public Shared Sub Main(args As String())
             Console.WriteLine("VB.NET")
             Dim alld As New List(Of Data)()
             alld.Add(New ExtData(37, True))
             Thread.Sleep(1000)
             alld.Add(New ExtData(32, True))
             Thread.Sleep(1000)
             alld.Add(New ExtData(19, True))
             Thread.Sleep(1000)
             alld.Add(New ExtData(50, False))
             Dump(alld)
             Console.ReadKey()
         End Sub
     End Class
End Namespace

VB.NET
[1/12/2024 2:49:04 PM: 37 (Verified)]
[1/12/2024 2:49:05 PM: 32 (Verified)]
[1/12/2024 2:49:07 PM: 19 (Verified)]
[1/12/2024 2:49:08 PM: 50 (Not verified)]

Besides using objected oriented programming the VB.NET code also
used some generic programming. The List(Of Data) thing.

An illustrative example of how it works:

Imports System

Namespace Gen
     Public Class Pair(Of T As IComparable(Of T))
         Public Property FirstValue() As T
         Public Property SecondValue() As T
         Public Sub New(first As T, second As T)
             FirstValue = first
             SecondValue = second
         End Sub
         Public Sub Swap()
             Dim temp As T = FirstValue
             FirstValue = SecondValue
             SecondValue = temp
         End Sub
         Public Function Max() As T
             If FirstValue.CompareTo(SecondValue) > 0 Then
                 Return FirstValue
             Else
                 Return SecondValue
             End If
         End Function
         Public Overrides Function ToString() As String
             Return String.Format("({0},{1})", FirstValue, SecondValue)
         End Function
     End Class
     Public Class Program
         Public Shared Sub Main(args As String())
             Dim ip As New Pair(Of Integer)(123, 456)
             Console.WriteLine(ip)
             Console.WriteLine(ip.Max())
             ip.Swap()
             Console.WriteLine(ip)
             Console.WriteLine(ip.Max())
             Dim sp As New Pair(Of String)("ABC", "DEF")
             Console.WriteLine(sp)
             Console.WriteLine(sp.Max())
             sp.Swap()
             Console.WriteLine(sp)
             Console.WriteLine(sp.Max())
             Console.ReadKey()
         End Sub
     End Class
End Namespace

>>  I
>> don't see any support for higher-order functions,
> 
> Not sure what that means ...
> 
>> lambdas,
> 
> Not sure what that means ...
> 
>> or
>> closures;
> 
> Not sure what that means ...
> 
>> no currying of functions.
> 
> Not sure what that means ...

Functional programming is another big area.

I don't think the typical business application need
much of the advanced stuff, but some things can be
done conveniently.

A slightly modified version of the last VB.NET example
with an appetizer:

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Threading

Namespace Modern3
     Public Class Data
         Public Property Created() As DateTime
         Public Property Counted() As Integer
         Public Sub New(c As Integer)
             Created = DateTime.Now
             Counted = c
         End Sub
         Public Overrides Function ToString() As String
             Return String.Format("[{0}: {1}]", Created, Counted)
         End Function
     End Class
     Public Class ExtData
         Inherits Data
         Public Property Verified() As Boolean
         Public Sub New(c As Integer, v As Boolean)
             MyBase.New(c)
             Verified = v
         End Sub
         Public Overrides Function ToString() As String
             Return String.Format("[{0}: {1} ({2})]", Created, Counted, 
If(Verified, "Verified", "Not verified"))
         End Function
     End Class
     Public Class Program
         Public Shared Sub Dump(lbl As String, lstd As IEnumerable(Of Data))
             Console.WriteLine(lbl)
             For Each d As Data In lstd
                 Console.WriteLine(d)
             Next
         End Sub
         Public Shared Sub Main(args As String())
             Console.WriteLine("VB.NET")
             Dim alld As New List(Of ExtData)()
             alld.Add(New ExtData(37, True))
             Thread.Sleep(1000)
             alld.Add(New ExtData(32, True))
             Thread.Sleep(1000)
             alld.Add(New ExtData(19, True))
             Thread.Sleep(1000)
             alld.Add(New ExtData(50, False))
             Dump("All:", alld)
             Dump("Counted < 30:", alld.Where(Function(d) d.Counted < 30))
             Dump("Verified = false:", alld.Where(Function(d) Not 
d.Verified))
             Console.ReadKey()
         End Sub
     End Class
End Namespace

VB.NET
All:
[1/12/2024 2:54:36 PM: 37 (Verified)]
[1/12/2024 2:54:37 PM: 32 (Verified)]
[1/12/2024 2:54:38 PM: 19 (Verified)]
[1/12/2024 2:54:39 PM: 50 (Not verified)]
Counted < 30:
[1/12/2024 2:54:38 PM: 19 (Verified)]
Verified = false:
[1/12/2024 2:54:39 PM: 50 (Not verified)]

The point is the function passed to the Where method that
allows for great flexibility in filtering data.

Arne




More information about the Info-vax mailing list