World: r3wp
[Core] Discuss core issues
older newer | first last |
Geomol 15-Aug-2007 [8628] | James, are you after a search three? Do you know those data structures? Examples are binary search threes, B-threes, etc. |
BrianH 15-Aug-2007 [8629] | Do you mean tree? |
Geomol 15-Aug-2007 [8630] | Yes, of course! Tree! Sorry about that. |
james_nak 15-Aug-2007 [8631] | Actually I was just wanting to know if I was missing something in the way I am checking for a value within an object that is part of a block of objects. Nothing really sophisticated and these blocks are really small so no need for speed increases. To be frank, I often look at the code you all write and say to myself: " Self, how in the world did they think of that?" or "Oh, I didn't know you could do that." For example when I first started using Rebol, I didn't know about the "in" word as in "Get in object 'word.." so I was always using paths and trying to figure out how one would make the path a "variable." (object/mypath, where mypath could be some changing value). Thanks for your input though. |
Geomol 15-Aug-2007 [8632x2] | Maybe you could make a block with the titles and the objects together, and then just use a path to get to the object? Something like: >> movies: reduce ["Star Wars" make object! [status: 'good!] "Matrix" make object! [status: 'cool]] >> movies/("Star Wars")/status == good! >> movies/("Matrix")/status == cool |
I'm just throwing ideas! :-) Work with it. | |
james_nak 15-Aug-2007 [8634x2] | You see, stuff like that is very interesting to me. |
I didn't know you could use ( ) like that. | |
Geomol 15-Aug-2007 [8636] | I think, we were allowed to use () in paths in recent versions of REBOL. Not exactly sure when. |
james_nak 15-Aug-2007 [8637] | Why doesn't anyone tell me these things? : ) |
Rebolek 15-Aug-2007 [8638x2] | james_nak: http://www.rebol.com/article/0025.html:) |
it's almost three years...time runs so fast :))) | |
Gregg 16-Aug-2007 [8640] | Another thing to consider is that this is a general need, so FOREACH (e.g.) may be used, but you can hide it in a wrapper func, maybe called SELECT-ALL, that works like REMOVE-EACH. I have different variations, based on how other langs do it, e.g. select/inject in smalltalk. Here's a very quick way to leverage REVMOE-EACH. filter: keep-each: func [ "Keeps only values from a series where body block returns TRUE." 'word [get-word! word! block!] "Word or block of words to set each time (will be local)" series [series!] "Series to traverse" body [block!] "Block to evaluate. Return TRUE to collect." ] [ remove-each :word series join [not] to paren! body ] comment { filter x [1 2 3] [x = 2] filter x [1 2 3] [odd? x] filter res [1 2 3] [odd? res] filter [x y] [a 1 b 2 c 3] [all [odd? y 'c = x]] } |
james_nak 16-Aug-2007 [8641] | Thanks Gregg and Rebolek! |
Joe 17-Aug-2007 [8642] | pekr,sqlab, thank you for your answers. I thought that sync ports also had a timeout like the async kernel (set-modes port [timeout: 30]) but they do not. thanks |
Henrik 20-Aug-2007 [8643x2] | I may be the last to learn this, but I didn't know you could do this: >> type? first [none] == word! >> type? first [#[none]] == none! |
which is neat :-) | |
Geomol 21-Aug-2007 [8645] | Any thoughts on this? >> #"a" * 2 == #"Â" >> 2 * #"a" == 194 So multiply is commutative in a 'funny' way. In this example, you get the result in the same datatype as the first argument. This also works: >> #"a" * 2.0 == #"Â" But you can't do: >> 2.0 * #"a" ** Script Error: Cannot use multiply on decimal! value So multiply is not commutative, when it comes to decimals and chars. Any comments? Also think of other datatypes, you wanna multiply. |
Tomc 22-Aug-2007 [8646] | I think I would avoid using that feature often |
[unknown: 5] 29-Aug-2007 [8647] | I once heard that R2 doesn't allow you to free memory and that R3 will. Anyone know if we are able to free memory in R2? I think it was concerning a stats command discussion somewhere. |
btiffin 30-Aug-2007 [8648x2] | Paul; Check http://www.rebol.org/cgi-bin/cgiwrap/rebol/view-script.r?script=free-mem.r for a small blurb and a way to free memory in R2. |
Newer versions of REBOL allow a simple unset 'var recycle sequence. But GC is voodoo a lot of times, not just in REBOL, so there are probably cases that this won't apply. | |
DanielSz 30-Aug-2007 [8650x2] | Hi Rebol community, I was wondering about how you deal with error handling in Rebol in those situations where you have a number of network operations which are likely to fail part of the time. Of course, you already raised the timeout for network protocols (system/schemes/default/timeout: 0:10). Now say your script contains a number of network operations (read url, for example) wrapped in user functions. This is a very common situation. For example: fetch-actual-ip: does [ page: read-url-with-basic-auth http://192.168.1.1/Status.htm(http-basic-auth-key router_username router_password) parse page [thru <td class="stdbold" nowrap> copy ip to </td>] return to-tuple ip ] Now this is fine, but if your read operation fails, the script will abort. You would like the function to try again a couple of times. The first thing you would be tempted to do is to redefine the function to repeat the function in case of error or unexpected result. A recursive function like the next one may provide some solace: fetch-actual-ip: does [ page: read-url-with-basic-auth http://192.168.1.1/Status.htm(http-basic-auth-key router_username router_password) either none? tmp: find/tail page "ip address" [ print "Retrying..." retries: retries + 1 if retries > 10 [print "Retried 10 times. Exiting" quit] fetch-actual-ip ] [ parse tmp [thru <td class="stdbold" nowrap> copy ip to </td>] retries: 0 return to-tuple ip ] ] You might have a number of user functions and each can fail, so transforming every user function into a recursive one with its own error handling block can be tedious. Wouldn't it be better to abstract the process with a meta-function that accepts as input the user function itself? The error handling logic would then be exclusively handled by that meta-function, which will save you from redundancy if you have multiple user functions. Let's do it: retry: func [external_function [function!] retries [integer!] /local .retry [function!] tries [integer!] value] [ tries: 0 .retry: func [.external_function [function!]] [ either not error? try [value: .external_function] [ if not none? value [return value] ] [ print "Retrying..." tries: tries + 1 if tries > retries [print rejoin ["Tried function " tries " times. Exiting"] return] .retry :.external_function ] ] .retry :external_function ] Now you call the short version of fetch-actual-ip like this: retry :fetch-actual-ip 5 (try the user function 'fetch-actual-ip up to 5 times) Anyone wants to comment or improve on this? |
One difficulty is to refine the meta-function 'retry to accept user functions with a variable number of arguments. Tricky. Anyone got an idea? | |
Graham 30-Aug-2007 [8652] | provide the argument list in a block to the retry function |
Gregg 31-Aug-2007 [8653] | It can seem like more work, but and FSM based model works well IMO. |
Louis 31-Aug-2007 [8654x3] | From section 11.12 of the Core users manual: inp: open/binary/direct ftp://ftp.site.com/big-file.bmp out: open/binary/new/direct %big-file.bmp buf-size: 200000 buffer: make binary! buf-size + 2 while [not zero? size: read-io inp buffer buf-size][ write-io out buffer size ;<================<<< Where did size come from; this is incorrect, no? total: total + size print ["transferred:" total] ] |
Whoops! Watch out for wordwrap. | |
Sorry. I see it now. My mistake. | |
DanielSz 31-Aug-2007 [8657] | Exactly, Graham, argument passing in a block is a decent solution. I saw here and there rebol code implementing this for similar purposes. I'll repost a an updated 'retry version when I get around it. |
Louis 31-Aug-2007 [8658] | Attention whoever is in charge of documentation. Section 11.12 of the Core Users Manual give an example that will not work. A clear buffer statement is needed after the write-io line, and the ports need to be closed after sending each file. |
DanielSz 31-Aug-2007 [8659x4] | Gregg, do you mean Finite State Machine. Care to expand? |
Ok, here is an updated version of 'retry. What is it? It is a higher -level function that takes as input a user function and repeats it the number of times specified. The current version handles user functions that take arguments. | |
Usage: retry :user_function 5 For a user function that doesn't take arguments retry/args :user_function 5 [args] For a user function that take arguments retry: func [user_function [function!] retries [integer!] /local .retry [function!] tries [integer!] value [any-type!] args_length [integer!] /args block [block!]] [ tries: 0 args_length: length? first :user_function if ((args_length > 0) and (not args)) [print ["User function require" args_length "arguments. Provide them in a block and use the /args refinement."] return] if not args [args_length: 0 block: []] .retry: func [.user_function [function!]] [ either not error? try [value: do compose [.user_function (copy/part block args_length)]] [ if not unset? value [return value] ] [ print "Retrying..." tries: tries + 1 if tries > retries [print rejoin ["Tried function " tries " times. Exiting"] return] .retry :.user_function ] ] .retry :user_function ] Everybody is invited to improve on this. | |
I wrote 'retry to use in scripts heavy in network calls where failure is, by nature of the internet, common, so instead of aborting when such a failure occurs, I can use 'retry to repeat individual functions any number of times I wish, improving the success of the script. | |
Gabriele 1-Sep-2007 [8663x2] | >> retry: func [code times] [ [ loop times [ [ attempt [ [ break/return do code [ ] [ ] [ ] |
>> retry [1 / probe -1 + random 2] 5 0 1 == 1 | |
DanielSz 1-Sep-2007 [8665x5] | Very elegant, and concise, Gabriele. Maybe you can propise have an expanded version to handle arguments the code should be invoked with |
Sorry, I pressed Enter by mistake, here I go again: Very elegant, and concise, Gabriele. Maybe you can propose an expanded version that can handle arguments that the code should be invoked with. | |
That's what 'retry currently does. | |
If you provide that capabilty, I take your version in no time. Mine is too obscure. | |
Another requirement is tthat if the code returns a value, retry should return that exact same value as well. I believe your version currently doesn't. | |
Ingo 1-Sep-2007 [8670x2] | After reading about /no-set to reduce, is this an error? / inconsistency? >> reduce ['s: 3 * 3] == [s 9] |
shouldn't it be == [s: 9] ? | |
Gabriele 1-Sep-2007 [8672x3] | Daniel, since my version takes a block, you can pass as many args as needed. |
example: retry [user-function arg1 arg2 arg3 ...] 5 | |
of course, it could be enhanced by reporting the error instead of returning none if it fails more than the given times, and so on. | |
DanielSz 1-Sep-2007 [8675x3] | I was going to apologize to you, Gabriele, a few minutes ago I had the sudden realization that your version can indeed handle user-function with arguments, as your latest post explains. |
Your version really makes rebol shine. Its expressiveness is beyond par. Bravo. | |
Gabriele, just one thing, imagine the following user function: f1: func [] [return "f1 body"] | |
older newer | first last |