Jump to content

Why isn't @error propagated across function calls ('Bubbled up' as it were)?


Recommended Posts

As the title says: The value of @error is not maintained after popping the stack a second time (returning from the function that called the function that set an error).

The documentation on SetError is not very clear on this, to the point of being ambiguous: It says that @error is reset when entering a function, but obviously not when leaving it. It only talks about backing it up in a While-WEnd  loop.

The problem is that you might want to write a set of functions which use a common function to do the work. You will then use these functions, and expect that an error raised in the core function be returned (2 levels up). This does not happen in practice.

This means that every such function you write must manually propagate @error by calling SetError.

Here is a script that demonstrates the problem:

;; Calling the main function directly sets @error as expected
_ErrorMaker()
ConsoleWrite("_ErrorMaker(): " & @error & @CRLF)

;; You would think by having a function calling our main function
;; we would still get the error. We don't.
_NaiveProxyFunc()
ConsoleWrite("_NaiveProxyFunc(): " & @error & @CRLF)

;; To make our point, look what happens inside such a function:
_NaiveProxyFuncBreakdown()
ConsoleWrite("After _NaiveProxyFuncBreakdown(): " & @error & @CRLF) ;; -> -99

;; We have to have a clever workaround to maintain the error.
;; Downside: Any proxying function must do this :-(
_WorldWiseProxyFunc()
ConsoleWrite("_WorldWiseProxyFunc(): " & @error & @CRLF)

;; If the world were perfect...
Func _NaiveProxyFunc()
    Return _ErrorMaker()
EndFunc

;; Let's take a closer look...
Func _NaiveProxyFuncBreakdown()
    $result = _ErrorMaker()
    ;; After calling the main function, the error is set...
    ConsoleWrite("Inside _NaiveProxyFuncBreakdown(): " & @error & @CRLF) ;; -> -99
    ;; Surely I don't have to set it again for the caller?
    Return $result
EndFunc

;; Good grief, what is the world coming to?
Func _WorldWiseProxyFunc()
    $result = _ErrorMaker()
    SetError(@error)
    Return $result
EndFunc

;; Our main function which we want to abstract, so naturally
;; we want errors to 'bubble up'
Func _ErrorMaker()
    SetError(-99)
    Return 22
EndFunc

And this is the output:

_ErrorMaker(): -99
_NaiveProxyFunc(): 0
Inside _NaiveProxyFuncBreakdown(): -99
After _NaiveProxyFuncBreakdown(): 0
_WorldWiseProxyFunc(): -99
Link to comment
Share on other sites

  • Moderators

mydoghasworms,

But what if there is an error in the Proxy function as well? Using your logic that would be hidden and surely you would want to know if that happened? :huh:

I would recommend returning SetError directly and using @extended to pass the additional information - like this: ;)

;; Calling the main function directly sets @error as expected
_ErrorMaker()
ConsoleWrite("_ErrorMaker(): " & @error & @CRLF)

;; You would think by having a function calling our main function
;; we would still get the error. We don't.
_NaiveProxyFunc()
ConsoleWrite("_NaiveProxyFunc(): " & @error & @CRLF)

;; To make our point, look what happens inside such a function:
_NaiveProxyFuncBreakdown()
ConsoleWrite("After _NaiveProxyFuncBreakdown(): " & @error & @CRLF) ;; -> -99

;; We have to have a clever workaround to maintain the error.
;; Downside: Any proxying function must do this :-(
_WorldWiseProxyFunc()
ConsoleWrite("_WorldWiseProxyFunc(): " & @error & @CRLF)

_HowToDoItProxyFunc() ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
ConsoleWrite("_HowToDoItProxyFunc(): " & @error & " : " & @extended & @CRLF)

;; If the world were perfect...
Func _NaiveProxyFunc()
    Return _ErrorMaker()
EndFunc   ;==>_NaiveProxyFunc

;; Let's take a closer look...
Func _NaiveProxyFuncBreakdown()
    $result = _ErrorMaker()
    ;; After calling the main function, the error is set...
    ConsoleWrite("Inside _NaiveProxyFuncBreakdown(): " & @error & @CRLF) ;; -> -99
    ;; Surely I don't have to set it again for the caller?
    Return $result
EndFunc   ;==>_NaiveProxyFuncBreakdown

;; Good grief, what is the world coming to?
Func _WorldWiseProxyFunc()
    $result = _ErrorMaker()
    SetError(@error)
    Return $result
EndFunc   ;==>_WorldWiseProxyFunc

Func _HowToDoItProxyFunc() ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    $result = _ErrorMaker()
    ; But we have an error in this function too!
    Local $iError = -37
    ; So let us return both error states using -1 as a flag
    Return SetError($iError, @error, -1)
EndFunc   ;==>_HowToDoItProxyFunc

;; Our main function which we want to abstract, so naturally
;; we want errors to 'bubble up'
Func _ErrorMaker()
    SetError(-99)
    Return 22
EndFunc   ;==>_ErrorMaker
Does that help? :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...