Home   Archive   Permalink



Proper use of attempt

I have a situation where I want to read a file and write it to a new file, but the input file might not be present and if it is not I will wait five seconds and try again. I know, doesn't make much sense, but it is part of a larger program. Anyway, I thought that the way to do this was to 'attempt' to read and write the file. So I did it as shown below. If the attempt FAILS and returns none, things work fine, but it the attempt SUCCEEDS and returns the 'result' of the attempt (whatever that means), then I get the error shown below. I know I am using this the wrong way, but I don't quite see the right way and am wondering if anyone can enlighten me.
    
Thank you. Demo follows.
    
R E B O L []
    
;; The file %test-out.txt DOES exist.
    
if not attempt [write %testoutput.txt read %test-out.txt] [
     wait 00:00:05
     attempt [write %testoutput.txt read %test-out.txt]
]
    
alert 'Done.'
    
** Script Error: not is missing its value argument
** Near: if not attempt [write %testoutput.txt read %test-out.txt] [
     wait 0:00:05
     attempt [write %testoutput.txt read %t...
>> exists? %test-out.txt
== true
>>


posted by:   Steven White     15-May-2017/10:38:26-7:00



R E B O L []    
while [error? try [write %testoutput.txt read %test-out.txt]][wait 00:00:05 print "waiting"]
halt

posted by:   Nick     15-May-2017/11:14:21-7:00



Instead of waiting for an error, I'd prefer to check for the actual condition:
    
R E B O L []    
while [not exists? f: %test-out.txt][wait 00:00:05 print "waiting"]
write %testoutput.txt read f
halt

posted by:   Nick     15-May-2017/11:19:58-7:00



BTW, I tend to use
    
if error? try []
    
instead of 'attempt, when watching for failures

posted by:   Nick     15-May-2017/20:44:16-7:00



In the balance of things, it is likely more useful if ATTEMPT was forced to a truthy result on non-failure:
    
     >> attempt []
     == #[true]
    
     >> attempt [any [false]]
     == #[true]
    
     >> attempt [1]
     == 1
    
This would make it more useful in conditional contexts, with the idea that conditionally false or void results in the expression are less interesting to the caller than a reliable question of whether an error was raised or not.
    
The Ren-C philosophy on these things is to make undecorated calls favor the return result ergonomics of casual use, while those using a version like ATTEMPT* would get at the raw form. So ATTEMPT*, then there is something like:
    
     to-true: func [x [ any-value!]] [ ;-- actually native
         either any [void :x | false? :x] [true] [false]
     ]
    
     attempt: chain [:attempt* | :to-true]
    
I've also wondered if a passive error result in TRAP (Ren-C's better analogue-to-CATCH word for TRY, e.g. TRAP/WITH and CATCH/WITH vs TRY/EXCEPT) should fail.
    
     >> trap [1 / 0]
     == make error! [... stuff about division by zero ...]
    
     >> trap [make error! "some error"]
     ** Error: Trap expression evaluated to error but did not FAIL
    
Similarly, TRAP* could avoid this protection and assume you knew what you were doing.
    
I know that these issues are only interesting to some people. I think those are the interesting people. We shall l e n n u t through. :-)

posted by:   Fork     16-May-2017/5:09:25-7:00