r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!REBOL3]

Paul
3-Mar-2010
[1147]
Brian, I agree with you.  I think if we make Try or Attempt handle 
these other exceptions then we are going to slow things down.  Again, 
we have  a way to handle this now.  No need to pursue the problem 
at this point.
Andreas
3-Mar-2010
[1148x3]
This `attempt [break]` debate is really interesting.
I think it uncovered not a bug in the implementation, but provokes 
a discussion on the language semantics.
I guess I'll have to write that up in more detail :)
Sunanda
3-Mar-2010
[1151]
Thanks for the repeated attempts to explain, Brian!

For me, the work around is:
    error? try [....]
That seems to work in all cases I have tried.


[Ironically, 99% of all the REBOL code I have ever written uses ERROR? 
TRY --  ATTEMPT did not exist when I started REBOL, and my fingers 
have learned to type the idiom. It's only with R3 that I'ved tried 
to update my error handling.....Seems I should stick with my older 
ways for a while...:)]
Andreas
3-Mar-2010
[1152x4]
Ok, I've written up some of my thoughts at http://www.rebol.net/wiki/User_talk:Andreas#Notes_on_Bug.231506_--_on_control_transfer_functions
The gist of it: I think most control transfer functions should be 
unbound globally, and only bound in code executing within their respective 
control transfer handler.
For example, BREAK should be unbound globally, and bound only within 
loop bodies.
That means, an erroneous use of e.g. BREAK would simply result in 
a "has no value" error, just as the use of any other unset word. 
And this error would of course be nicely caught by ATTEMPT.
Sunanda
3-Mar-2010
[1156]
The crux of the issue for me is this:
  attempt [badcode] print true
I (naively perhaps) suggest that this should always either:
-- close the console (if badcode has a QUIT); or
-- halt (if  badcode has a HALT; or
-- print TRUE in all other cases.


Brian argues that there are internal engineering reasons for a fourth 
possibility:
-- ATTEMPT returns an error message
Andreas
3-Mar-2010
[1157x4]
I think that your suggestion is not naive but very reasonable
And I also think there's an easy way to fix things that they work 
as you expect
Easy
 from a language design perspective, that is.
I also think it is reasonably straightforward to implement and has 
no significant impact on performance. But I don't have the time to 
write down why I think this, at the moment.
BrianH
3-Mar-2010
[1161x2]
Sunanda, that error? try [....] code you keep mentioning doesn't 
work in all cases you mention. The problem is this:
>> error? break
== true

This is an error (bug#771 and bug#862): It should not return true, 
it should break and then later on trigger an error for an unhandled 
break. To illustrate why:
>> loop 1 [error? break 'buggy]
== buggy

That should have returned unset, not continued. The BREAK is supposed 
to halt execution and resume it somewhere else, either after the 
enclosing loop or at the top level. The same error is affecting your 
error? try [....] code, which is not behaving correctly. 


Your problem, Sunanda, is that you are thinking that ATTEMPT is not 
catching bad code (bugs) that it is supposed to catch - this is not 
strictly true. ATTEMPT isn't supposed to catch bugs, it is supposed 
to catch triggered errors. And a lot of logic bugs don't trigger 
errors, because the code itself is technically correct (what REBOL 
can check for), but not in accordance with the programmer's intentions 
(which REBOL can't know).


Now in this case the logic bug is that you have forgotten that the 
purpose of the BREAK, CONTINUE, THROW, EXIT and RETURN functions 
is escape from the normal flow of the code ("structured" gotos, aka 
non-local returns, exceptions, ...) - you remembered this about HALT 
and QUIT - and didn't realize that the error you are trying to catch 
with ATTEMPT is not in the code that you have wrapped in the ATTEMPT: 
It is not bad code. The error is triggered by the code on the other 
end, the handler, which is not wrapped in the ATTEMPT at all.

So you need to realize that this code is technically correct:
>> attempt [break]
** Throw error: no loop to break
but doesn't do what you thought it should.

And this code is absolutely incorrect:
>> error? try [break]
== true

but doesn't trigger an error because of a weird design quirk in R3 
that is arguably a bug, but not necessarily fixable (see bug#771 
and bug#862).
Created a ticket (bug#1509) to explain the real problem with these 
functions.
Paul
3-Mar-2010
[1163x3]
do we really want this behavior:

>> obj: construct [a: b: c: 1]
== make object! [
    a: 1
    b: 1
    c: 1
]
I think we need a way to pass that block so that 'a and 'b can evaluate 
to none
It is clear why it setting a and b to 1 but we need to have something 
a bit safer.
BrianH
3-Mar-2010
[1166x2]
We want that behavior and much code depends on it. You can add the 
none explicitly if you need that value.
And CONSTRUCT doesn't evaluate anything, so safety is not an issue.
Paul
3-Mar-2010
[1168x2]
Still we need to check it and we could simply have another switch 
that could fix construct to be even more superior.
construct/as-is
BrianH
3-Mar-2010
[1170]
We have that option, except it's called /only.
Paul
3-Mar-2010
[1171x2]
that doesn't work for this issue
>> a: construct/only [c: d: 1]
== make object! [
    c: 1
    d: 1
]
BrianH
3-Mar-2010
[1173]
Chained assignments aren't an issue, they are an intended feature.
Paul
3-Mar-2010
[1174]
I understand that but we need a feature in which they are NOT.
BrianH
3-Mar-2010
[1175]
>> construct/only [a: b:]
== make object! [
    a: none
    b: none
]
Paul
3-Mar-2010
[1176]
that is still a chained assignment
BrianH
3-Mar-2010
[1177]
But that's not a problem.
Paul
3-Mar-2010
[1178x4]
Ok, it doesn't seem your following me, so let's forget about construct.
We need a function that does not evaluate or do chain assignment.
But let's you access the elements as if they are an object and can 
already exist in a block style spec that can be passed to context.
So it would be similiar to construct except without the chain assignment.
BrianH
3-Mar-2010
[1182]
CONTEXT does chained assignment too, btw.
Paul
3-Mar-2010
[1183]
Yes, so does almost everything in REBOL since day 1.  Surely your 
not thinking I just stumbled upon that discovery.
BrianH
3-Mar-2010
[1184]
Do you need to access the elements as if they are in an object, or 
elements that are actually in an object?
Paul
3-Mar-2010
[1185]
I'm just seeing room for improvement here to make REBOL even more 
safe.
BrianH
3-Mar-2010
[1186]
But there are no safety issues with chained assignment.
Paul
3-Mar-2010
[1187x5]
I could simply just use a block if I want to access elements but 
that isn't ideal for conversion to an object when I decide I want 
that flexibility.
Not so my friend.
That is where your wrong.
Ideally you would use a construct for assignments of values passed 
via cgi.
While those items are string values it could still potentially be 
exploited in my opinion.
BrianH
3-Mar-2010
[1192]
It sounds like you need a PARSE wrapper.
Paul
3-Mar-2010
[1193x2]
Or we just make sure that such assignment is not chained -       
       ;-)
bbl
BrianH
3-Mar-2010
[1195x2]
If the CGI data is parsed properly it should never generate anything 
other than pairs. If it ever generates chained assignments that is 
an error in your parse rules, not CONSTRUCT.
By "pairs" I mean name-value pairs, not pair! values.