Among the CPU exceptions are "invalid opcode" exceptions which can happen if there is a bug in the compiler one is using, not in the program.
Or using the program on a different CPU that lacks the "invalid opcode"?
Also, these days, programmers are raising exceptions because they buried themselves in a pile of function/procedure calls and the only way they have left to inform the original caller something went wrong is by raising an exception (extremely poor programming!.)
Keeping all the code in one function and returning false or any value to indicate the exact error is not much different. Taking either extreme is simply poor programming practice, and does not help readability nor prevents bugs.
Using enough functions that return error codes, or objects that raise exceptions carrying error codes and messages, both are simply two styles of programming. You can abuse either one.
I see exceptions on top of exceptions.
I see lots of those in OOP programs.
You should, it is just a style of programming.
apart from small samples, programs are always dealing with resources they do not own,
By resources they don't own, I mean resources whose existence they cannot predict. For instance, if a program is attempting to read memory that is in another process (or the same process but, is not managed by the program), the program cannot make any assumptions as to the presence of memory at a particular address. That said, that example with memory is not very good since using Read/WriteProcessMemory eliminates the need for an exception handler. The basic rule is, when the proper operation of a set of instructions cannot be predicted then, exceptions are warranted,
It is hard to imagine an applications that does not deal with the internet, json, networks, databases, acquired data from wired/wireless sources like images or ... etc.
otherwise the programmer should write clean code, which means do all the necessary checking before carrying out the function.
This applies when using OOP or not.
or depend on libraries that do use exceptions.
That's defines the typical case: a poorly written library spreads its poor design to the program that wants to use it. Apparently, it's too much work these days to return an indication of failure or success as a function result. Using exceptions makes a programmer look "kewl" and knowledgeable. Function results ?... way too prosaic these days.
I hear you, you prefer to use a library and with each call to check the result: Initialize the library, check. A call, a check. Another call, another check, repeat... , finalize the library, then check.
You don't like to include all of that in one block and leave the checking to the library itself? It would keep your code focused on its own part. But again, this sounds like your own style of programming, I have nothing against it. I can imagine how
if thisVar=someErrorValue then grows in your code.
I want to let you know that JAVA does have exceptions and you have to catch them, and, unfortunately, FPC can produce JAVA classes, run on JVMs, and interact with other JAVA classes.
Exceptions are just a tool. Like any tool, they need to be used right.
I agree with that. These days they are grossly abused and misused.
Anything could be abused of misused, does not mean we need to avoid it, or consider it poor practice.
While this usage is the common one, it is not the only reason. You can use try/finally to signal the end of a process, or change the status, or anything else that you want to make sure is done at the end of a try finally block.
You're right, it's not the only reason. That was just an example and I picked something quite common for it. I can write much simpler, easier to understand and follow code without using try/finally.
Yes, until you are forced.
Wait, this example is supposed to show how you do not need try/finally?
That's one example. I'd much rather code it like that than use a try/finally construct. It is a lot cleaner. No nested try/finally and when debugging, the execution doesn't jump around into some finally(ies) if something didn't go as expected.
The debugger, when enough debugging data is available, is supposed to show you exactly where the exception had happened before it takes you anywhere else. But if you don't like try/finally for that reason, then you do not like
else either because it jump somewhere far from the line the debugger was on.
You used a for loop to create a scope so you can use break?
Yes, unfortunately. There are no scopes in Pascal. That is not as clean as I'd like it to be but, it's still way better than try/finally(ies.)
It is not clean, and not supported by Pascal, but you used it. While Try/Finally is part of the language, the object oriented dialect, and you refuse to use it?
You want to use break but avoid try/finally?
That's only one of the reasons. Another reason is that, that way, all the resource deallocation is in _one_ place, not scattered all over. In more complex functions, that makes a very noticeable difference, particularly when debugging (the debugger isn't jumping around from one finally to another.)
"Scattered" or not, if deallocation happens in a logical and correct way, and always guaranteed there is no problem. The desire to have all the deallocations in one place came with extra price, at least, the chain of
IF THEN. Again, a style of programming.
You avoided using objects in your function. You do realize that you can achieve the same goal using objects, specially when this function get complicated, right?
I strongly believe that ANYTHING that can be written using objects can be written in a clearer, simpler, easier to maintain and more efficient way without objects. If there is an exception to that, I am yet to see it.
Yes, a call to member function of an object like AStringList.Add is actually a call to a function with the first parameter is the object itself: Add(AStringList,... see?
It is like adjectives are before/after the nouns in different languages:
English (Brown Horse)
Spanish (Horse Brown)
Which one do you prefer?
That said, if you'd like to rewrite that function using objects and point out the reasons why yours is better than the one I posted, I would be very pleased to see it.
I might give it a shot, not sure.
if(s) and try/finally are very poor solutions to releasing resources. A little bit of structuring (with a scope) makes the function fully linear with a minimum amount of nesting (usually, 1 nesting level : the scope)
Can you show how you do that with the function you showed above?
Why do you want to keep nesting at minimum?
The function already uses a scope (unfortunately, with trickery since there is no support for it in the language.) The reason I keep nesting at a minimum is because the lower the level of nesting the easier a construction is to understand.
When the level of nesting grows, it is time to consider another function/member function.
Now I believe that you have your own style of programming and refuse to change it, not because it protects you from bugs, but simply because you do not want to try something new. Nothing unusual here, but considering other ways as poor or more prone to bugs is not accurate.