Problems with catch-throw

Started by Maurizio, March 13, 2006, 12:34:51 AM

Previous topic - Next topic

Maurizio

Seems that "catch" leads to unexpected results:

in the following example the 'if' always succeed,

both with the throw statement commented or not commented.

Moreover, the doc seems misleading.



In a paragraph is written :
Quote
If an error occurs during evaluation, catch returns nil and stores the error message in symbol.

Few lines under is written :
Quote
When a throw is executed during the evaluation of expr catch will return true and the throw argument will be stored in symbol

I'm working with vers 8.8.1, on Windows 2000.



Regards

Maurizio






(define (start)
  (if (catch (do-work) 'errormsg)
    (println "error occurred " errormsg)
    (println "all goes well " errormsg)))
 
(define (do-work)
  ;; (throw "this is an error")
  (println "i'm working"))
   
   
(start)  
(exit)

Maurizio

#1
Any suggestion about this problem ?

Regards

Maurizio

pjot

#2
Hi Maurizio,



Actually I do not see the problem. Let's look at the situation:



#!/usr/bin/newlisp

(define (start)
  (if (catch (do-work) 'errormsg)
    (println "error occurred " errormsg)
    (println "all goes well " errormsg)
)
)
 
(define (do-work)
  ;; (throw "this is an error")
  (println "i'm working"))

(start)  
(exit)


Now the output of this is:


Quote
i'm working

error occurred i'm working


This seems OK to me. The 'if' is executed, which prints the first line "i'm working", and the catch returns 'true', because there was no error. Therefore, the line "error occured" is printed because this is in the true part of the if-statement. As the (do-work) is evaluated, which is "i'm working", this is printed again right after the "error occured" since it is in the symbol 'errormsg, which contains the result of the evaluation.





When you enable the 'throw', the result is:
Quote
error occurred this is an error


This is completely correct. The throw really throws you out of the function (do-work) but returns 'true', therefore the first part of the 'if' is executed again, together with the evaluation of (do-work), which, in this case, is the output of 'throw'.



The documentation is correct and it seems to be working as expected. There is no misleading at all. The text you refer to relates to an evaluation which has an error. But there is no error in your example. Hence the 'catch' always returns true, also with 'throw'.



Peter

Maurizio

#3
So you mean that catch always returns the value of :



If there is no throw:

   the value of the function evaluated

If there is a throw:

  the value throwed by such a call.



I supposed it returned nil in the second case.



So If I need to differentiate the two cases I must follow one of the following strategies :

a) always return nil from a successfull execution of a function

and throw a meaningful error code in case of error.

b) always return something different from nil from a successfull execution of a function, and throw nil in case of error



I suppose strategy A is the best.



In general (in other languages) I'm accustomed to the use  of catch/throw when I have to check user input.

Generally my pattern is the following (pseudo-code) :



(define (do-checks)
  (set 'value1 (get-a-number-from-input-form 'field1))
  (set 'value2 (get-a-number-from-input-form 'field2))
  (if (< value2 value1) (throw (list "value 2 must be greater or equal to value1" 'field2)))
  (set 'value3 (get-a-number-from-input-form 'field3))
  (set 'value4 (get-a-date-from-input-form 'field4))
  ---
  (save-data-somewhere value1 value2 value3 value4))

(if (catch (do-checks) error)
    (show-the-error-to-user error))


The various get-a-xxx-from-input-form checks the formal validity

of the fields, perhaps calling subprocedures that can throw errors,

and they throws an error if something is invalid, with an indication

to what field was wrong, in order to set the cursor, if possible to such a field.

Additional checks are made in the do-checks routine.

To use such a pattern I need to differentiate the outcome of the

catch function.



Thanks for your answer,

Maurizio.

Lutz

#4
Rmember that their are two forms of 'catch' one with the additional result symbol parameter the other one without, and there are also two kinds or throwing: 'throw' and 'throw-error':



(catch (foo x y z) 'result)  ;  type (A)

(catch (foo x y z))          ; type (B)


type (A) returns 'nil' or 'true' depending if an error occured  or 'throw-error' was used or not. The good result or errror message or 'throw-error' parameter is in 'result.



type (B) returns the result of (foo x y z) or of a 'throw', gives an error exception on error or throw-error.



The point is: you must distinguish between 2 forms of 'catch' and 2 types of 'throw/throw-error'



Lutz

Maurizio

#5
Thanks, I'm going to study them more carefully.

Maurizio