Page 1 of 3

ProcedureReturn statement...

Posted: Sun Oct 27, 2019 4:00 pm
by Dudemeister
Greetings to All...

I am new to PureBasic, coming from VBA and VB.NET (please don't hold this against me).

I have an initial question about the execution flow of procedure and function routines. In VBA, it is considered best practice to always terminate a procedure with the statement 'Exit Sub', and to terminate a function with the statement 'Exit Function', as demonstrated below:

Private Function MyProcedure(ByVal SomeParam) As SomeDatatype
OnError Goto ErrHndlr

Do something cool here...

MyProcedure = SomeValue

Exit Function (Exit Sub for procedure)

ErrHndlr:
Handle error here
End Function

The reason for doing this is because in VBA/VB/VB.NET, any routine which contains an error handling label (or any label, actually) following the regular code block, the code in the label gets executed, regardless of whether an error occurs. So, strategically placing the 'Exit Sub' or 'Exit Function' somewhere in the regular code block is considered "best practice" in order to prevent the error handling label from executing when no error is raised. Keep in mind that VBA/VB/VB.NET routines always raise an error value no matter what. They raise an error code of zero (0) for successful execution.

So, this brings me to my two related questions here:
1.) Do PureBasic routines always raise an error value, even upon successful execution, the way some other programming languages do?
2.) Is using 'ProcedureReturn' in every routine considered best practice?
3.) If the answer to number two is yes, implementing 'ProcedureReturn SomeValue' works for functions (routines that return values), but what do we use for procedures that do not return values?

Thanks!

Re: ProceureReturn statement...

Posted: Sun Oct 27, 2019 4:12 pm
by Bitblazer
Dudemeister wrote:Greetings to All...

I am new to PureBasic, coming from VBA and VB.NET (please don't hold this against me).
Welcome to PureBasic!
Dudemeister wrote:1.) Do PureBasic routines always raise an error value, even upon successful execution, the way some other programming languages do?
No.
Dudemeister wrote:2.) Is using 'ProcedureReturn' in every routine considered best practice?
I dont do it as i think its pointless. If you call a function which doesnt return a value, but you use a return value anyway, i guess you would technically read some "random" register value from EAX/RAX.

But that would be your bug ;)
Dudemeister wrote:3.) If the answer to number two is yes, implementing 'ProcedureReturn SomeValue' works for functions (routines that return values), but what do we use for procedures that do not return values?
ProcedureReturn

But i dont write a ProcedureReturn without a value as i try to keep my sources as lean and clean as possible. I guess most others dont do that either.

Code: Select all

Procedure HelloWorld()
  Debug "hello world"
EndProcedure

  HelloWorld()
Thats enough for me :)

ps: there are only Procedures in PureBasic, a Procedure with a return value would work like a classic "function". But a return value for procedures is optional.

Re: ProceureReturn statement...

Posted: Sun Oct 27, 2019 4:15 pm
by wombats
You only need to use ProcedureReturn if the procedure is actually returning something. If so, the procedure should specify a return type after the Procedure keyword. By default, procedures will return integers.

Code: Select all

Procedure.i returnInt()
  ProcedureReturn 5
EndProcedure

Procedure.s returnStr()
  ProcedureReturn "Hello World"
EndProcedure

Procedure myFunc() ; No type specified, so will return integer
  ProcedureReturn 5.5 ; Will return 6
EndProcedure

Re: ProceureReturn statement...

Posted: Sun Oct 27, 2019 4:33 pm
by mk-soft
Welcome first.

First of all there is no error counter at Purebasic.
What the procedure returns is up to you.

There is no difference in procedures that run as sub or function.

As a sub the procedure is simply terminated with EndProcedure.
As a function the procedure will leave with ProcedureReturn. So there can be several ProcedureReturns in the procedure.

Code: Select all

;-TOP

EnableExplicit

Procedure MySub(sVal.s, iVal.i)
  Protected result.s
  result = sVal + " = " + iVal
  Debug result
EndProcedure

Procedure.f MyFunction(fltVal1.f, fltVal2.f) ; Result as Integer)
  If fltVal2 = 0.0
    ProcedureReturn NaN()
  Else
    ProcedureReturn fltVal1 / fltVal2
  EndIf
EndProcedure

MySub("Value" , 123)

Debug MyFunction(256.0, 16.0)
Debug MyFunction(16.0, 0.0)

Parameters are passed as ByVal by default. But you can pass parameters as ByRef. To do this, pass the pointer to the variable again.

Code: Select all

Procedure.i MyFunction2(*Result.float, fltVal1.f, fltVal2.f) ; Result State ; *Result need Pointer to variable
  If fltVal2 = 0.0
    ProcedureReturn #False
  Else
    *Result\f = fltVal1 / fltVal2
    ProcedureReturn #True
  EndIf
EndProcedure

Define result.f

; @[variable] get the adress from variable

If MyFunction2(@result, 256, 16)
  Debug "Result = " + StrF(result, 2)
Else
  Debug "Error"
EndIf

If MyFunction2(@result, 16, 0)
  Debug "Result = " + StrF(result, 2)
Else
  Debug "Error"
EndIf

Re: ProceureReturn statement...

Posted: Sun Oct 27, 2019 5:37 pm
by Dudemeister
After some thorough testing, here is what I found...

1.) All executed statements in a procedure raise an error code. The error code raise by successful execution is -1 (it is 0 in VBA/VB).
So, when I say that "... no actual error occurs.", I mean when a statement raised -1 error code rather than any other number.

2.) All procedures return a value, regardless of whether they are specified to do so. If the procedure is specified to return a value, it returns whatever value is specified as part of the 'ProcedureReturn SomeValue' statement. If no 'ProcedureReturn SomeValue' statement is used and no datatype is specified in the procedure's declaration, the procedure returns a default integer value of zero (0). This can be handy information to know in some circumstances.

So, this helps me make the decision to use 'ProcedureReturn SomeValue' to terminate procedures that return values, and to use 'ProcedureReturn' to terminate procedures that are not meant to return a value (other than the default 0). The reason for this is to prevent the error handling label (ErrHndlr:) from executing when no actual error occurs.


Procedure MyProcedure(SomeParam)
    OnErrorGoto (?ErrHndlr)

    - Put some cool code here -

    ProcedureReturn ;Use return statement without value here to prevent the ErrHndlr label below from executing

ErrHndlr:
    - Put error handler code here -
EndProcedure


Otherwise, the other (less desriable) option is the following -


Procedure MyProcedure(SomeParam)
    OnErrorGoto (?ErrHndlr)

    - Put some cool code here -

ErrHndlr:
    If ErrorCode() <> -1 ;If any error other than successful execution occurs
        - Put error handler code here -
    EndIf
EndProcedure

Re: ProceureReturn statement...

Posted: Sun Oct 27, 2019 5:53 pm
by mk-soft
No,
ProcedureReturn without value is undefined... Its alway the 'rax' register!

Code: Select all

Procedure Dummy()
  ProcedureReturn 100
EndProcedure

Procedure foo()
  Dummy()
  ProcedureReturn
EndProcedure

Procedure foo2()
  Protected a
  a = 200
  !mov rax, qword[p.v_a]
  ProcedureReturn
EndProcedure

r1 = foo()
Debug r1
r1 = foo2()
Debug r1
The Purebasic ErrorHandle is to be used only for serious errors. After an error the program cannot be continued with all errors.
Show Purebasic Help "OnError"

It is your own task to catch errors.
That means:
- Could the file be opened.
- Could the file be saved.
- Could the memory be created.
- etc

For all these checks, the Purebasic functions always give a result. Error Library is not responsible for this.

Code: Select all

#Failed = 0

Procedure MyOpenFile(FileName.s)
  
  If ReadFile(0, FileName) = #Failed
    Debug "Error: Open file to read!"
    ProcedureReturn #False
  Else
    ;TODO
    Debug "Ok: Open file to read!"
    CloseFile(0)
    ProcedureReturn #True
  EndIf
EndProcedure

If MyOpenFile("text.txt")
  Debug "Ok"
Else
  Debug "Failed"
EndIf

Re: ProceureReturn statement...

Posted: Sun Oct 27, 2019 7:05 pm
by Little John
mk-soft wrote:The Purebasic ErrorHandle is to be used only for serious errors. After an error the program cannot be continued with all errors.
Show Purebasic Help "OnError"

It is your own task to catch errors.
That means:
- Could the file be opened.
- Could the file be saved.
- Could the memory be created.
- etc

For all these checks, the Purebasic functions always give a result. Error Library is not responsible for this.
I want to emphasize this!
When I think of what I've read here from some new PureBasic users in the past, maybe they should print this advice on a sheet of paper and hang it over their bed. :-)

Re: ProceureReturn statement...

Posted: Mon Oct 28, 2019 12:11 am
by Dudemeister
"The Purebasic ErrorHandle is to be used only for serious errors. After an error the program cannot be continued with all errors."

If this is the case, I wouldn't have a problem with this if PureBasic were open source. However, since it (PureBasic) is advertised as a commercial product on which people spend their money, wouldn't it be a good idea to put this important bit of information front and center on PB's web page before people waste their money purchasing it? I ask because error handling is kind of a necessity in most commercial applications one might want to produce with PureBasic. I wouldn't trust any data-critical program that has been written without extensive error handling. So, I guess I will just have to consider PB a hobby language and continue relying on other languages for my commercial apps.

Re: ProceureReturn statement...

Posted: Mon Oct 28, 2019 12:41 am
by Little John
Dudemeister wrote:"The Purebasic ErrorHandle is to be used only for serious errors. After an error the program cannot be continued with all errors."
This is just one sentence of mk-soft's message that has been taken out of context. Reading his whole post, you'll see that there actually is error handling in PureBasic.
Dudemeister wrote:I am new to PureBasic, coming from VBA and VB.NET (please don't hold this against me).
And you shouldn't hold against PureBasic that it is a language in its own rights. If you prefer coding in VB style, you probably should use VB.

Re: ProceureReturn statement...

Posted: Mon Oct 28, 2019 1:32 am
by mk-soft
I also use Purebasic commercially.
Even in automation where high reliability is required. Here, for example, some services are running that collect data or pass it on. These run continuously on various servers without interruption.

Re: ProceureReturn statement...

Posted: Mon Oct 28, 2019 1:54 am
by BarryG
Dudemeister wrote:since it (PureBasic) is advertised as a commercial product on which people spend their money, wouldn't it be a good idea to put this important bit of information front and center on PB's web page before people waste their money purchasing it? I ask because error handling is kind of a necessity in most commercial applications one might want to produce with PureBasic. I wouldn't trust any data-critical program that has been written without extensive error handling. So, I guess I will just have to consider PB a hobby language and continue relying on other languages for my commercial apps.
Wasting money: why didn't you try the demo version (and/or RTFM) first? That's what the demo and manual is for. You can't blame the website for you not doing your homework.

PureBasic does have extensive error-handling (commands that can fail will return 0 when called), plus the main error handler: you, the developer. You surely not expecting the compiler to handle an error about reading a file when the file doesn't exist, right? Maybe VBA does that, but PureBasic doesn't hold your hand, and assumes you know what you're doing and that you're testing the return values of calls. That is, you as the responsible developer should always be checking first that the file actually exists, and can be opened for reading ("If ReadFile()=0" means it failed, instead of VBA's way of just jumping around to a generic feel-good error handler like the spaghetti code it is). You need to be testing the return values (and not blindly relying on "OnError Goto ErrHndlr" that you posted), so I can trust you with my critical data.

BTW, PureBasic is not a hobby language. It holds its own against other Basics quite well. It's closest competitor was PowerBasic (definitely not a hobby language either!) but PowerBasic is now dead. Plus, there's posts in these forums where people make a commercial living from their PureBasic apps, bought houses from it, and even a millionaire from using it. Myself: one of my commercial PureBasic apps was even published (reviewed) in print in a computer magazine a couple of years ago. Class that as a hobby if you like, but we all know the reality.

Re: ProceureReturn statement...

Posted: Mon Oct 28, 2019 2:18 am
by Dudemeister
@BarryG

"That is, you as the responsible developer should always be checking first that the file actually exists, and can be opened for reading ("If ReadFile()=0" means it failed, instead of VBA's way of just jumping around to a generic feel-good error handler like the spaghetti code it is). If you're not doing that (as appears by your "OnError Goto ErrHndlr" line), then you're just a hobby coder who I wouldn't trust my critical data with."

What you are describing here, we call exception handling in my part of the world. Exceptions are errors which are not system generated and which can be foreseen. ie; a file not existing, invalid parameters getting passed to a routine, etc. These things I do check for and, despite your uncontrolled emotional flatulence here, there is no "spaghetti code" in my applications.

I can handle exceptions quite well, thank you. I am merely concerned with, and reasonably so, a PB app wanting to exit following an unforeseen critical run-time error. If the way PB handles critical errors works for you gentlemen, then I say good for you. I'll buy you a drink. However, when I mention that it doesn't work for what I need, this is no reason for you to get all emotional and issue childish replies.

Re: ProceureReturn statement...

Posted: Mon Oct 28, 2019 2:30 am
by BarryG
Hi Dudemeister, yes, I got emotional and I apologize. I also edited my post to not directly insult you anymore (but you quoted it before my edit was submitted). My edited post was to show I regret the name-calling.

Re: ProceureReturn statement...

Posted: Mon Oct 28, 2019 2:55 am
by Dudemeister
Utilizing the 'OnErrorGoto' command along with the error handling label (ErrHndlr:) is well established as best practice structured programming in the BASIC languages when being used to trap unexpected critical run-time errors. It is not spaghetti code.

It is not used to trap exception (foreseen) type errors. Exceptions are tested for and trapped in the regular code block, such as testing if a specified file exists, or if a value acquired from an INI file is valid, etc.

Example:

Procedure MyProc(MyParameter.s)
    OnErrorGoto (?ErrHndlr) ;This is used to trap unexpected/critical errors - not for trapping exceptions (expected errors)

    If MyParameter <> "" ;If the file name parameter contains valid data
        If FileExists(MyParameter) ;If the specified file exists
            ;Do something cool with the file.
        Else ;If the specified file does not exist
            ;This is an exception type error, not a critical error - notify User the file does not exist and allow him/her to decide what to do.
        EndIf
    Else ;If the file name parameter does not contain valid data
        ;This is also an exception type error, not a critical error - notify User about invalid parameter and allow him/her to decide what to do.
    EndIf

ErrHndlr:
    ;Handle critical/unexpected errors here. Non-critical expected errors (exceptions) are handled in regular code block above - not here.
EndProcedure

Re: ProceureReturn statement...

Posted: Mon Oct 28, 2019 3:01 am
by skywalk
Dudemeister, you sound a lot like

Will you be asking to delete your forum account now that you determined PB unworthy of your investment :?:
Yes, I use PureBasic for complex control systems and the usual database apps.
I come upon many, many errors and log them.
My crashes are seldom, but a few recent ones were from power outages or referencing a map element that does not exist.