Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 17:31 09 May 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : OOP (object oriented programming) in MMBASIC (kind of)

     Page 1 of 3    
Author Message
Amnesie
Guru

Joined: 30/06/2020
Location: Germany
Posts: 528
Posted: 03:26pm 21 Mar 2025
Copy link to clipboard 
Print this post

Hello,

I'm turning my head around this question. Of course I am aware of the fact that BASIC isn't about OOP at all. I know, BUT:

C programming language isn't about OOP, too but it is kind of possible in C to do this. For example with this approach:

C example Code:

struct myStructure {
 int  myNum;
 char myLetter;
 char myString[30]; // String
};

int main() {
 struct myStructure s1;

 // Assign a value to the string using the strcpy function
 strcpy(s1.myString, "Some text");

 // Print the value
 printf("My string: %s", s1.myString);

 return 0;
}


Is there a way in MMBASIC to do something similar to the STRUCT in C?
I think this could be a great way for bigger programs to give it a better structure. At this point I am only aware of some worarounds with arrays...

Greetings
Daniel
Edited 2025-03-22 01:27 by Amnesie
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7499
Posted: 03:59pm 21 Mar 2025
Copy link to clipboard 
Print this post

I don't understand C so a lot of the above doesn't mean a lot to me, but isn't this close to a FUNCTION ? You can feed it a set of variables and it returns a value?
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
vegipete

Guru

Joined: 29/01/2013
Location: Canada
Posts: 1121
Posted: 04:07pm 21 Mar 2025
Copy link to clipboard 
Print this post

Maybe something like the following? (Untested)
dim string mystruct
dim integer myaddr = PEEK(VARADDR mystruct)

POKE INTEGER myaddr, 1234  ' store an integer in the "structure"
MID$(mystruct,9,1) = "T"   ' store character, 9th element
MID$(mystruct,10,31) = "A string to store."

i = PEEK(INTEGER myaddr)   ' read the integer
c = MID$(mystruct,9,1)     ' read the character
s$ = MID$(mystruct,10)     ' read the string

Which is indeed just a bunch of work-arounds with an array.
Edited 2025-03-22 02:09 by vegipete
Visit Vegipete's *Mite Library for cool programs.
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4249
Posted: 04:08pm 21 Mar 2025
Copy link to clipboard 
Print this post

That's not OOP, that's just a structured type - MMBasic doesn't have those, the best you can do is use a STRING type with the FIELD$() function or allocate integer arrays and PEEK and POKE around them as raw memory (as just illustrated by @vegipete plus he used MID$ to access string members). Both of which have significant performance implications.

Naively OOP starts from structured types and then allows them to have embedded functions (which we call methods) that receive an implict 'this' parameter which is the instance of the structure they are operating on. Plus they tend to allow the structured types to be hierarchical (or introduce the concept of an "interface" and have those be hierarchical instead.)

I have some ideas for adding structured types to MMB4L (from where Peter might decide they can be implemented more generally) and could probably manage objects in time ... however, if you're planning on holding your breath until then you should probably advise your relatives to send flowers .

Best wishes,

Tom
Edited 2025-03-22 02:13 by thwill
MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
Marcel27

Regular Member

Joined: 13/08/2024
Location: Netherlands
Posts: 77
Posted: 05:26pm 21 Mar 2025
Copy link to clipboard 
Print this post

Oh, no, please no oop in mmbasic, it's the worst invention ever made.
 
bfwolf
Regular Member

Joined: 03/01/2025
Location: Germany
Posts: 72
Posted: 06:06pm 21 Mar 2025
Copy link to clipboard 
Print this post

  thwill said  
...
Naively OOP starts from structured types and then allows them to have embedded functions (which we call methods) that receive an implict 'this' parameter which is the instance of the structure they are operating on. Plus they tend to allow the structured types to be hierarchical (or introduce the concept of an "interface" and have those be hierarchical instead.)

I have some ideas for adding structured types to MMB4L (from where Peter might decide they can be implemented more generally) and could probably manage objects in time ... however, if you're planning on holding your breath until then you should probably advise your relatives to send flowers .

Best wishes,

Tom


Oh - having structured data types would be really very nice and useful!

Perhaps this would come at some future day?
I suggest using the syntax as described for VBA:
Type MyType
MyName As String ' String variable stores a name.
MyBirthDate As Date ' Date variable stores a birthdate.
MySex As Integer ' Integer variable stores sex (0 for female, 1 for male).
End Type


https://learn.microsoft.com/en-us/office/vba/language/how-to/user-defined-data-type

Extending to OOP wold be a further step, but could be added by just extending this syntax with the ability to define functions and subs (methods) within this "Type .. End Type" clause.

I think I already saw some OOP BASIC variants using this syntax.

In C++ structs are also "just classes" with the difference, that in structs all members default as public - so no need to define an aditional "Class .. End Class" clause.

Adding public/private isn't mandatory and makes OOP "more complicated" for beginners.
And single inheritance (as e.g. in Java) would be enough - multiple (as allowed in C++) leads to confusion very often..
This also applies to polymorphism!

bfwolf
Edited 2025-03-22 04:21 by bfwolf
 
Amnesie
Guru

Joined: 30/06/2020
Location: Germany
Posts: 528
Posted: 06:34pm 21 Mar 2025
Copy link to clipboard 
Print this post

@ vegipete

Yes I came up with something similar.. But never thought about possible downsides when it comes to speed.

@ Tom

I know that this isn't real OOP, that's why I wrote "kind of" just that one understand what I am thinking of.

@ bfwolf

Yes, I also think it would be a nice addition to the MMBASIC syntax / possibilities. This way it would be possible to "wrap" more than just one datatype in a nice little structure. Especially when it comes to databases or textadventures I see a huge benefit for this... I also think, that going further isn't necessary (private.. polymorphism etc.) But I often wish to be able just to combine different datatypes into one "package" since I use this often in C.

To give an example for a text adventure game, I need a lot of arrays to not get lost:


Dim location(3)= "" 'array to store player location
Dim exits(3)= "" 'array to store player exit points
Dim itemsPlayer(10)= "" 'array to store player items
Dim itemsRoom(10)= "" 'array to store items in the room
'etc...

Dim integer room = 1 'current room of player


It would be way more practical if I could say, that all these arrays belong to the
room. This is just an example with a few things.. And multidimensional arrays make things worse when it comes to readability... I think.

Greetings
Daniel
Edited 2025-03-22 05:01 by Amnesie
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7499
Posted: 07:06pm 21 Mar 2025
Copy link to clipboard 
Print this post

Why load MMBasic down with even more stuff that it doesn't need?  :)
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Amnesie
Guru

Joined: 30/06/2020
Location: Germany
Posts: 528
Posted: 07:11pm 21 Mar 2025
Copy link to clipboard 
Print this post

  Mixtel90 said  Why load MMBasic down with even more stuff that it doesn't need?  :)


Because it is easier to maintain code. It is all about readability and not repeating myself again and again.

In Python for example I do this:


class Room():
def __init__(self, name, description):
self.name = name
self.description = description
self.exits = {}
self.items = []
self.npcs = []


And I think some kind of
struct
type isn't a bad idea. It must not be classes or such... But one datatype to wrap different datatypes into one package does make a whole lot of sense. Of course you can also write whole programs in assembly - so why using BASIC anyways.

Greetings
Daniel
Edited 2025-03-22 05:15 by Amnesie
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7499
Posted: 08:06pm 21 Mar 2025
Copy link to clipboard 
Print this post

But BASIC is already a language, one that has grown over many years and has so far resisted OOP. ;) It was never designed to handle it and, generally, has performance issues (as an interpreter) that make it inefficient to add such foreign concepts.

Modern languages such as RUST are designed with code security in mind. You can *never* get that in BASIC, C or Python. OOP is ideal for something like RUST, where the code can be built with secure partitioning and without the risk of the programmer breaking memory management, buffer overflows etc. Gluing OOP on top of BASIC can only bring tears in the long run. :)
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Amnesie
Guru

Joined: 30/06/2020
Location: Germany
Posts: 528
Posted: 08:17pm 21 Mar 2025
Copy link to clipboard 
Print this post

  Mixtel90 said  But BASIC is already a language, one that has grown over many years and has so far resisted OOP. ;) It was never designed to handle it and, generally, has performance issues (as an interpreter) that make it inefficient to add such foreign concepts.

Modern languages such as RUST are designed with code security in mind. You can *never* get that in BASIC, C or Python. OOP is ideal for something like RUST, where the code can be built with secure partitioning and without the risk of the programmer breaking memory management, buffer overflows etc. Gluing OOP on top of BASIC can only bring tears in the long run. :)


@ Mixtel90
Uhm... Visual BASIC has OOP and Python as an interpreted language also has OOP, but that isn't the point. As Tom already wrote I am not really talking about OOP more of an datatype called STRUCT. So... yeah sorry my Topic title was a bit of clickbait.

Greetings
Daniel
Edited 2025-03-22 06:18 by Amnesie
 
PeteCotton

Guru

Joined: 13/08/2020
Location: Canada
Posts: 527
Posted: 03:29am 22 Mar 2025
Copy link to clipboard 
Print this post

I've been using arrays with constants to make the code a bit more readable (like a struct). Of course, you are limited to just using one variable type, but there is very little penalty (if any) for using Float vs Ints in MMBasic, so you could use Floats for the array - which would cover most scenarios (apart from Strings obviously).

DIM INTEGER Ships(100,16) ' ShipId, then parameters (see next few lines)
CONST SHIP_TYPE = 1
CONST SHIP_X = 2
CONST SHIP_Y = 3
CONST SHIP_ANGLE = 4
CONST SHIP_SHIELDN = 5
CONST SHIP_SHIELDE = 6
CONST SHIP_SHIELDS = 7
CONST SHIP_SHIELDW = 8
CONST SHIP_SHIELD_MAX = 9
CONST SHIP_HULL = 10
CONST SHIP_ENGINES = 11
CONST SHIP_WEAPONS = 12
CONST SHIP_SENSORS = 13
CONST SHIP_LOGIC = 14  ' 0=None, 1=Attacking, 2=Fleeing
CONST SHIP_LOGIC2 = 15 ' Used as part of the logic
CONST SHIP_POWER = 16


So, if I want to get the X location of ship #5, then I just use


Ships(5,SHIP_X)


It's not as neat as a struct. And while Structs would be an amazing addition to MMBasic, I am aware that it's probably a bit of a nightmare to add in, and I am already sooo grateful for the amazing features MMBasic has already given us, that I can live with this.
Edited 2025-03-22 13:29 by PeteCotton
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7499
Posted: 08:07am 22 Mar 2025
Copy link to clipboard 
Print this post

If you set up some constants:
CONST num.of.ships = 11
CONST TYPE = 1
CONST XPOS = 2
CONST YPOS = 3
CONST ANGLE = 4
etc.

Then define an array:

DIM SHIP(num.of.ships,16)

You can then use the values as:
SHIP(1,TYPE)
SHIP(4,ANGLE)
etc.

You may be able to re-use the CONS values for other things.
e.g,

DIM SPACEMINE(12,16)

if SPACEMINE(3,XPOS) = 0 then mine.is.inactive

It would help to keep shared CONST values in the lowest numbers as then any arrays could be smaller. i.e. if CONST XPOS = 1 and CONST XPOS = 2 then you could use DIM SPACEMINE(12,2)

.
Edited 2025-03-22 18:10 by Mixtel90
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
bfwolf
Regular Member

Joined: 03/01/2025
Location: Germany
Posts: 72
Posted: 10:18am 23 Mar 2025
Copy link to clipboard 
Print this post

Arrays with "named indices" are one possibility, but this is more of a "würgaround" than a workaround.

For readers unfamiliar with German language: This is a play on words... "würgen" = "to choke."

Furthermore, such arrays naturally only accommodate values ​​of the same type, which would require creating multiple arrays to store different types of information.
And of course pass multiple args to subs and functions for the same "bundle"..


CONST num.of.ships = 11
CONST num.of.ship_int = 4
CONST TYPE = 1
CONST XPOS = 2
CONST YPOS = 3
CONST ANGLE = 4

CONST num.of.ship_str = 2
CONST NAME = 1
CONST OWNER = 2
' etc.

' Then define arrays:
DIM SHIP_INT(num.of.ships,num.of.ship_int) As integer
DIM SHIP_STR(num.of.ships,num.of.ship_str) As string

' You can then use the values as:
SHIP_INT(1,TYPE) = 3
SHIP_STR(1,OWNER) = "Geoff"
SHIP_INT(4,ANGLE) = 88
'etc.


Structs (Records in Pascal) are simply the most elegant way to do this, and you can create arrays of structs, which then "bundle" the information in each element. You can also pass the entire struct to procedures and functions as an argument (e.g., by reference).

Unfortunately, the '.' character is permitted as part of variable names and therefore cannot simply be used as a separator between struct instance names and member names. A different separator might have to be found that isn't already used as a token or operator. Perhaps the '#' character?

Extending structs with OO by adding methods and inheritance would open up entirely new programming techniques, but that would be the icing on the cake - and it doesn't necessarily have to be that way.
 
homa

Guru

Joined: 05/11/2021
Location: Germany
Posts: 459
Posted: 01:04pm 23 Mar 2025
Copy link to clipboard 
Print this post

  bfwolf said  
Unfortunately, the '.' character is permitted as part of variable names and therefore cannot simply be used as a separator between struct instance names and member names. A different separator might have to be found that isn't already used as a token or operator. Perhaps the '#' character?

Extending structs with OO by adding methods and inheritance would open up entirely new programming techniques, but that would be the icing on the cake - and it doesn't necessarily have to be that way.


To use the '.' character, you could give the command via OPTION in the program (analogous to OPTION EXPLICIT), but I don't think OOP comes in MMBasic on a microprocessor, but what do I know.

Matthias
 
LeoNicolas

Guru

Joined: 07/10/2020
Location: Canada
Posts: 499
Posted: 02:07pm 23 Mar 2025
Copy link to clipboard 
Print this post

I think the question is not about OOP, but regarding data structures. There is no struct like structures in basic. For my game Knightmare I'm using the same approach as PeteCotton. I'm allocating arrays to store what I want.

https://github.com/leonicolas/knightmare-cmm2/blob/main/global.inc
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4249
Posted: 02:27pm 23 Mar 2025
Copy link to clipboard 
Print this post

Whilst I think structured types would be of great benefit (not least because they should be faster than the approach using arrays with named constants which require two variable lookups) I'm not convinced about the need for OOP ... except that once you have proper structured types, including the ability to pass them by reference to functions then I believe the jump to implement OOP is not that great.

However I again caution against holding of breath (unless Peter decides to work one of his miracles) as adding a new fundamental type to MMBasic is a very significant piece of work with plenty of opportunity to destablise MMBasic for several months.

Best wishes,

Tom
MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
bfwolf
Regular Member

Joined: 03/01/2025
Location: Germany
Posts: 72
Posted: 02:46pm 23 Mar 2025
Copy link to clipboard 
Print this post

I also agree that the step to OOP would be another big one, and that it wouldn't be necessary.

And yes - in "classic" BASIC dialects, the concept of "user-defined types" (UDT) isn't known - but in many modern dialects, it is:

VBA:
https://learn.microsoft.com/en-us/office/vba/language/how-to/user-defined-data-type

FreeBasic:
https://freebasic.net/wiki/ProPgUDTs

XC=BASIC (for C64 etc.):
https://xc-basic.net/doku.php?id=v3:udt

And all three use the same approach and syntax..

FreeBasic even supports pointers!

But let this be "future music"..

bfwolf.
Edited 2025-03-24 00:47 by bfwolf
 
toml_12953
Guru

Joined: 13/02/2015
Location: United States
Posts: 390
Posted: 02:53pm 23 Mar 2025
Copy link to clipboard 
Print this post

  Amnesie said  
  Mixtel90 said  But BASIC is already a language, one that has grown over many years and has so far resisted OOP. ;) It was never designed to handle it and, generally, has performance issues (as an interpreter) that make it inefficient to add such foreign concepts.

Modern languages such as RUST are designed with code security in mind. You can *never* get that in BASIC, C or Python. OOP is ideal for something like RUST, where the code can be built with secure partitioning and without the risk of the programmer breaking memory management, buffer overflows etc. Gluing OOP on top of BASIC can only bring tears in the long run. :)


@ Mixtel90
Uhm... Visual BASIC has OOP and Python as an interpreted language also has OOP, but that isn't the point. As Tom already wrote I am not really talking about OOP more of an datatype called STRUCT. So... yeah sorry my Topic title was a bit of clickbait.

Greetings
Daniel


Heck, I'd settle for just having user-defined data types. Fixed length records of user defined types would make handling RANDOM files much cleaner, too.
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4852
Posted: 05:34pm 23 Mar 2025
Copy link to clipboard 
Print this post

All,

If you think OOB (Out Of the Box) in stead of OOP, you can implement structures already in MMBasic.

Assume you want this

Struct address{
  STREET as string 12
  NUMBER as integer
      }

Define Peter type address

Peter.street = "churchroad"
Peter.number = 12


What about using following technique

DIM street$(nn) length 12
DIM number%(nn)

Peter = 0 : Charly = 1 : Karen = 2
street$(Peter)="churchroad"
number%(Peter)=12


So instead of Peter.street you use street$(Peter).

Volhout
Edited 2025-03-24 03:38 by Volhout
PicomiteVGA PETSCII ROBOTS
 
     Page 1 of 3    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025