[Implemented] Features: lists in structure, assertions
[Implemented] Features: lists in structure, assertions
The list is short: lists and maps in structures and try-catch-finally assertion blocks.
Lists/maps in structures and the loss of encapsulation
I've begun to find more and more that some projects I'll code outright in C++ instead of PureBasic simply because the loss of encapsulation for lists makes programming a particular design a spectacular chore. Sure, I can split up the data structures into a separate file and interact with them with an additional interface on top but then I'm just emulating class-like behavior anyways, right? But to interact with a list I then have to encapsulate all of its functions --yuck! Or I could call it directly.. but then I lose encapsulation, again.
I've already written a replacement linked list library in PureBasic which I can use in structures but then I decide why bother? I can get better encapsulation out of the box using objects anyways and I don't have to rewrite data structures that already exist or implement a new interface on top of them every time I want the encapsulation.
I'm not suggesting that I'm too lazy to not just use it the way it is. It's that the resulting code makes less sense when coming back to it in the future. And where complex associated lists begin talking to each other where they exist outside of structures they should exist within, it becomes extremely difficult to read and maintain. And what about dynamically allocating lists and maps? That's impossible, unless I write my own.
So I did. I wrote my own linked list library. And the PureBasic semantics make it crazy to use and to read. But it doesn't have to be that way.
Every element must be passed as "@*This" which is in and of itself dangerous and is not well supported by PureBasic. Without references, native pointer-to-pointers and an equivalent to the arrow -> to go with it or at least a dereference operator, dealing with these pointer-to-pointer values is overly complex, error prone as a result, difficult to read, and difficult to maintain.
If I'm building some exotic data structure this might be a necessary evil. But it shouldn't be this difficult just to use lists in structures. Really, it shouldn't.
Assertions make coding infinitely simpler
See my detailed explanation of how error handling in PureBasic can be overly difficult:
http://www.purebasic.fr/english/viewtop ... =3&t=37568
Assertions make coding simpler and replace the necessity of handling and checking for error codes everywhere. Error handling and your normal code become closely intertwined. To program good rock-solid code with excellent error handling in PureBasic is a herculean effort. The resulting code is messy and it becomes hard to ensure that you have actually dealt with all possible errors. It's spaghetti code and extremely difficult to read.
One of my personal projects I've written in PureBasic was designed from the beginning to have robust error handling because it was expected to throw errors frequently and at random in any function where the state could change (as per the nature of the project).
The error handler needed to be able to handle the error appropriately, log a reverse stack trace back to the source of the error for reference including the file name and line number, and then continue from where it left off. All of this had to be accomplished with transparent support for multithreading where multiple errors could be thrown simultaneously.
The difficulty of trying to manage general coding and error handling in this project has been insane. I've rewritten this project from scratch three times now because the code just couldn't scale, handle errors elegantly, and remain as clear, maintainable code. That's asinine. I can say for certain that the next iteration certainly won't be written in PureBasic.
I've mentioned before how macro functions can alleviate a lot of the spaghetti code that is required for error handling in PureBasic. But I believe that assertions are also a necessary iteration for eliminating the inevitable error handling mess where robust error handling is essential.
This request isn't meant to bash Fred/freak in any way. It's very clear that in every new version that is always a great list of additional features. This is merely the extent of my frustration of what I've been experiencing when trying to write good code in PureBasic.
This is, for you, a very real and a very blunt synopsis of my dissatisfaction with PureBasic for certain projects where I've found it to be sorely inadequate. However, all of these projects have gone beyond what I would consider to be the bounds of PureBasic. The point I hope to convey is that PureBasic's capability in these scenarios is very weak.
Lists/maps in structures and the loss of encapsulation
I've begun to find more and more that some projects I'll code outright in C++ instead of PureBasic simply because the loss of encapsulation for lists makes programming a particular design a spectacular chore. Sure, I can split up the data structures into a separate file and interact with them with an additional interface on top but then I'm just emulating class-like behavior anyways, right? But to interact with a list I then have to encapsulate all of its functions --yuck! Or I could call it directly.. but then I lose encapsulation, again.
I've already written a replacement linked list library in PureBasic which I can use in structures but then I decide why bother? I can get better encapsulation out of the box using objects anyways and I don't have to rewrite data structures that already exist or implement a new interface on top of them every time I want the encapsulation.
I'm not suggesting that I'm too lazy to not just use it the way it is. It's that the resulting code makes less sense when coming back to it in the future. And where complex associated lists begin talking to each other where they exist outside of structures they should exist within, it becomes extremely difficult to read and maintain. And what about dynamically allocating lists and maps? That's impossible, unless I write my own.
So I did. I wrote my own linked list library. And the PureBasic semantics make it crazy to use and to read. But it doesn't have to be that way.
Every element must be passed as "@*This" which is in and of itself dangerous and is not well supported by PureBasic. Without references, native pointer-to-pointers and an equivalent to the arrow -> to go with it or at least a dereference operator, dealing with these pointer-to-pointer values is overly complex, error prone as a result, difficult to read, and difficult to maintain.
If I'm building some exotic data structure this might be a necessary evil. But it shouldn't be this difficult just to use lists in structures. Really, it shouldn't.
Assertions make coding infinitely simpler
See my detailed explanation of how error handling in PureBasic can be overly difficult:
http://www.purebasic.fr/english/viewtop ... =3&t=37568
Assertions make coding simpler and replace the necessity of handling and checking for error codes everywhere. Error handling and your normal code become closely intertwined. To program good rock-solid code with excellent error handling in PureBasic is a herculean effort. The resulting code is messy and it becomes hard to ensure that you have actually dealt with all possible errors. It's spaghetti code and extremely difficult to read.
One of my personal projects I've written in PureBasic was designed from the beginning to have robust error handling because it was expected to throw errors frequently and at random in any function where the state could change (as per the nature of the project).
The error handler needed to be able to handle the error appropriately, log a reverse stack trace back to the source of the error for reference including the file name and line number, and then continue from where it left off. All of this had to be accomplished with transparent support for multithreading where multiple errors could be thrown simultaneously.
The difficulty of trying to manage general coding and error handling in this project has been insane. I've rewritten this project from scratch three times now because the code just couldn't scale, handle errors elegantly, and remain as clear, maintainable code. That's asinine. I can say for certain that the next iteration certainly won't be written in PureBasic.
I've mentioned before how macro functions can alleviate a lot of the spaghetti code that is required for error handling in PureBasic. But I believe that assertions are also a necessary iteration for eliminating the inevitable error handling mess where robust error handling is essential.
This request isn't meant to bash Fred/freak in any way. It's very clear that in every new version that is always a great list of additional features. This is merely the extent of my frustration of what I've been experiencing when trying to write good code in PureBasic.
This is, for you, a very real and a very blunt synopsis of my dissatisfaction with PureBasic for certain projects where I've found it to be sorely inadequate. However, all of these projects have gone beyond what I would consider to be the bounds of PureBasic. The point I hope to convey is that PureBasic's capability in these scenarios is very weak.
Re: Features I think PureBasic really needs: lists, assertions
List/Map in structure are planned. About assertions, i'm not sure. Exception oriented programming really needs object oriented langauge, with managed data (ie: garbage collector or smart pointers) else you will soon or later have major leak etc. in your program.
Re: Features I think PureBasic really needs: lists, assertions
That's what "finally" is for. An object-oriented language with the right semantics doesn't need finally because that kind of functionality is supposed to be handled in the destructor. In a procedural language it would be necessary.Fred wrote:List/Map in structure are planned. About assertions, i'm not sure. Exception oriented programming really needs object oriented langauge, with managed data (ie: garbage collector or smart pointers) else you will soon or later have major leak etc. in your program.
See here:
http://www2.research.att.com/~bs/bs_faq2.html#final
Re: Features I think PureBasic really needs: lists, assertions
Exceptions without automatic cleanup will create leaks.
The reason is that during the unwind of the stack, you will inevitable unwind functions which were not written with exception handling in mind, and these will leak memory even if the rest of the code doesn't. The only ways to avoid that would be to either stick a try/catch/finally into every procedure which allocates a resource in your entire code, or make sure that any code within a try/catch block never calls a procedure that doesn't have one. Both of these are unpractical solutions, so in reality you will always end up with hidden leaks.
The reason is that during the unwind of the stack, you will inevitable unwind functions which were not written with exception handling in mind, and these will leak memory even if the rest of the code doesn't. The only ways to avoid that would be to either stick a try/catch/finally into every procedure which allocates a resource in your entire code, or make sure that any code within a try/catch block never calls a procedure that doesn't have one. Both of these are unpractical solutions, so in reality you will always end up with hidden leaks.
quidquid Latine dictum sit altum videtur
Re: Features I think PureBasic really needs: lists, assertions
In reality, as you say, my code is already like spaghetti where I need to ensure very robust error handling at every level of code. Despite having to surround any block that allocates resources the code will still be much, much cleaner. At least then I would only need to write code to cleanup a particular block at the end rather than several times for each possible error at every function call.
I'm not worried about having to test for leaks. That's what unit testing is for.
Errors need to be handled regardless. At least with exceptions I only need to do it once per block instead of a zillion times.
If I allocate memory ten times in a function I have to check each allocation separately and include a unique free several times. With exception handling I only need to do it once.
I'm not worried about having to test for leaks. That's what unit testing is for.
Errors need to be handled regardless. At least with exceptions I only need to do it once per block instead of a zillion times.
If I allocate memory ten times in a function I have to check each allocation separately and include a unique free several times. With exception handling I only need to do it once.
Re: Features I think PureBasic really needs: lists, assertions
You can use Apple-like goto based coding. Basically you have a cleaning block at the end of each functions and you use some macro to trigger the jump:
Code: Select all
Macro Try(Result, Expression, Name)
Result = Expression
If Result = 0
Goto ExitBlockLabel#Name
EndIf
EndMacro
Macro ExitBlock(Name)
ExitBlockLabel#Name:
EndMacro
Macro SafeFreeMemory(Memory)
If Memory
FreeMemory(Memory)
EndIf
EndMacro
Procedure Test()
Try(Block1, AllocateMemory(1000), Test)
Try(Block2, AllocateMemory(1000), Test)
Debug "Step 1"
Try(Block2, AllocateMemory(2000000000), Test) ; Too big size of x86
Debug "Not here"
Try(Block3, AllocateMemory(1000), Test)
; Other objects if you like to
OpenWindow(0, 0, 0, 100, 100, "Test")
ExitBlock(Test) ; Macro which define a procedure unique label
Debug "Cleaning..."
SafeFreeMemory(Block1) ; Null safe FreeMemory()
SafeFreeMemory(Block2)
SafeFreeMemory(Block3)
SafeFreeMemory(Block4)
If IsWindow(0)
CloseWindow(0)
EndIf
EndProcedure
Test()
Re: Features I think PureBasic really needs: lists, assertions
Your example still inherits the problems I highlighted in my other post on the necessity of function macros.
The example:
Cannot be used in expressions and does not alleviate the complexity of working without them.
I have to do something like this:
Instead of:
This is just a basic example. Because of differing return values and the additional functionality added on for per-library error handling, it becomes unruly and loses the simplicity of "Try()".
Even though this is only two more lines it's two lines per one small block. Expand this over a several thousand line library and you've got a lot of extra lines just for assignments. And the requirement to ensure unique variables as needed adds an additional headache.
And in response to the goto for cleanup, I would have to be able to goto back to resume operation after handling the error. And that's not always possible or feasible even with a macro. Not to mention it's a step in the wrong direction towards harboring spaghetti code.
The example:
Code: Select all
Macro Try(Result, Expression, Name)
Result = Expression
If Result = 0
Goto ExitBlockLabel#Name
EndIf
EndMacro
I have to do something like this:
Code: Select all
Try(Result1, Expression1)
Try(Result2, Expression2)
If Result1 = 1 And Result2 = 2
;/ Do something else
EndIf
Code: Select all
If Try(Expression1) = 2 And Try(Expression2) = 3
;/ Do something else
EndIf
Even though this is only two more lines it's two lines per one small block. Expand this over a several thousand line library and you've got a lot of extra lines just for assignments. And the requirement to ensure unique variables as needed adds an additional headache.
And in response to the goto for cleanup, I would have to be able to goto back to resume operation after handling the error. And that's not always possible or feasible even with a macro. Not to mention it's a step in the wrong direction towards harboring spaghetti code.
Re: Features I think PureBasic really needs: lists, assertions
> I'm not worried about having to test for leaks. That's what unit testing is for.
Sorry, but this is not just about you.
Adding a language feature which just screams for the creation of hidden bugs for everybody just so a few think they will write better code does not make much sense to me.
Sorry, but this is not just about you.
Adding a language feature which just screams for the creation of hidden bugs for everybody just so a few think they will write better code does not make much sense to me.
quidquid Latine dictum sit altum videtur
Re: Features I think PureBasic really needs: lists, assertions
It's not about me. It's about PureBasic.
Your statement to me was:
But I'll rephrase my statement to help clarify the point:
As long as you use assertions properly and remember to test your code then you shouldn't have any leaks. Or if you do, there they should be any more common than if you were to write code without assertions.
If you write unit tests as go it's a lot easier to test for that kind of thing.
Your statement to me was:
And I responded that it's true that I'm not worried about memory leaks.so in reality you will always end up with hidden leaks
But I'll rephrase my statement to help clarify the point:
As long as you use assertions properly and remember to test your code then you shouldn't have any leaks. Or if you do, there they should be any more common than if you were to write code without assertions.
If you write unit tests as go it's a lot easier to test for that kind of thing.
Re: Features I think PureBasic really needs: lists, assertions
Mistel, it's all very true, I found myself in your position writing projects probably a lot smaller than the ones you are referring to in your post. That's why I wrote in the past I like GOTOs and I use them. Because as in the example wrote by Fred using GOTOs to concentrate the cleanup at the end of the procedure is the only way to keep the needed error checking under control, in some way, and concentrate the cleaning in a single place.
You pointed out the shortcomings of this method, and I agree.
There is one more shortcoming IMHO. Using macros you tend to forgot you are really using GOTOs. You WANT to forgot that, it's the idea behind wrapping them out of your sight into something more "elegant" and easy to use.
But in some cases it's not safe to use gotos. For example if you try somenthing of that kind inside a select case, in case of error you jump out of the select - endselect and this construct in PB use not some kind of jump table but the stack (if I'm not mistaken).
So you will end up with the stack unbalanced.
Probably there are more scenarios like this. Would be nice to know by the way. I noticed the above looking at the code generated, but knowing it in advance would be nicer (from the helpfile, for example).
You pointed out the shortcomings of this method, and I agree.
There is one more shortcoming IMHO. Using macros you tend to forgot you are really using GOTOs. You WANT to forgot that, it's the idea behind wrapping them out of your sight into something more "elegant" and easy to use.
But in some cases it's not safe to use gotos. For example if you try somenthing of that kind inside a select case, in case of error you jump out of the select - endselect and this construct in PB use not some kind of jump table but the stack (if I'm not mistaken).
So you will end up with the stack unbalanced.
Probably there are more scenarios like this. Would be nice to know by the way. I noticed the above looking at the code generated, but knowing it in advance would be nicer (from the helpfile, for example).
"Have you tried turning it off and on again ?"
A little PureBasic review
A little PureBasic review
Re: Features I think PureBasic really needs: lists, assertions
Correct me if I'm wrong but a macro is a compile-time find and replace not a goto. 

Re: Features I think PureBasic really needs: lists, assertions
LOL! Maybe I'm not expressed myself in a clear manner...
When I said "Using macros you tend to forgot you are really using GOTOs" I was referring to the use of macros like the one proposed by Fred in his example:
and the rest follows from here ... 
When I said "Using macros you tend to forgot you are really using GOTOs" I was referring to the use of macros like the one proposed by Fred in his example:
Code: Select all
Macro Try(Result, Expression, Name)
Result = Expression
If Result = 0
Goto ExitBlockLabel#Name
EndIf
EndMacro

"Have you tried turning it off and on again ?"
A little PureBasic review
A little PureBasic review