World: r4wp
[!REBOL3] General discussion about REBOL 3
older newer | first last |
Ladislav 15-Mar-2013 [2058x2] | Yes, that is what I guessed |
(but I did not test your LOOP, to be honest) | |
Gregg 15-Mar-2013 [2060x3] | And your approach with the bump overflow check is much cleaner. |
You can just run it, and it will dump tests and output to the console. | |
And mine uses CFOR as the internal loop handler. As I noted briefly, it's just a dialect wrapper over CFOR. | |
Ladislav 15-Mar-2013 [2063x4] | That is no problem with me, but I know that CFOR does not need to handle overflow leaving that to the programmer if needed |
(the important thing is that it is not needed in the great majority of cases) | |
However, FOR does not have this luxury | |
(which leads to slowness and overhead) | |
Gregg 15-Mar-2013 [2067x2] | Why can't you just convert FOR args to CFOR rules? |
Internally. | |
Ladislav 15-Mar-2013 [2069] | I do not think it could spare any effort |
Gregg 15-Mar-2013 [2070] | You mean the time to implement it? |
Ladislav 15-Mar-2013 [2071x2] | My tests are actually "preconditions" at least in the specification, but due to the overflow possibility I converted them to one precondition and one postcondition to be able to handle the arithmetic issues before they occur. |
once the condition allows another evaluation, I already know that the overflow does not occur and I can increment without taking any risk | |
Gregg 15-Mar-2013 [2073x3] | You lost me. Do you mean CFOR can't spare the effort to do the checks, or you can't spare the effort to create a version of FOR that uses CFOR? |
If Brian is OK with your new FOR, I think I am as well. I am also happy to refine my new LOOP func more, if people think there is value in it; as an alternative. | |
And I assume you will add support for other datatypes back into your FOR, beyond integers. | |
Ladislav 15-Mar-2013 [2076] | You lost me. - sorry, this looks to be caused by my bad English this time Do you mean CFOR can't spare the effort - actually, CFOR (its implementation) does not need to handle such issues leaving that to the programmer to handle only when needed regarding the "I do not think it could spare any effort" - the sentence should probably look as follows: "I do not think it (implementing FOR using CFOR) could save any effort" |
Gregg 15-Mar-2013 [2077] | Thanks for clarifying. And rememeber how much better your English is than my Czech. :-) My LOOP, using CFOR, is slower to set up, but much faster in the loop than FOR (incl your new FOR), so I thought it might be worth it. |
Ladislav 15-Mar-2013 [2078x2] | aha, interesting, did not make any measurements |
Would not have guessed that to be the case. Then it really may be worth trying. | |
Gregg 15-Mar-2013 [2080] | loop - 1 - 100'000 calls 0:00:02.108 for - 1 - 100'000 calls 0:00:00.508 loop - 1'000'000 - 1 call 0:00:00.304 for - 1'000'000 - 1 call 0:00:01.122 |
Ladislav 15-Mar-2013 [2081] | I suppose you use R2? |
Gregg 15-Mar-2013 [2082x10] | Yes. |
Let me see if I can test real quick with R3. My timing func uses LOOP. :-) | |
R3 results: loop - 1 - 100'000 calls 0:00:01.539 for - 1 - 100'000 calls 0:00:00.683 loop - 1'000'000 - 1 call 0:00:00.358 for - 1'000'000 - 1 call 0:00:01.144 | |
No special handling in mine for decimal step values. So under R3, that test will show this: [loop [i 0 1 0.2] [print i]] 0 0.2 0.4 0.6000000000000001 0.8 1.0 | |
For those not following closely, the discussion about FOR is trying to clarify and document its behavior, while keeping it easy to use (e.g., avoid accidental infinite loops). Ladislav has also asked for better names for CFOR, his general loop func that is efficient and flexible, but requires a bit more care in use. There is also a general consensus that FOR takes more args than we would like, while noting that we have other looping funcs we can use in most cases. I propose a new LOOP implementation that is compatible with the current LOOP func (and delegates to it internally), while also providing a dialected interface which is a wrapper to CFOR. | |
Goals: * Provide a general loop that is both friendly and flexible * Support multiple datatypes as FOR does today * Use CFOR internally for efficiency * Adhere to the latest model discussed here and on CC | |
Interface: LOOP compatible [loop 5 [print "x"]] REPEAT compatible [loop [i 5] [print i]] CFOR compatible (except for all args being in a block) [loop [[i: 1] [i <= 1000] [i: i + i]] [print i]] FOR compatible (except for all args being in a block) [loop [i 5 10 2] [print i]] Like FOR, but with a default bump of 1 [loop [i 5 10] [print i]] Or -1 if start is greater than end [loop [i 10 5] [print i]] | |
I've posted %mezz/new-loop.r here, but the implementation should be considered preliminary, as it was meant mainly to experiment with the interface, generating CFOR calls, and analyzing the new behavior spec in terms of test cases. It can and should be improved. | |
You don't need to look at %new-loop.r, but if you have any input on the above interface approach, or just want to post a NEW-LOOP: +1, -1, or 0 message, that would be great. | |
Note that the above examples are, themselves, in block, because I cut them out of my test cases. | |
Sunanda 15-Mar-2013 [2092] | Nice work, Gregg - thanks for doing all that. I am having trouble getting LOOP to do what FOR can do with a series: ser: [1 2 3 4 5 6 7] for v ser skip ser 5 2 [print v] 1 2 3 4 5 6 7 3 4 5 6 7 5 6 7 Neither of these work for me: loop [v ser skip ser 6 2] [print v] loop compose [v ser (skip ser 6) 2] [print v] |
Gregg 15-Mar-2013 [2093x2] | Good catch. I just added series support, and since it's a simple dialect, it won't like that. In the current version, you would have to use an interim var for 'end. e.g.: >> b: (skip ser 6) == [7] >> loop compose [v ser b 2] [print v] |
One of the downsides of dialects, and wanting to keep them simple. | |
Sunanda 16-Mar-2013 [2095] | Thanks Gregg. If FORing on a series is relatively uncommon, then (per curecode #666) losing the direct ability would be a good R3ish thing to do. I am little more concerned about LOOP set up needing COMPOSE in a way that existing looping constructs do not. The cost of creating simplicity in the language core should not be exporting complexity to the language users. |
Marco 16-Mar-2013 [2096x4] | my contribution to loop-for discussion: for-step: func [ {simplified for} [catch] 'word [word!] start [number!] end [number!] step [number!] body [block!] /local op result ][ do reduce [to set-word! :word start] if step = 0 [throw make error! "step parameter cannot be = 0"] op: either step > 0 [:lesser-or-equal?][:greater-or-equal?] while [op get word end][set/any 'result do body set word (get word) + step] get/any 'result ] for-step i 1 3 1 [print i] |
another contribution: use [count inc start end op][ count: inc: start: end: op: 0 in-range: func [ [catch] 'word [word!] start [number!] end [number!] /bump step [number!] /local result ] [ if inc = 0 [ if step = 0 [throw make error! "step parameter cannot be = 0"] count: start either start > end [inc: -1 op: :greater-or-equal?][inc: 1 op: :lesser-or-equal?] unless none? step [inc: step] ] set word count result: either op count end [count: (get word) + inc true][false] if not result [count: inc: start: end: op: 0] result ] ] i: 0 ; define a var while [in-range i 1 3] [print i] | |
about the Gregg's loop (on Rebol 2.7.8.3.1): >> probe cfor [num: 1] [num <= 3] [num: num + 1] [print num "a"] 1 2 3 4 ?? >> probe cfor [num: 1] [num <= 3] [num: num + 1] [if num = 2 [throw make error! "what 2?"] "a"] ; nothing printed nor error report | |
what about this?: cfor: func [ {General loop} [throw catch] init [block!] test [block!] inc [block!] body [block!] /local result ] [ do init while [do test] [set/any 'result do body do inc] get/any 'result ] | |
BrianH 16-Mar-2013 [2100x2] | The existing LOOP is used quite often, so any replacement for it won't go in R3 by default. However, the main reason LOOP is used is because it doesn't have the overhead that a lot of the other loops have, less than the other natives even. Its simplicity and definite form are its strengths - a loop with a more flexible form would be need to process that flexibility at runtime, which would add inefficiency that could easily be avoided by making that choice at development time by choosing the loop that meets your needs. And any loop construct that requires any kind of manual reducing of its arguments in order to have it take the result of an expression is a definite no-go. I just got rid of that in REWORD. I like http://issue.cc/r3/884as a replacement for FOR. It keeps the local binding (unlike Marco's CFOR above, sorry) and is flexible in behavior without being flexible in form (it has a very simple implementation). |
Watch out though, all mezzanine control structures that execute code blocks passed as parameters are be subject to http://issue.cc/r3/539 so they would need to be native until we have a solution to that. And not a command, because the necessary internal stuff isn't exported (purposely), so you couldn't do REWORD as a command. | |
Marco 16-Mar-2013 [2102] | In rebol 2.7.8.3.1 the #884 version has the same "strange behaviors" as the one that Gregg posted as a file here. |
BrianH 16-Mar-2013 [2103] | I just updated it to fix a couple more bugs; haven't read any of Gregg's comments so I don't know what those strange behavior are, but they might be fixed now. I am more a fan of its API style - we can fix any internal problems. |
Marco 16-Mar-2013 [2104] | ok, much better now, just add [catch] at the beginning and it will catch also errors. |
BrianH 16-Mar-2013 [2105] | No need, because this is an R3 function and R3 doesn't have [catch], it has better errors with stack traces instead. Improvement. |
Marco 16-Mar-2013 [2106] | Nice! I must try it sooner then later ;) |
BrianH 16-Mar-2013 [2107] | I had to get rid of [catch] in my first edit. And [catch] is a bad idea for loops because it hides where the real error is being triggered. |
older newer | first last |