Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Help me, Obi Reb Kenobi, you're my only hope!

 [1/34] from: edanaii::cox::net at: 27-Aug-2002 19:51


OK, so what's going on here. I'm trying to put a little error handling around my application. If it fails, I need it to send out an alarm. But, depending on the statement, I get an error when trying to trap the error. For example, this works as expected:
>> If Error? Fred: Try [ 1 / 0 ] [ Print "Whatever!" ]
Whatever! As does this:
>> If Error? Fred: Try [ 1 / 1 ] [ Print "Whatever!" ]
== none This too:
>> If Error? Fred: Try [ Print ] [ Print "Whatever!" ]
Whatever! But this doesn't:
>> If Error? Fred: Try [ Print "Get a grip!" ] [ Print "Whatever!" ]
Get a grip! ** Script Error: Fred needs a value ** Near: If Error? Fred: Try [Print "Get a grip!"] This is confusing because why should I get an error on something that doesn't and shouldn't cause an error. This works, of course:
>> If Error? Fred: Try [ x: 1 ] [ Print "Whatever!" ]
== none And this:
>> If Error? Fred: Try [ x: 1 / 0 ] [ Print "Whatever!" ]
Whatever! And so do these:
>> If Error? Fred: Try [ Do [ 1 / 0 ] ] [ Print "Whatever!" ]
Whatever!
>> If Error? Fred: Try [ Do [ 1 / 1 ] ] [ Print "Whatever!" ]
== none What's perplexing about the previous two is that it is a "Do" statement that I am trying to execute and trap. Instead of functioning as above, it blows up and gives me the "needs a value error". And curiously, not only does Print fail, but so does Write. And that is a function that I need error trapping on, if ever there was one.
>> If Error? Fred: Try [ Write %Temp.txt "Yup!" ] [ Print "Whatever!" ]
** Script Error: Fred needs a value ** Near: If Error? Fred: Try [Write %Temp.txt "Yup!"] I've even tried disarming the error, but to no avail:
>> If Error? Fred: Try [ Write %Temp.txt "Yup!" ] [ Print "Whatever!" ] Disarm Fred
** Script Error: Fred needs a value ** Near: If Error? Fred: Try [Write %Temp.txt "Yup!"] So what gives? Is this some subtle intricacy of the language, a bug, or my normal state of confusion? -- Sincerely, | Mud can make you prisoner, and the plains can bake Ed Dana | you dry. Snow can burn your eyes, but only people Software Developer | make you cry. 1Ghz Athlon Amiga | -- Lee Marvin, Paint Your Wagon. =========== http://OurWorld.CompuServe.com/Homepages/EDanaII ===========

 [2/34] from: al:bri:xtra at: 28-Aug-2002 17:11


> And curiously, not only does Print fail, but so does Write. And that is
a function that I need error trapping on, if ever there was one.
>> type? try [print "The Force will be with you; always."]
The Force will be with you; always. == unset!
>> type? try [write %Force.txt "The Force will be with you; always."]
== unset! Both 'print and 'write return a unset! value, which can't be "assigned" as a value to 'Fred, by the set-word "Fred:". Perhaps 'attempt from the latest Rebol/Core might be more useful to you:
>> source attempt
attempt: func [ {Tries to evaluate and returns result or NONE on error.} value ][ if not error? set/any 'value try :value [get/any 'value] ] I hope that helps! Andrew Martin Rebol Superhero! :) ICQ: 26227169 http://valley.150m.com/

 [3/34] from: carl:cybercraft at: 28-Aug-2002 17:49


Hee - wasted time on this myself today! The problem is that 'print doesn't return a value when 'Fred is expecting one...
>> Fred: print "What's wrong with this?"
What's wrong with this? ** Script Error: Fred needs a value ** Near: Fred: print "What's wrong with this?" and it's not trapped by your error routine as 'Fred is outside the block that's being 'try'ed. Place 'Fred inside it and you'll trap the error...
>> If Error? try [Fred: Print "See?"][Print "Whatever!"]
See? Whatever! It's possible to write a function that'll check for nothing returned, as the any-type! datatype will accept nothing. ie... nothing-check: func [value [any-type!]][ either value? 'value [join "that was: " value]['nothing...] ]
>> nothing-check "abc"
== "that was: abc"
>> nothing-check print "abc"
abc == nothing...
>> nothing-check join "abc" "xyz"
== "that was: abcxyz"
>> nothing-check
== nothing... HTH! Carl. PS: And 'focus in VID returns nothing too. (; On 28-Aug-02, Ed Dana wrote:
> OK, so what's going on here. > I'm trying to put a little error handling around my application. If
<<quoted lines omitted: 43>>
> So what gives? Is this some subtle intricacy of the language, a bug, > or my normal state of confusion?
-- Carl Read

 [4/34] from: lmecir:mbox:vol:cz at: 28-Aug-2002 9:02


Hi Ed, Rebforce can easily help you. Try these: If Error? set/any 'Fred Try [ Print "Get a grip!" ] [ Print Whatever! ] If Error? set/any 'Fred Try [ Write %Temp.txt "Yup!" ] [ Print Whatever! ] We might call it "a subtle intricacy of the language". This is a feature, that deserves a lengthy discussion. I would prefer a different behaviour instead, but the above solution works... The whole trouble is caused by a situation similar to this: a: () , while this works: set/any 'a () Cheers -L ----- Original Message ----- From: "Ed Dana" <[EDanaII--Cox--net]> To: "REBOL List" <[rebol-list--rebol--com]> Sent: Wednesday, August 28, 2002 4:51 AM Subject: [REBOL] Help me, Obi Reb Kenobi, you're my only hope! OK, so what's going on here. I'm trying to put a little error handling around my application. If it fails, I need it to send out an alarm. But, depending on the statement, I get an error when trying to trap the error. For example, this works as expected:
>> If Error? Fred: Try [ 1 / 0 ] [ Print "Whatever!" ]
Whatever! As does this:
>> If Error? Fred: Try [ 1 / 1 ] [ Print "Whatever!" ]
== none This too:
>> If Error? Fred: Try [ Print ] [ Print "Whatever!" ]
Whatever! But this doesn't:
>> If Error? Fred: Try [ Print "Get a grip!" ] [ Print "Whatever!" ]
Get a grip! ** Script Error: Fred needs a value ** Near: If Error? Fred: Try [Print "Get a grip!"] This is confusing because why should I get an error on something that doesn't and shouldn't cause an error. This works, of course:
>> If Error? Fred: Try [ x: 1 ] [ Print "Whatever!" ]
== none And this:
>> If Error? Fred: Try [ x: 1 / 0 ] [ Print "Whatever!" ]
Whatever! And so do these:
>> If Error? Fred: Try [ Do [ 1 / 0 ] ] [ Print "Whatever!" ]
Whatever!
>> If Error? Fred: Try [ Do [ 1 / 1 ] ] [ Print "Whatever!" ]
== none What's perplexing about the previous two is that it is a "Do" statement that I am trying to execute and trap. Instead of functioning as above, it blows up and gives me the "needs a value error". And curiously, not only does Print fail, but so does Write. And that is a function that I need error trapping on, if ever there was one.
>> If Error? Fred: Try [ Write %Temp.txt "Yup!" ] [ Print "Whatever!" ]
** Script Error: Fred needs a value ** Near: If Error? Fred: Try [Write %Temp.txt "Yup!"] I've even tried disarming the error, but to no avail:
>> If Error? Fred: Try [ Write %Temp.txt "Yup!" ] [ Print "Whatever!" ]
Disarm Fred ** Script Error: Fred needs a value ** Near: If Error? Fred: Try [Write %Temp.txt "Yup!"] So what gives? Is this some subtle intricacy of the language, a bug, or my normal state of confusion? -- Sincerely, | Mud can make you prisoner, and the plains can bake Ed Dana | you dry. Snow can burn your eyes, but only people Software Developer | make you cry. 1Ghz Athlon Amiga | -- Lee Marvin, Paint Your Wagon. =========== http://OurWorld.CompuServe.com/Homepages/EDanaII ===========

 [5/34] from: jason:cunliffe:verizon at: 28-Aug-2002 2:12


hmmm.. I also be glad if someone can explain this issue well
>> Fred: Try ["hello"]
== "hello"
>> fred
== "hello"
>> Fred: Try [print "hello"]
hello ** Script Error: Fred needs a value ** Near: Fred: Try [print "hello"]
>> >> ? try
USAGE: TRY block DESCRIPTION: Tries to DO a block and returns its value or an error. TRY is a native value. ARGUMENTS: block -- (Type: block)
>> do [print "hello"]
hello
>> fred: do [print "hello"]
hello ** Script Error: fred needs a value ** Near: fred: do [print "hello"]
>> fred: do ["hello"]
== "hello"
>>
Looks like REBOL is being very consistent. So RebGurus, how do you interpret "returns its value" in this context? Which Rebol statements have value? thanks ./Jason

 [6/34] from: louisaturk:coxinet at: 28-Aug-2002 0:51


Hi Ed, My ISP's mail server went done last night, and I was thus unable to send this. Someone else has probably already helped you by now, but I'll send this anyway. At 07:51 PM 8/27/2002 -0700, you wrote:
>OK, so what's going on here. >I'm trying to put a little error handling around my application. If it
<<quoted lines omitted: 16>>
>This is confusing because why should I get an error on something that >doesn't and shouldn't cause an error.
Try returns either a value or error message from the block it evaluates. print because it lacks an argument returns an error message, which try passes on to Fred. print ["Get a grip!"] outputs a value to the console (thus fooling you), but actually _returns_ nothing (not even an error message, since there is no error); so try in turn is unable to put a value into Fred. Rebol therefore cannot proceed past Fred. After each of your lines type fred to see what fred now contains. Enable try to actually return something and see what happens:
>> If Error? Try [Fred: "Get a grip!" ] [ Print "Whatever!" ]
== none
>> fred
== "Get a grip!"
>>
At the console type help <function-name> If it doesn't say that the function returns something, then it probably doesn't. hth, Louis

 [7/34] from: lmecir:mbox:vol:cz at: 28-Aug-2002 17:37


Hi Jason, even Rebol expressions such as: try [print "hello"] or do [print "hello"] or () yield a Rebol value, which, is of type UNSET!. Check: type? try [print "hello"] ; == unset! or probe head insert [] try [print "hello"] ; == [unset] etc. The only trouble with a value of that type is, that you cannot use it in an expression like: a: () , which fires an error. OTOH, you can use UNSET! type value like this: set/any 'a () probe head insert [] () ; == [unset] type? () ; == unset! error? () ; == false unset? () ; == true etc. Generally spoken, if your expression can yield an UNSET! type value, you have to use (set/any 'a ...) instead of (a: ...). The trouble with this approach is, that in the former case you lose the typo protection you normally have. If no Rebol expression was allowed to yield an UNSET! type value, this "problem" wouldn't exist. ----- Original Message ----- From: "Jason Cunliffe" <[jason--cunliffe--verizon--net]> To: <[rebol-list--rebol--com]> Sent: Wednesday, August 28, 2002 8:12 AM Subject: [REBOL] Re: Help me, Obi Reb Kenobi, you're my only hope! hmmm.. I also be glad if someone can explain this issue well
>> Fred: Try ["hello"]
== "hello"
>> fred
== "hello"
>> Fred: Try [print "hello"]
hello ** Script Error: Fred needs a value ** Near: Fred: Try [print "hello"]
>> >> ? try
USAGE: TRY block DESCRIPTION: Tries to DO a block and returns its value or an error. TRY is a native value. ARGUMENTS: block -- (Type: block)
>> do [print "hello"]
hello
>> fred: do [print "hello"]
hello ** Script Error: fred needs a value ** Near: fred: do [print "hello"]
>> fred: do ["hello"]
== "hello"
>>
Looks like REBOL is being very consistent. So RebGurus, how do you interpret "returns its value" in this context? Which Rebol statements have value? thanks ./Jason

 [8/34] from: edanaii:cox at: 28-Aug-2002 18:33


Carl Read wrote:
>Hee - wasted time on this myself today! >The problem is that 'print doesn't return a value when 'Fred is
<<quoted lines omitted: 11>>
>See? >Whatever!
Yes. But the value that I was trying to assign Fred was the error that was to occur when I attempted my action. More accurately, I have written a couple of daemons, that execute a command that I pass to it as a parameter. I wanted the daemon to send out an email if it could not execute the action it was assigned. Something like this (where Action is the variable that holds the statement to be executed: If Error? Error: Try [ Do Action] [ Send Warning email ] Realizing that Try is similar to Do, I even used: If Error? Error: Try [ Action] [ Send Warning email ] The first executed without issue, making me think that everything was executing OK; it wasn't. The second gave me the "no value" error. But this is why I'm confused: If try is to be used to help trap errors, why does it care if a value is set or not? That's why I pointed out that I got the error when issuing a "write" command. If anything needed to be trapped, it was that. How else can I tell if a file is not there, or I don't have access permission, or the file system is too full, etc? The above statements, BTW, were taken (in form) from a REBOL manual. They were text-book examples...
>It's possible to write a function that'll check for nothing returned, >as the any-type! datatype will accept nothing. ie...
<<quoted lines omitted: 14>>
>>> >== nothing...
I suppose I could use that technique as part of my error trapping, the question still remains: why? Error trapping should have to do with trapping errors, not (just) return values. -- Sincerely, | Cold Hearted Orb, that rules the night. Removes Ed Dana | the colours from our sight! Red is gray and Software Developer | yellow white! But we decide which is right... 1Ghz Athlon Amiga | And which is an illusion! | -- The Moody Blues, Late Lament.

 [9/34] from: carl:cybercraft at: 29-Aug-2002 20:23


On 29-Aug-02, Ed Dana wrote:
> Carl Read wrote: >> Hee - wasted time on this myself today!
<<quoted lines omitted: 19>>
> Yes. But the value that I was trying to assign Fred was the error > that was to occur when I attempted my action.
Ah. And thanks to the other responses to your post, (specifically the ones talking about unset), this might be what you want... if error? Fred: try [unset? print "OK!"][ Fred: disarm Fred print "Fred reports..." probe Fred ] That gives... OK! == none and this... if error? Fred: try [unset? 1 / 0][ Fred: disarm Fred print "Fred reports..." probe Fred ] Fred reports... make object! [ code: 400 type: 'math id: 'zero-divide arg1: none arg2: none arg3: none near: [unset? 1 / 0] where: none ] Okay - a full blown test... test: [either error? Fred: try [ unset? Harry: switch random 3 [ 1 [print "Printing..."] 2 ["Returning a value..."] 3 [1 / 0] ] ][ Fred: disarm Fred print "Fred reports error near..." print mold Fred/near ][ print ["Harry reports..." Harry] ]] Doing that block 10 times gives...
>> loop 10 [do test]
Harry reports... Returning a value... Printing... Fred reports error near... [unset? Harry: switch random 3] Fred reports error near... [1 / 0] Harry reports... Returning a value... Printing... Fred reports error near... [unset? Harry: switch random 3] Fred reports error near... [1 / 0] Printing... Fred reports error near... [unset? Harry: switch random 3] Fred reports error near... [1 / 0] Harry reports... Returning a value... Printing... Fred reports error near... [unset? Harry: switch random 3]
> More accurately, I have written a couple of daemons, that execute a > command that I pass to it as a parameter. I wanted the daemon to
<<quoted lines omitted: 3>>
> statement to be executed: > If Error? Error: Try [ Do Action] [ Send Warning email ]
Hopefully the above is what you need. If not, keep asking. Someone here will know the answer!
> Realizing that Try is similar to Do, I even used: > If Error? Error: Try [ Action] [ Send Warning email ]
<<quoted lines omitted: 3>>
> But this is why I'm confused: If try is to be used to help trap > errors, why does it care if a value is set or not?
It doesn't - your error was outside the 'try block...
>> either error? try [print "x"]["Error!"]["No error!"]
x == "No error!"
>> either error? Fred: try [print "x"]["Error!"]["No error!"]
x ** Script Error: Fred needs a value ** Near: either error? Fred: try [print "x"] There'd have to be a special case made to stop 'try causing an error in such cases - and yes, there probably should be. Writing the above made me think about an error-trap within an error-trap. So, an alternative to the first test... test2: [ either error? try [ if error? Fred: try [ switch random 3 [ 1 [print "Printing..."] 2 ["Returning something..."] 3 [1 / 0] ] ][ print "Error!" Fred: disarm Fred ] ][ print "Fred Error!" ; ie, Fred unset. ][ print ["Fred reports..." probe Fred] ] ] Not the same output as the first test though...
>> loop 10 [do test2]
Returning something... Fred reports... Returning something... Returning something... Fred reports... Returning something... Printing... Fred Error! Printing... Fred Error! Returning something... Fred reports... Returning something... Error! make object! [ code: 400 type: 'math id: 'zero-divide arg1: none arg2: none arg3: none near: [1 / 0] where: 'switch ] Fred reports... ?object? Printing... Fred Error! Returning something... Fred reports... Returning something... Returning something... Fred reports... Returning something... Returning something... Fred reports... Returning something... -- Carl Read

 [10/34] from: tomc:darkwing:uoregon at: 29-Aug-2002 0:31


On Wed, 28 Aug 2002, Ed Dana wrote:
> Yes. But the value that I was trying to assign Fred was the error that > was to occur when I attempted my action.
you capture that error from 'try
>> either error? err: try[1 / 0 ][true][false]
== true
>> err
** Math Error: Attempt to divide by zero ** Near: 1 / 0
>> either error? err: try[1 / 1][true][false]
== false
>> err
== 1
> More accurately, I have written a couple of daemons, that execute a > command that I pass to it as a parameter. I wanted the daemon to send
<<quoted lines omitted: 4>>
> Realizing that Try is similar to Do, I even used: > If Error? Error: Try [ Action] [ Send Warning email ]
been doing something similar daily for years should not be a problem
> The first executed without issue, making me think that everything was > executing OK; it wasn't. The second gave me the "no value" error.
<<quoted lines omitted: 3>>
> trapped, it was that. How else can I tell if a file is not there, or I > don't have access permission, or the file system is too full, etc?
I agree that current behavior does not lead me down the path of least astonishment. I would expect err: try[prin ""] to pass quietly and 'err to have the value it would have after a unset 'err that is:
>> error? unset 'err
== false prolly should send it to feedback. however as a umm.. hack! you could add a constant (anything but an error!) to the end of your 'try block 'try will return the constant if it gets to it without encountering an error first. err: none either error? err: try[ (1 / 0 ) "no-err"][true][false] == true
>> err
** Math Error: Attempt to divide by zero ** Near: 1 / 0
>> err: none either error? err: try[ (print 1 ) "no-err"][true][false]
1 == false
>> err
== "no-err"
>> err: none either error? err: try[ (1 ) "no-err"][true][false]
== false
>> err
== "no-err"
>> either error? err: try[ make error! "boo" "no-err"][true][false]
== true
>> err
** User Error: boo ** Near: make error! "boo" "no-err"

 [11/34] from: lmecir:mbox:vol:cz at: 29-Aug-2002 10:06


Hi Ed, it looks, that you missed my advice on this. <<Ed>> ...
>>>If Error? try [Fred: Print "See?"][Print "Whatever!"] >>> >See? >Whatever! >
Yes. But the value that I was trying to assign Fred was the error that was to occur when I attempted my action. More accurately, I have written a couple of daemons, that execute a command that I pass to it as a parameter. I wanted the daemon to send out an email if it could not execute the action it was assigned. Something like this (where Action is the variable that holds the statement to be executed: If Error? Error: Try [ Do Action] [ Send Warning email ] Realizing that Try is similar to Do, I even used: If Error? Error: Try [ Action] [ Send Warning email ] The first executed without issue, making me think that everything was executing OK; it wasn't. The second gave me the "no value" error. But this is why I'm confused: If try is to be used to help trap errors, why does it care if a value is set or not? That's why I pointed out that I got the error when issuing a "write" command. If anything needed to be trapped, it was that. How else can I tell if a file is not there, or I don't have access permission, or the file system is too full, etc? <</Ed>> <<L>> the situation is simpler than you think. You can use: if error? set/any 'error try action [send warning email] Try doesn't care what is the result value. Your problem is, that if you use an expression like (error: ...), the interpreter fires an error, if the result of the (...) expression is of the UNSET! datatype. This means, that the error occurs outside of the try block, which means, that TRY cannot trap it. <</L>> <<Ed>> ... The above statements, BTW, were taken (in form) from a REBOL manual. They were text-book examples... <</Ed>> <<L>> yes, there are some misleading informations in the documentation... <</L>> <<Ed>> I suppose I could use that technique as part of my error trapping, the question still remains: why? Error trapping should have to do with trapping errors, not (just) return values. <</Ed>> <<L>> you can, you just need to know how and why... <</L>> Cheers -L

 [12/34] from: carl:cybercraft at: 30-Aug-2002 10:48


On 29-Aug-02, Tom Conlin wrote:
> err: none either error? err: try[ (1 / 0 ) "no-err"][true][false] > == true
<<quoted lines omitted: 17>>
> ** Near: make error! "boo" "no-err" >>>
And that's probably the best way to do it, and certainly simpler than my approach... -- Carl Read

 [13/34] from: edanaii:cox at: 29-Aug-2002 17:23


Ladislav Mecir wrote:
>Hi Ed, > >it looks, that you missed my advice on this. >
I didn't miss your advice, Ladislav. Yesterday was a busy day so I kinda read through it quickly. Sorry for that. I tried the solution you presented below, it worked great. Thanks to all for the input. Personally, I would call it a quirk, but every language has its quirks, why should REBOL be any different. :) -- Sincerely, | Life is pain, Highness. Anyone who says Ed Dana | differently is selling something. Software Developer | -- The Princess Bride. 1Ghz Athlon Amiga |

 [14/34] from: ammon:rcslv at: 30-Aug-2002 21:45


Hi, The other suggestions will probably bring you to realise this, but I wanted to make it a little more obvious... When attempting to catch an error and disarm it for your own error handling scheme you will find that using 'set/any is needed rather than a set-word for maximum strength error handling. For example: Use
>> if error set/any fred try [print "done"] [print "Error!"]
done
>>
Rather than
>> if error fred: try [print "done"] [print "Error!"]
All that try does is catches any error that may be encountered and returns it in as an Error! datatype. 'try doesn't care if a datatype that cannnot be assigned via 'set or a set-word is passed, it will only attempt to 'disarm an error within the argument passed to it. HTH Ammon

 [15/34] from: lmecir:mbox:vol:cz at: 31-Aug-2002 10:58


Hi all, <<Ed>> ... Personally, I would call it a quirk, but every language has its quirks, why should REBOL be any different. :) <</Ed>> I call it a quirk too and I suggested to straighten the things some time ago. Meanwhile I use my DEFAULT function: default action error-handling The source of the function is: Rebol [ Title: "Default" File: %default.r Author: "Ladislav Mecir" Email: [lmecir--mbox--vol--cz] Reb: reb://Sites/Ladislav Web: http://www.rebolforces.com/~ladislav Purpose: { An error handling function } Category: [General] ] default: function [ { Try to evaluate code. Evaluate the fault block, if an error occurs } [throw] code [block!] fault [block!] /good pass [block!] ] [result] [ either error? set/any 'result try code [ use [error] compose [ any-type? error: :result do (reduce [fault]) ] ] [ either good [do pass] [get/any 'result] ] ]

 [16/34] from: g:santilli:tiscalinet:it at: 31-Aug-2002 15:56


Hi Ladislav, On Saturday, August 31, 2002, 10:58:41 AM, you wrote: LM> Meanwhile I use my DEFAULT function: BTW Ladislav, do you think there could be any problems with this alternative version? default: func [ [throw] code [block!] fault [block!] /good pass [block!] /local result ] [ either error? set/any 'result try code [ fault: func [[throw] error [error!]] fault fault result ] [ do any [pass [get/any 'result]] ] ] Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [17/34] from: lmecir:mbox:vol:cz at: 31-Aug-2002 20:28


Hi Gabriele, <<G>> ... BTW Ladislav, do you think there could be any problems with this alternative version? default: func [ [throw] code [block!] fault [block!] /good pass [block!] /local result ] [ either error? set/any 'result try code [ fault: func [[throw] error [error!]] fault fault result ] [ do any [pass [get/any 'result]] ] ] <</G>> I think, that your version is more understandable and more robust. That is why I suggest others to use Gabriele's version instead of mine. I am still curious, if many Rebol users prefer to allow UNSET! valued expressions (eventually why?). OTOH, both versions of DEFAULT cannot discern "illegal" and "legal" errors, which is another glitch in Rebol I would prefer to have straightened. Ciao -L

 [18/34] from: g:santilli:tiscalinet:it at: 1-Sep-2002 12:06


Hi Ladislav, On Saturday, August 31, 2002, 8:28:43 PM, you wrote: LM> I am still curious, if many Rebol users prefer to allow UNSET! valued LM> expressions (eventually why?). There's no reason to have them, and that's just likely to be an implementation issue with the current interpreter (it needs unset! for unset words, and once you have that is pretty natural to have:
>> f: func [] [return]
return unset!, being RETURN's argument unset; so they have probably decided that empty blocks should have returned unset! too...) LM> OTOH, both versions of DEFAULT cannot discern "illegal" and "legal" errors, LM> which is another glitch in Rebol I would prefer to have straightened. I was looking in your site to see what you intend for an illegal error, but I wasn't able to find it. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [19/34] from: lmecir:mbox:vol:cz at: 1-Sep-2002 13:23


Hi Gabriele and all, LM> I am still curious, if many Rebol users prefer to allow UNSET! valued LM> expressions (eventually why?). <<Gabriele>> There's no reason to have them, and that's just likely to be an implementation issue with the current interpreter (it needs unset! for unset words, and once you have that is pretty natural to have:
>> f: func [] [return]
return unset!, being RETURN's argument unset; so they have probably decided that empty blocks should have returned unset! too...) <</Gabriele>> <<L>> You are right, it looks logical at a first glance. Nevertheless, the following looks logical too: type? while [false] [] ; == none! and it differs from type? do [] ; == unset! I think, that the behaviour should be unified. My proposition is to use the former convention, which is much less complicated. I am not against using UNSET! values internally for the interpreter purposes (detection of uninitialized variables). OTOH, this purpose is totally internal and shouldn't be "exposed" to the user. A similar "quirk" with an END! type value has already been straightened by RT. <</L>> LM> OTOH, both versions of DEFAULT cannot discern "illegal" and "legal" errors, LM> which is another quirk in Rebol I would prefer to have straightened. <<Gabriele>> I was looking in your site to see what you intend for an illegal error, but I wasn't able to find it. <</Gabriele>> <<L>> It is my fault, I wrote it too lazily. Here is a more thorough explanation: block: [] probe disarm try [first block] ; == make object! [ ; code: 315 ; type: 'script ; id: 'past-end ; arg1: none ; arg2: none ; arg3: none ; near: [first block] ; where: none ; ] The result of the (first block) expression evaluation doesn't exist in a sense. Try "creates" its result catching the fired error you see above. Now a more complicated code sample: block2: head insert tail copy [] try [first block] probe disarm try [first block2] The difference is, that in this case the result of the (first block2) expression evaluation "legally" exists, that is why I call it a "legal" error. A function like TRY cannot discern these cases, while a native version of the DEFAULT function could. Ciao -L

 [20/34] from: g:santilli:tiscalinet:it at: 1-Sep-2002 19:26


Hi Ladislav, On Sunday, September 1, 2002, 1:23:35 PM, you wrote: LM> The difference is, that in this case the result of the (first block2) LM> expression evaluation "legally" exists, that is why I call it a "legal" LM> error. I see. I'd more likely have errors as first class, instead of a DEFAULT function able to make the distinction. Anyway, it is possible to discern the two cases with:
>> is-really-error?: func [code] [error? try compose [error? (code)]] >> is-really-error? [first block]
== true
>> is-really-error? [first block2]
== false I haven't tried it with any other case tough. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [21/34] from: lmecir:mbox:vol:cz at: 1-Sep-2002 20:28


Hi again, LM> The difference is, that in this case the result of the (first block2) LM> expression evaluation "legally" exists, that is why I call it a "legal" LM> error. <<Gabriele>> I see. I'd more likely have errors as first class, instead of a DEFAULT function able to make the distinction. Anyway, it is possible to discern the two cases with:
>> is-really-error?: func [code] [error? try compose [error? (code)]] >> is-really-error? [first block]
== true
>> is-really-error? [first block2]
== false I haven't tried it with any other case tough. <</Gabriele>> It looks to me, that the "first class error" and the "legal vs. illegal error" distinction are two sides of the same coin. Your IS-REALLY-ERROR? function works for simple code like above, but, AFAIK, we cannot handle all possible cases, like e.g.: is-really-error? [1 first block2] ; == true (until errors will be "first class"). Ciao -L

 [22/34] from: g:santilli:tiscalinet:it at: 2-Sep-2002 0:39


Hi Ladislav, On Sunday, September 1, 2002, 8:28:22 PM, you wrote: LM> It looks to me, that the "first class error" and the "legal vs. illegal LM> error" distinction are two sides of the same coin. Indeed. We cannot use errors at all, only disarm them. So, probably we can state that errors can never be "legal", if we decide that we should never intentionally return an (armed) error. (It can be seen as a sort of workaround...) LM> Your IS-REALLY-ERROR? function works for simple code like above, but, AFAIK, LM> we cannot handle all possible cases, like e.g.: The problem is that if you enclose the code in a block or a paren the error is immediately fired; i.e. the only way to return an error from an expression is if the expression is being evaluated directly as an argument for a function. This makes me think that it's likely that this was added as a way to make functions like DISARM and ERROR? work, but otherwise error!s were intended as a very special class of values. I am more and more tempted to start writing a REBOL implementation, just to try out different approaches and to better understand why things have been done this way... pity I don't really have the time to do it. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [23/34] from: rotenca:telvia:it at: 2-Sep-2002 2:36


Hi Ladislav and Gabriele,
> Your IS-REALLY-ERROR? function works for simple code like above, but, AFAIK, > we cannot handle all possible cases, like e.g.: > > is-really-error? [1 first block2] ; == true > > (until errors will be "first class").
You are right about first class, but i think the code above gives the correct result in the actual implementation of Rebol, because, for example, the execution of the block: [x: 1 first block2 x: 2] is interrupted with a real error when the expression "first block2" is executed, and "x: 2" is never executed: do [x: 1 first block2 x: 2] x ; == 1 so this is a real error in the actual Rebol implementation. I think, indeed, that is not correct to return false with: is-really-error? [first block2] ;==false for the same reason. The function should answer to this question: "the code fires an error when evaluated?" and [first block2] fires an error when evaluated. While the expression: [type? first block2] does not fires an error when evaluated I think there is no difference from this point of view between [first block] -> error [first block2] -> error but there is a difference between [type? first block] -> error [type? first block2] -> not error And Try is enough to discern them. Is-really-error? should be called: can-some-functions-accept-this-argument-without-an-error? and the blocks [first block2] can be accepted by many functions if not evaluated, but when you do it, before passing the result to a function, it always fires an error! BTW, actual implementation fails with is-really-error? first block2 ;== *** error! but can be corrected. --- Ciao Romano

 [24/34] from: lmecir:mbox:vol:cz at: 2-Sep-2002 8:58


Hi Romano, no objection to your analyse. The fact, that the expression (first block2) is illegal, while (error? first block2) isn't justifies my POV, that this behaviour is a Rebol quirk. I want the interpreter/language to be less aggressive (and faster and simpler and logical ...). I am saying the same about the "exposition" of the UNSET! datatype, and I was saying it about the "exposition" of the END! datatype, but the last one got straightened. <<Romano>> Hi Ladislav and Gabriele,
> Your IS-REALLY-ERROR? function works for simple code like above, but,
AFAIK,
> we cannot handle all possible cases, like e.g.: > > is-really-error? [1 first block2] ; == true > > (until errors will be "first class").
You are right about first class, but i think the code above gives the correct result in the actual implementation of Rebol, because, for example, the execution of the block: [x: 1 first block2 x: 2] is interrupted with a real error when the expression "first block2" is executed, and "x: 2" is never executed: do [x: 1 first block2 x: 2] x ; == 1 so this is a real error in the actual Rebol implementation. I think, indeed, that is not correct to return false with: is-really-error? [first block2] ;==false for the same reason. The function should answer to this question: "the code fires an error when evaluated?" and [first block2] fires an error when evaluated. While the expression: [type? first block2] does not fires an error when evaluated I think there is no difference from this point of view between [first block] -> error [first block2] -> error but there is a difference between [type? first block] -> error [type? first block2] -> not error And Try is enough to discern them. Is-really-error? should be called: can-some-functions-accept-this-argument-without-an-error? and the blocks [first block2] can be accepted by many functions if not evaluated, but when you do it, before passing the result to a function, it always fires an error! BTW, actual implementation fails with is-really-error? first block2 ;== *** error! but can be corrected. --- Ciao Romano

 [25/34] from: lmecir:mbox:vol:cz at: 2-Sep-2002 10:19


Hi Gabriele, Romano, myself and others, when I said: <<L>> IS-REALLY-ERROR? function works for simple code like above, but, AFAIK, we cannot handle all possible cases, like e.g.: is-really-error? [1 first block2] ; == true (until errors will be "first class")" <</L>> , I was wrong. Here is a (complicated, but working) version of the DEFAULT function, that can handle it: do http://www.rebolforces.com/~ladislav/highfun.r default2: transp-func [ code [block!] fault [block!] /good pass [block!] /local result error code2 ] [ transp-while [not tail? code] [ code: if error? set/any 'error try [ set/any 'code2 second do/next compose [ error? set/any 'result (code) ] skip code (index? code2) - 3 ] [tail code] ] either error? get/any 'error [ fault: func [[throw] error [error!]] fault local-return fault error ] [ do any [pass [local-return get/any 'result]] ] ] block2: head insert copy [] try [first []] default2/good [first block2 1] ["error"] ["pass"] ; == "pass" default2/good [first block2] ["error"] ["pass"] ; == "pass" default2/good [first []] ["error"] ["pass"] ; == "error" Ciao Ladislav

 [26/34] from: lmecir:mbox:vol:cz at: 2-Sep-2002 10:31


Correction, I posted a wrong version, so once again: do http://www.rebolforces.com/~ladislav/highfun.r default2: transp-func [ code [block!] fault [block!] /good pass [block!] /local result error code2 ] [ transp-while [not tail? code] [ if error? set/any 'error try [ code2: second do/next compose [ error? set/any 'result (code) ] code: skip code (index? code2) - 3 ] [code: tail code] ] either error? get/any 'error [ fault: func [[throw] error [error!]] fault fault error ] [ do any [pass [local-return get/any 'result]] ] ] block2: head insert copy [] try [first []] default2/good [first block2 1] ["error"] ["pass"] ; == "pass" default2/good [first block2] ["error"] ["pass"] ; == "pass" default2/good [first []] ["error"] ["pass"] ; == "error" Ciao Ladislav

 [27/34] from: rotenca:telvia:it at: 2-Sep-2002 13:38


Hi Ladislav and all,
>, I was wrong. Here is a (complicated, but working) version of the DEFAULT >function, that can handle it:
I also was experimenting with do/next and this is my code. It try to handle also return, throw, break. isr?: function [blk [block!]][res][ while [not tail? blk][ either error? try [ error? catch [ error? do does [ error? loop 1 [ error? set 'res do/next compose [error? (blk)] ] ] ] ][ return true ][ if none? res [prin "control detected " return false] blk: second res res: none ] ] false ] block2: head insert tail copy [] try [first []] isr? [1 2 first block2 3] ;==false isr? [1 2 first block 3] ;==true isr? [1 2 throw first block2 3] ;==control detected false isr? [1 2 throw first block 3] ;==true isr? [1 2 return first block2 3] ;==control detected false isr? [1 2 return first block 3] ;==true isr? [1 2 break/return first block2 3] ;==control detected false isr? [1 2 break/return first block 3] ;==true --- Ciao Romano

 [28/34] from: lmecir:mbox:vol:cz at: 2-Sep-2002 15:11


Hi Romano, <<Romano>> ... I also was experimenting with do/next and this is my code. It try to handle also return, throw, break. isr?: function [blk [block!]][res][ while [not tail? blk][ either error? try [ error? catch [ error? do does [ error? loop 1 [ error? set 'res do/next compose [error? (blk)] ] ] ] ][ return true ][ if none? res [prin "control detected " return false] blk: second res res: none ] ] false ] block2: head insert tail copy [] try [first []] isr? [1 2 first block2 3] ;==false isr? [1 2 first block 3] ;==true isr? [1 2 throw first block2 3] ;==control detected false isr? [1 2 throw first block 3] ;==true isr? [1 2 return first block2 3] ;==control detected false isr? [1 2 return first block 3] ;==true isr? [1 2 break/return first block2 3] ;==control detected false isr? [1 2 break/return first block 3] ;==true <</Romano>> 1a) THROW. My DEFAULT2 function "works" as follows: default2/good [1 2 throw first block2 3] ["caught"] ["passed"] ** Throw Error: ** Script Error: Out of range or past end ** Near: first [] i.e. it isn't able to catch this kind of error. The ISR? function seems to not notice there was an error. 1b) However: type? catch [default2/good [1 2 throw first block2 3] ["caught"] ["passed"]] ; == error! , i.e. DEFAULT2 works as expected in this case. type? catch [isr? [1 2 throw first block2 3]] ; control detected == logic! , i.e. the ISR? function "creates" an artifact. For RETURN and BREAK I obtained equivalent results. I would prefer to have the ability to catch even BREAK, RETURN and THROW errors, which I cannot do now (AFAIK!). Ciao Ladislav

 [29/34] from: rotenca:telvia:it at: 2-Sep-2002 18:08


Hi Ladislav,
> 1a) THROW. My DEFAULT2 function "works" as follows: > > default2/good [1 2 throw first block2 3] ["caught"] ["passed"] > ** Throw Error: ** Script Error: Out of range or past end > ** Near: first [] > > i.e. it isn't able to catch this kind of error. The ISR? function seems to > not notice there was an error.
[...]
> , i.e. the ISR? function "creates" an artifact. > > For RETURN and BREAK I obtained equivalent results.
I wanted to catch throw (without catch), return (out of function) and break (out of a loop). I left to the user what to do with them. If you think they must be errors in the Default function, the isr? func should return true: if none? res [return true] instead of if none? res [prin "control detected " return false]
> I would prefer to have the ability to catch even BREAK, RETURN and THROW > errors, which I cannot do now (AFAIK!).
If one wants the throw/break/return error! object in the isr? function, he must re-create it :-( But attention, the no-loop error is a special error. If this is standard: error? do does [return make error! [throw no-function]] ;== true this is not:
>> error? do does [return make error! [throw no-loop]]
** Throw Error: Nothing to break ** Near: return make error! [throw no-loop] The break error! is third class! :-)
> Ciao > Ladislav
--- Ciao Romano

 [30/34] from: anton:lexicon at: 3-Sep-2002 5:13


I'm glad you guys are sorting all this stuff out, because I don't know what you are on about half the time. :) You have encouraged me to learn something new for today - that is using do/next. I never really looked into it before. Probably because I couldn't think of a use for it. Anyway, for other newbies to do/next, here's how to step through some code, one expression at a time. code: [print 1 print 2 print 3] loop 3 [ code: second do/next code ] Cool! Now to think of a use for it... Anton.

 [31/34] from: lmecir:mbox:vol:cz at: 3-Sep-2002 9:32


Hi all, I thank Romano for his finding and try to comprise out knowledge about Rebol errors. We can classify errors by the interpreter behaviour to three groups: 1) crashes (errors, that crash the interpreter). I think, that such errors shouldn't exist at all. (Opinions?) 1a) Native function crashes, like SAME? crash, where it is enough to modify the function - my IDENTICAL? doesn't crash. (I don't understand, why this crash still persists?!) 1b) "Self-modifying" code crashes - there is only one recipe to "cure" this - rewrite the interpreter, i.e. use a slightly different interpretation strategy. An example of such crash is: a: func [x] [1] a a: 1 This crash has already been "cured", but the behaviour still is strange - compare it to the Freebell interpreter's behaviour, where the above code isn't self-modifying at all! These crashes can be eliminated - e.g. using a strategy I proposed. (Opinions?) 2) Errors are representable by Rebol values which don't crash the interpreter. 2a) Errors, that cannot be caught. Examples are THROW ERRORS caused by RETURN or EXIT out of function, THROW out of a catch block or BREAK out of a loop. I think, that the interpreter should be modified to be able to catch these. (Opinions?) 2b) "Normal" errors, that can be caught by the TRY function (or my DEFAULT/DEFAULT2). Another possibility is to classify errors by aggressivity of their evaluation. Almost every error is second class like: II) type? make error! "" ; == error! , which is OK, but: type? (make error! "") ** User Error: ** Near: make error! "" doesn't yield the same result as the former expression, which is an interpreter quirk. I propose to change all errors to first class, which would be: I) Hypothetical! type? (make error! "") ; == error! III) Romano revealed, that some errors are third class, like: type? make error! [throw no-loop] ** Throw Error: Nothing to break ** Near: type? make error! [throw no-loop] , which is a bigger quirk than above. Opposite opinions welcome Cheers Ladislav

 [32/34] from: rotenca:telvia:it at: 3-Sep-2002 13:05


Hi Ladislav, thank for your summary, only a note about:
> type? make error! [throw no-loop] > ** Throw Error: Nothing to break > ** Near: type? make error! [throw no-loop] > > , which is a bigger quirk than above.
no-loop error! seems to have the same beaviour which has any others error, when a function has at least the attribute []:
>> error? do func[][return make error! "any"] ;== true >> error? do func[[]][return make error! "any"]
** Throw Error: Return or exit not in function ** Where: func [[]][return make error! "any"] ** Near: return make error! "any" --- Ciao Romano
> Opposite opinions welcome > Cheers
<<quoted lines omitted: 3>>
> [rebol-request--rebol--com] with "unsubscribe" in the > subject, without the quotes.
--- Ciao Romano

 [33/34] from: lmecir:mbox:vol:cz at: 3-Sep-2002 14:49


Hi Romano, the behaviour seems to have more to do with function attributes: <<Romano>> ... no-loop error! seems to have the same beaviour which has any others error, when a function has at least the attribute []:
>> error? do func[][return make error! "any"] ;== true >> error? do func[[]][return make error! "any"]
** Throw Error: Return or exit not in function ** Where: func [[]][return make error! "any"] ** Near: return make error! "any" <</Romano>> See the following code samples: type? do does [type? do func [] [return make error! ""]] ; == datatype! type? do does [type? do func [[throw]] [return make error! ""]] ; == error! type? do does [type? do func [[]] [return make error! ""]] ; == error! The empty attribute is interpreted like the [throw] attribute in this case! It looks like an implementation issue. Ciao Ladislav

 [34/34] from: rotenca:telvia:it at: 3-Sep-2002 16:19


Hi Ladislav,
> the behaviour seems to have more to do with function attributes: > See the following code samples:
<<quoted lines omitted: 3>>
> The empty attribute is interpreted like the [throw] attribute in this case! > It looks like an implementation issue.
Yes, we spoke about that some time ago. But my previous statement: no-loop error! seems to have the same beaviour which has any others error, when a function has at least the attribute []: is wrong: no-loop is uncatchable at all, and undisarmable, while orthers errors in functions with the attribute [] or [throw] can be catched and disarmed with a function wrapper. BTW, no-loop is the only one error wich show this behaviour. Neither Syntax error have its behaviour. I think that this could be related to the Break behaviour which ignores functions bound: loop 2 [print 1 do does [break]] ;= 1 Break does not requires [throw] to throw the break to the upper function. So a Break error can only happens at the higher level of code execution and never inside user code.
> Ciao > Ladislav
--- Ciao Romano

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted