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

Don't understand "try" and "disarm"

 [1/19] from: swhite:ci:bloomington:mn:us at: 14-Mar-2006 7:44


I am writing a very simple script to transfer a file when a button is clicked on a screen. It works fine. The procedure to send the file is basically this (the SOURCE-FILE is an ftp url, the DESTINATION-FILE is a local file name): TRANSFER-FILE: does [ write/binary DESTINATION-FILE read/binary SOURCE-FILE alert "File has been transferred" ] Now I want to add an error check in case the file does not exist, the directory structure is changed, or something like that, so the script doesn't just stop. I am trying to approach it a step at a time so I know what I am doing. I read the dictionary entries for try and disarm and thought I could do the following as my first step toward thorough error detection: TRANSFER-FILE: does [ FTP-RESULT: try [ write/binary DESTINATION-FILE read/binary SOURCE-FILE ] alert "File has been transferred" ] ...and then, after the write-read operation, I would check if FTP-RESULT was an error value, and if so, disarm it and check its various parts. But when I run the script as above (with the "try"), I get the error: FTP-RESULT needs a value Could someone explain, in simple terms, this try-disarm business, or tell me the appropriate way to do what I am trying to do, which is to catch an error in my file transfer process so the script doesn't just crash? Thank you. Steven White City of Bloomington 1800 W Old Shakopee Rd Bloomington MN 55431-3096 USA 952-563-4882 (voice) 952-563-4672 (fax) steven.white-ci.bloomington.mn.us

 [2/19] from: petr:krenzelok:trz:cz at: 14-Mar-2006 15:03


Hi Steven, a bit confusing, isn't it? In fact, some time ago, I just did the same mistake. I expected 'try to catch the error. Well, it does so, but it returns it. I don't like the way it work, but it is so, so let's just find some way out from it - ->> try [read %nonexistant.txt] ** Access Error: Cannot open /c/rebol/view/nonexistant.txt ** Near: read %nonexistant.txt ->> error? try [read %nonexistant.txt] == true You can see? 'try is there just to catch the error, but you still have to somehow maintain it. Single 'error? is enough for script not to crash, let's rewrite it a bit: ->> if error? try [read %nonexistant.txt][print "file does not exist"] file does not exist It seems to me, the error is returned from 'try call to the interpreter. We can "catch" it using 'disarm function: ->> probe disarm try [read %nonexistant.txt] make object! [ code: 500 type: 'access id: 'cannot-open arg1: "/c/rebol/view/nonexistant.txt" arg2: none arg3: none near: [read %nonexistant.txt] where: none ] I think you was not alone, who was a bit confused, so we've got some shortcuts in some later Core releases - 'attempt function: ->> attempt [read %nonexistant.txt] == none Attempt is a mezzanine function (defined in rebol): ->> 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 you can proceed from that further .... Cheers, -pekr-

 [3/19] from: swhite:ci:bloomington:mn:us at: 14-Mar-2006 9:33


Really, it is quite amazing to post a programming question and get an answer from someone who is (it seems) half-way around the world. I don't always get and answer as quickly from the next desk. I have used the tips I have received and have isolated my problem in the following test script: ;;;;; start of test script REBOL [ ] TRANSFER-FILE: does [ either error? FTP-RESULT: try [ ;;;; read %nonexistent.txt ;;;;; this file does NOT exist ;;;; read %fileexists.txt ;;;;; This file DOES exist write %tempfile.txt read %fileexists.txt ] ;;;;;; -- There was some error [ FTP-ERROR-OBJECT: disarm FTP-RESULT FTP-ERROR-MESSAGE: rejoin [ "The file was not transferred." " The REBOL interpreter returned the following message: " to-string FTP-ERROR-OBJECT/id ] alert FTP-ERROR-MESSAGE ] ;;;;;; -- There was no error [ alert "The file was read successfully" ] ] view layout [ title "Test the script" button "GO" [TRANSFER-FILE] ] ;;;;; end of test script Here is the problem: In the "try" block I have three different operations, (1) reading a file that does not exist, (2) reading a file that does exist, and (3) reading a file that exists and writing it to a new file. I comment-out two of the three in various combinations to find out what does not work. If I read a file that does not exist, the script works. If I read a file that does exist, the script works. If I use the third test, reading a file and then writing it, the script crashes with the following message:
>> do %trytest.r
** Script Error: FTP-RESULT needs a value ** Where: TRANSFER-FILE ** Near: either error? FTP-RESULT: try [ write %tempfile.txt read %fileexists.txt ]
>>
Can anyone explain why this happens? Thank you.
>>> petr.krenzelok-trz.cz 3/14/2006 8:03 AM >>>
Hi Steven, a bit confusing, isn't it? In fact, some time ago, I just did the same mistake. I expected 'try to catch the error. Well, it does so, but it returns it. I don't like the way it work, but it is so, so let's just find some way out from it - ->> try [read %nonexistant.txt] ** Access Error: Cannot open /c/rebol/view/nonexistant.txt ** Near: read %nonexistant.txt ->> error? try [read %nonexistant.txt] == true You can see? 'try is there just to catch the error, but you still have to somehow maintain it. Single 'error? is enough for script not to crash, let's rewrite it a bit: ->> if error? try [read %nonexistant.txt][print "file does not exist"] file does not exist It seems to me, the error is returned from 'try call to the interpreter. We can "catch" it using 'disarm function: ->> probe disarm try [read %nonexistant.txt] make object! [ code: 500 type: 'access id: 'cannot-open arg1: "/c/rebol/view/nonexistant.txt" arg2: none arg3: none near: [read %nonexistant.txt] where: none ] I think you was not alone, who was a bit confused, so we've got some shortcuts in some later Core releases - 'attempt function: ->> attempt [read %nonexistant.txt] == none Attempt is a mezzanine function (defined in rebol): ->> 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 you can proceed from that further .... Cheers, -pekr-

 [4/19] from: swhite:ci:bloomington:mn:us at: 14-Mar-2006 9:58


Well, I am slowly beginning to understand my own question. The previously-submitted test script left out the obvious fourth option of trying to read a file that does NOT exist and then writing it. That operation "works" also, as in reporting the error of the file not existing. (The revised script is at the end of the message.) Of the four options, the script crashes when it tries to read a file that DOES exist and write it to another file. It crashes only when it works. According to the REBOL dictionary, "try" returns either an error or THE RESULT OF THE BLOCK. So, if I comment-out things so the script tries to read a file that does not exist, FTP-RESULT is an error. If I comment-out things so the script just reads a file that does exist, FTP-RESULT is a a string. A string is the result of reading a text file. The script crashes when it tries to write a file. What is the "result" of a block that writes a file? That, perhaps, is what I don't understand. My actual mission is to write a script that transfers a file from one computer to another by FTP, and not crash if the file is not there, or if the transfer fails in some way. Maybe I am trying to do this the wrong way. Thank you for any advice. ;;;; revised test script REBOL [ ] TRANSFER-FILE: does [ either error? FTP-RESULT: try [ ;;;; read %nonexistent.txt ;;;;; this file does NOT exist ;;;; read %fileexists.txt ;;;;; This file DOES exist ;;;; write %tempfile.txt read %nonexistent.txt write %tempfile.txt read %fileexists.txt ;;;; this crashed ] ;;;;;; -- There was some error [ FTP-ERROR-OBJECT: disarm FTP-RESULT FTP-ERROR-MESSAGE: rejoin [ "The file was not transferred." " The REBOL interpreter returned the following message: " to-string FTP-ERROR-OBJECT/id ] alert FTP-ERROR-MESSAGE ] ;;;;;; -- There was no error [ alert "The file was read successfully" ] ] view layout [ title "Test the script" button "GO" [TRANSFER-FILE] ] ;;;; end of test script Steven White City of Bloomington 1800 W Old Shakopee Rd Bloomington MN 55431-3096 USA 952-563-4882 (voice) 952-563-4672 (fax) steven.white-ci.bloomington.mn.us

 [5/19] from: greggirwin:mindspring at: 14-Mar-2006 9:12


Hi Steven, This is pretty easy, once you know the trick. First, though, I'll ask if you've looked into using EXISTS? ? SW> TRANSFER-FILE: does [ SW> either error? FTP-RESULT: try [ SW> ;;;; read %nonexistent.txt ;;;;; this file does NOT exist SW> ;;;; read %fileexists.txt ;;;;; This file DOES exist SW> write %tempfile.txt read %fileexists.txt SW> ] TRY returns the result of the block evaluation; in this case, the result of WRITE. Fire up a console and see what WRITE returns. Now, try assigning that value using a set-word!, like the above code. What's happening is that WRITE returns an unset! value, which doesn't work directly with set-word! syntax. You need to use SET/ANY. e.g.: either error? set/any 'FTP-RESULT try [ write %tempfile.txt read %fileexists.txt ] HTH! -- Gregg

 [6/19] from: swhite::ci::bloomington::mn::us at: 14-Mar-2006 10:46


Thank you. It did not register in my old-fashioned brain that one could do an existence check across the network. I tossed out all the "try" stuff and just checked to see if the source file and the target directory existed before I allowed any file transfer. This "set-word" concept is a bit confusing, but I am going to wait with my criticism of the REBOL documentation until I have re-read it, plus the two books I have purchased. Then I'll complain.
>>> greggirwin-mindspring.com 3/14/2006 10:12 AM >>>
Hi Steven, This is pretty easy, once you know the trick. First, though, I'll ask if you've looked into using EXISTS? ? SW> TRANSFER-FILE: does [ SW> either error? FTP-RESULT: try [ SW> ;;;; read %nonexistent.txt ;;;;; this file does NOT exist SW> ;;;; read %fileexists.txt ;;;;; This file DOES exist SW> write %tempfile.txt read %fileexists.txt SW> ] TRY returns the result of the block evaluation; in this case, the result of WRITE. Fire up a console and see what WRITE returns. Now, try assigning that value using a set-word!, like the above code. What's happening is that WRITE returns an unset! value, which doesn't work directly with set-word! syntax. You need to use SET/ANY. e.g.: either error? set/any 'FTP-RESULT try [ write %tempfile.txt read %fileexists.txt ] HTH! -- Gregg

 [7/19] from: volker::nitsch::gmail::com at: 14-Mar-2006 21:29


either error? set/any 'FTP-RESULT try [ write %tempfile.txt read %fileexists.txt ] or either error? FTP-RESULT: try [ write %tempfile.txt read %fileexists.txt 'worked ; we return something "real" ] On 3/14/06, Steven White <swhite-ci.bloomington.mn.us> wrote:
<snip> > > This "set-word" concept is a bit confusing, but I am going to wait with > my criticism of the REBOL documentation until I have re-read it, plus > the two books I have purchased. Then I'll complain. > > >>> greggirwin-mindspring.com 3/14/2006 10:12 AM >>> >
-- -Volker Any problem in computer science can be solved with another layer of indirection. But that usually will create another problem. David Wheeler

 [8/19] from: gabriele::colellachiara::com at: 15-Mar-2006 12:43


Hi Steven, On Tuesday, March 14, 2006, 5:46:39 PM, you wrote: SW> This "set-word" concept is a bit confusing, but I am going to wait with SW> my criticism of the REBOL documentation until I have re-read it, plus SW> the two books I have purchased. Then I'll complain. Try something like this at the console: word: write %file "something" word: print "hello" HTH, Gabriele. -- Gabriele Santilli <gabriele-rebol.com> --- http://www.rebol.com/ Colella Chiara software division --- http://www.colellachiara.com/

 [9/19] from: tim-johnsons:web at: 15-Mar-2006 7:42


* Gabriele Santilli <gabriele-colellachiara.com> [060315 02:54]:
> Hi Steven, > On Tuesday, March 14, 2006, 5:46:39 PM, you wrote:
<<quoted lines omitted: 4>>
> word: write %file "something" > word: print "hello"
Hi Steven: A rebol 'word is a symbol. It may or it may not have a value, if it has no value it is considered unset. Lisp programmers understand this instinctively, but for the rest of us, it is best to take it one step at a time. It took me a long time to understand coming from C/C++ When you follow Gabrielle's instructions, you will get an error, but do not be dismayed. Here's a copy of an annotated console session for you which expands a bit:
>> word: print "hello"
hello ;; print sends "hello" to stdout ** Script Error: word needs a value ** Near: word: print "hello" ;; but you get an error, because the set-word word: expects a return ;; value but print does not return any value ;; now let us use the unset? predicate to test for a return value
>> unset? print "hello"
hello == true
>> help unset?
USAGE: UNSET? value DESCRIPTION: Returns TRUE for unset values. UNSET? is an action value. ARGUMENTS: value -- (Type: any-type) Now try it youself. I could say more, like how helpful this concept can be, but let's take it one step at a time. Once that sinks in a bit, we can show you some really cool tricks with words that may make you never want to use another language again. Or maybe lisp. :-) HTH tim -- Tim Johnson <tim-johnsons-web.com> http://www.alaska-internet-solutions.com

 [10/19] from: carlos:lorenz:g:mail at: 15-Mar-2006 14:16


Gabriele Interesting. I have never tried this before. By otherhand if I use set/any as in
>> set/any 'word print "hello"
I have no error but either cannot probe 'word Any ideas on how to to know what 'word has in it after set/any ?
> >>Try something like this at the console: > > >> word: write %file "something" > > >> word: print "hello" >
-- *:-.,_,.-:*'``'*:-.,_,.-: Carlos Lorenz *:-.,_,.-:*'``'*:-.,_,.-:

 [11/19] from: greggirwin:mindspring at: 15-Mar-2006 10:42


Hi Carlos, CL> By otherhand if I use set/any as in
>>> set/any 'word print "hello"
CL> I have no error but either cannot probe 'word CL> Any ideas on how to to know what 'word has in it after set/any ?
>> set/any 'word print "hello"
hello
>> value? 'word
== false -- Gregg

 [12/19] from: massung::gmail::com at: 15-Mar-2006 11:51


Something that might help a bit is to understand how symbols work internally. I'm going to describe this from the way Lisp does it (as I assume REBOL is the same, or just slightly modified). Regardless, the principle is the same and may help. Symbols (or words) do not have values. Instead, they are *bound* to values. It might help to think of this binding as an added level of indirection. If you were to implement a [crude] version of this in C++, it might looks something like this: enum value_type { VT_NUMBER, VT_STRING, VT_URL, VT_WORD, /* ... */ }; struct bind_slot { value_type type; void* value; }; map<string, bind_slot*> symbol_table; That bind_slot is important for several reasons: - a symbol can exist without being bound to anything - a symbol doesn't have a type - based on implementation, data doesn't have a type! Also, the bind_slots can act as a kind of reference. Two symbols can point to the same bind_slot. I think this is much easier to test around and play with in Lisp than in REBOL, but the priciples are the same. One important concept that REBOL can simulate, but doesn't have intrinsically, that I miss from Lisp is that of keywords. Keywords (in Lisp) are symbols that are bound to themselves. This is used for many things, but most commonly for enumerated values. HTH, Jeff M. -- massung-gmail.com On 3/15/06, Tim Johnson <tim-johnsons-web.com> wrote:

 [13/19] from: tim-johnsons:web at: 15-Mar-2006 10:53


* Jeff Massung <massung-gmail.com> [060315 09:05]:
> One important concept that REBOL can simulate, but doesn't have > intrinsically, that I miss from Lisp is that of keywords. Keywords (in Lisp) > are symbols that are bound to themselves. This is used for many things, but > most commonly for enumerated values. >
;; Do you mean like this:
>> test: [a 1 b "two" c 3.3]
== [a 1 b "two" c 3.3]
>> select test a
** Script Error: a has no value ** Near: select test a
>> test test 'a ;; word must be quoted
== a
>> test/a ;; if 'placeholder' is word, can be path
== 1
>> test/b
== "two"
>> test/c
== 3.3 ;; ;; Or this (I know a little lisp, but know python better def td(**kw): for k in kw: ## do something with k, but check against ## internal dictionary print td(bgcolor="red",align="right",data="cell contents") Can be emulated in rebol, but haven't tried it. tim -- Tim Johnson <tim-johnsons-web.com> http://www.alaska-internet-solutions.com

 [14/19] from: massung:gm:ail at: 15-Mar-2006 14:05


Wow! I didn't know REBOL supported associated lists like that. That's very cool. :-) Regarding Lisp keywords, no. Here's some Lisp code to consider:
>> :im-a-keyword
== :im-a-keyword
>> (eval :im-a-keyword)
== :im-a-keyword This is because keywords are symbols bound to themselves. In REBOL I can simulate them like so:
>> foo: 'foo
== foo
>> do foo
== foo It's possible that I only miss this in REBOL because there are still gaps in knowledge I have as to when REBOL evaluates and when it doesn't. I'm getting the hang of it more, but still having trouble. Consider the following sample code to print a tile on an Othello board: ;; assume "tile" is none, white, or black switch/default tile [ 'white [ prin "X "] 'black [ prin "O "] ] [ prin ". " ] Simple enough. Only it isn't obvious that this is wrong. 'white and 'black aren't ever evaluated, so there is no need for the quote. But, written without the quote it looks like I might be comparing against the RGB tuple. Keywords eliminate this ambiguity, because evaluated or not, they are always the same. I hope that makes sense. Jeff M. On 3/15/06, Tim Johnson <tim-johnsons-web.com> wrote:
> * Jeff Massung <massung-gmail.com> [060315 09:05]: > >
<<quoted lines omitted: 19>>
> >> test/c > == 3.3
-- massung-gmail.com

 [15/19] from: tim-johnsons:web at: 15-Mar-2006 12:09


* Jeff Massung <massung-gmail.com> [060315 11:20]:
> Wow! I didn't know REBOL supported associated lists like that. That's very > cool. :-) > > > == [a 1 b "two" c 3.3] > > >> test/a ;; if 'placeholder' is word, can be path > > == 1
Rebol documentation is constantly being upgraded. I can't recall if this is even included in the most current docs that I have. It's easy enough to convert the block above to a context also: as in ;; untested code!!!! o: copy [] foreach [k v] test[append o reduce[to-set-word k get/any v]] make object! compose o NOTE: this functionality is bundled in a function that has dependencies, so actual code might muddy the waters. tim -- Tim Johnson <tim-johnsons-web.com> http://www.alaska-internet-solutions.com

 [16/19] from: gabriele:colellachiara at: 15-Mar-2006 22:22


Hi Jeff, On Wednesday, March 15, 2006, 6:51:58 PM, you wrote: JM> One important concept that REBOL can simulate, but doesn't have JM> intrinsically, that I miss from Lisp is that of keywords. Keywords (in Lisp) JM> are symbols that are bound to themselves. This is used for many things, but JM> most commonly for enumerated values. I'm not a Lisp expert... how much are Lisp's keywords different from:
>> keyword: 'keyword
== keyword
>> keyword
== keyword Anyway, this thread might be helpful: http://www.rebol.org/cgi-bin/cgiwrap/rebol/ml-display-thread.r?m=rmlKVVC Regards, Gabriele. -- Gabriele Santilli <gabriele-rebol.com> --- http://www.rebol.com/ Colella Chiara software division --- http://www.colellachiara.com/

 [17/19] from: gabriele::colellachiara::com at: 15-Mar-2006 22:28


Hi Jeff, On Wednesday, March 15, 2006, 9:05:05 PM, you wrote: JM> Simple enough. Only it isn't obvious that this is wrong. 'white and 'black JM> aren't ever evaluated, so there is no need for the quote. But, written JM> without the quote it looks like I might be comparing against the RGB tuple. JM> Keywords eliminate this ambiguity, because evaluated or not, they are always JM> the same. I see your point, although the reason REBOL does not have this is that basically nothing is evaluated unless specifically noted otherwise. I can understand the confusion this can create though. I wonder if it would be useful to have a keyword! datatype in REBOL; I must say that in so many years I never felt the need for it. Regards, Gabriele. -- Gabriele Santilli <gabriele-rebol.com> --- http://www.rebol.com/ Colella Chiara software division --- http://www.colellachiara.com/

 [18/19] from: massung:g:mail at: 15-Mar-2006 15:33


I don't think they are needed by any stretch, they just make things easier. I don't think REBOL needs a keyword! datatype. I think think syntax to do:
>> foo: 'foo
would be handy. In Lisp, this is the ':' token, but in REBOL this is used as [almost] a synonym for get. Using some other token might make things easier. Just a method of auto-interning a new symbol that is automatically set to point to itself when evaluated. Jeff M. On 3/15/06, Gabriele Santilli <gabriele-colellachiara.com> wrote:
> Hi Jeff, > On Wednesday, March 15, 2006, 9:05:05 PM, you wrote:
<<quoted lines omitted: 20>>
> To unsubscribe from the list, just send an email to > lists at rebol.com with unsubscribe as the subject.
-- massung-gmail.com

 [19/19] from: carlos::lorenz::gmail::com at: 17-Mar-2006 8:38


Gregg Again I was doing it in the wrong way because I was testing word not 'word and value? word gives an error Thanks
>> set/any 'word print "hello" > hello > >> value? 'word > == false >
-- *:-.,_,.-:*'``'*:-.,_,.-: Carlos Lorenz *:-.,_,.-:*'``'*:-.,_,.-:

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