World: r4wp
[!REBOL3] General discussion about REBOL 3
older newer | first last |
Endo 12-Mar-2013 [1759] | * end_value + step_value |
Ladislav 12-Mar-2013 [1760] | Hmm, that is not convenient in some cases |
Endo 12-Mar-2013 [1761x2] | There is another issue; on R3: for i 1 3 0.2 [print i] ; prints 1 ... 2.8 (end value is not included) for i 3 1 -0.2 [print i] ; prints 3 ... 1.2 (end value is not included) on R2: for i 1 3 0.2 [print i] ; prints 1 ... 3 (both start & end value included) for i 3 1 -0.2 [print i] ; prints 3 ... 1 (both start & end value included) |
I think R2's behaviour is "more" correct. | |
Ladislav 12-Mar-2013 [1763x2] | for i 1 3 0.2 [print i] ; prints 1 ... 2.8 (end value is not included) - this is an arithmetic problem; 0.2 is not representable exactly by a binary floating point (i.e. decimal!) value. |
I do *not* recommend to use a general code for such loops | |
Endo 12-Mar-2013 [1765] | right, for i 1 3 0.1999999999999999 [print i] ; --> 1.0 ... 3.0 |
Gregg 12-Mar-2013 [1766] | This is an excellent question Ladislav. What if we start with the doc string: R2: Repeats a block over a range of values. R3: Evaluate a block over a range of values. That makes me think 'bump has to be non-zero, and it should throw an error. It should also throw an error (under R2) if 'start and 'end are series values and won't terminate (e.g. empty series). R3 does this now. That is, FOR should always terminate. R2 allows char! values, R3 does not. Under R2 specifying an 'end of #"ÿ" (char 255) also results in an endless loop. My RANGE func tests for that, because it caused me a problem at one point. |
BrianH 12-Mar-2013 [1767] | I think that we have two conflicting values here: * Do what I *say*, since you can't read my mind to know what I mean * Trigger errors when you run into something almost definitely wrong as a favor to the developer In the case of FOREACH, it triggers an error for an empty words block and doesn't allow none because that block is part of the control structure, not the data (which we do allow empty or none for). In the case of a block of only set-words, that also doesn't really advance, but at least you get a reference to the series so you could in theory be doing something (that you should probably use WHILE to do instead), so not triggering an error in that case is iffy, you could make an argument either way. For FOR, the main factor for whether the loop would normally end (without BREAK or changing the index manually somehow) is whether the step > 0 if start < end, or step < 0 if start > end. So it's not whether it = 0. |
Gregg 12-Mar-2013 [1768] | My preference, then, is to 1) throw an error or 2) never execute the loop. |
BrianH 12-Mar-2013 [1769] | Bad control parameters usually mean triggering an error in R3, to better help the developer with their debugging. We only do nothing for empty data, sometimes for values of "empty" that include none. |
Gregg 12-Mar-2013 [1770] | And since I mentioned RANGE (which I still think could be a useful datatype), how would we expect FOR to work in the context of a range! type? e.g., a range with bounds of 0 and 0. With regard to decimal 'bump values, I do allow them in my RANGE func, which uses FOR internally. It is one of the few places I do use FOR. |
BrianH 12-Mar-2013 [1771] | REPEAT would be used with the range, not FOR. FOR takes too many parameters. |
Gregg 12-Mar-2013 [1772x2] | Brian, yes. I vote for an error because FOR says, to me, that you expect the loop to terminate. If you want an infinite loop, use FOREVER to make that clear. |
Well, yes, REPEAT would be the clear choice, but if you have a range! and passed its lower and upper bounds to FOR, what would you expect? FWIW, I've always thought 'bump should have been a refinement option in FOR. | |
BrianH 12-Mar-2013 [1774] | Right. One thing we need to consider is whether we want changes to the index in the code block to affect the index of the loop, or whether we just want to do that with BREAK. There are advantages to either model. If manual changes to the index are ignored, it becomes safe to change in your code. If they aren't ignored, it becomes another way to affect the loop in your code. |
Gregg 12-Mar-2013 [1775] | Another fun question. :-) |
BrianH 12-Mar-2013 [1776] | If you have a range type (which was rejected, btw, but might get revisited) and you break out its upper and lower bounds so it can be passed to FOR's *two* parameters for those values, the programmer would still need to specify them as they see fit. |
Gregg 12-Mar-2013 [1777x2] | While I think it's a bad idea to mess with the index, there are reasons to allow it. I think manual changes should be allowed, but discouraged. |
On range!, my thinking is that the default would be a 'bump of 1 (next value in a series), because that's how I think of iterating over a range of values. | |
BrianH 12-Mar-2013 [1779] | We can't really discourage anything because we don't have "warnings" in Rebol (no way to implement them without a logging facility, and no point in logging them without a precompiler). It's allowed or it's not. If it's allowed (in R3 at least) it's because it's part of the intentioned model. |
Ladislav 12-Mar-2013 [1780] | We can't really discourage anything - I guess that Gregg mentions to discourage it in the documentation |
Gregg 12-Mar-2013 [1781] | Yes, in docs. |
Ladislav 12-Mar-2013 [1782] | (should be "means") |
BrianH 12-Mar-2013 [1783x3] | The range! type turned out to not actually be useful. You can stop adding a ! when referring to ranges :) |
So the question we're posing is whether we want the developer to be able to manually affect the FOR loop process from the inside (a feature, useful for advanced developers), or whether we want the loop process to be inviolate regardless of changes to the index in the code (another feature, useful for compilers that might want to unroll loops). Given that we don't have a compiler, that suggests that affecting it might be a useful feature, but Red compatibility and the overhead of checking the index value rather than just setting it based on an internal value in native code suggests that the latter might be better. There is no point in discouraging anything, since there is so much overhead to allowing it at all that we should only do so to provide a feature explicitly. | |
If you have the loop process inviolate then you can use a C value or even a raw value slot as an internal loop counter. If you want changes to the index in the code to persist, the loop would need to check that word after the loop cycle ends to determine its current value, then change that. That has overhead, like checking for and reacting to unset values, that just ignoring the word's value doesn't have. So if we want to allow it at all, it shouldn't be discouraged except as a potential gotcha, it should be considered a feature. | |
Maxim 12-Mar-2013 [1786] | in languages like C the for loop is the basic iterator and it should be completely open. but in REBOL we do have a lot of purpose-built iterators, I think FOR shoudn't allow non advancing steps and should't allow the inner loop to affect index. This would make FOR faster for its primary purpose. I don't see the point in trying to make every different iterator another interface to while/until |
Ladislav 12-Mar-2013 [1787] | in languages like C the for loop is the basic iterator and it should be completely open - actually, C does not have a FOR loop, it only have a general loop called for () |
Maxim 12-Mar-2013 [1788] | IMHO, differenciation of each iterator, increase their relative "relevance" in the language. |
BrianH 12-Mar-2013 [1789] | Whatever we choose with FOR, we should make REPEAT behave similarly in that same choice. Those two are in the same family. |
Ladislav 12-Mar-2013 [1790] | i.e. C language for () is not a FOR loop, in fact. it is a general loop |
BrianH 12-Mar-2013 [1791] | Ladislav, try to keep on topic. We're not talking about CFOR, we're talking about FOR :) |
Ladislav 12-Mar-2013 [1792] | It was Max who mentioned that |
BrianH 12-Mar-2013 [1793x3] | Back to the step argument: For FOR, the main factor for whether the loop would normally end is whether the step > 0 if start < end, or step < 0 if start > end. So it's not whether it = 0. We should allow one iteration when start = end, but trigger an error otherwise if we have a non-advancing step. Developers can just as easily use BREAK and such for an advancing step. |
Simply not doing anything is bad here because it makes the error much harder to track down. It's terrible for debugging. | |
Wait, I might be wrong about step. For start > end, if step is positive then FOR should do nothing. It should only trigger an error for 0. The step sign determines the direction of the FOR. | |
Maxim 12-Mar-2013 [1796x2] | exactly. it should only raise an error when the step = 0 |
I've used some languages that try to prevent ranges which are opposite to step (with an error) but I found that very annoying when playing with code which uses variables for start & end values. | |
BrianH 12-Mar-2013 [1798x3] | Do we have enough factors to make some tests and tickets for FOR? I'm not sure whether we came to an agreement about the changing index issue, so that might be worth an issue ticket (assuming this conversation will disappear because we're in AltME, not CureCode). |
I can make the tickets later today - it just looks like two, one for step, one for index-changing. | |
Sorry, bump. Don't know why I thought it was called step. | |
Bo 12-Mar-2013 [1801x3] | I think that 'for should be as flexible as possible. One of the main problems IMHO of most programming languages and software systems is designed inflexibility. |
Let's say that I have two series that are the same length, and the values at each position of each series are related to each other. What if I want to use a 'for loop to increment through the first series, but in some cases, depending on the value of the first series, I want to skip x values ahead, and on other values, I want to access that same position in the second series and perform an action on it. Why couldn't I use a 'for loop to do this if I wanted? | |
It would be sad if 'for was designed to disallow me from doing this. | |
BrianH 12-Mar-2013 [1804] | Well, FOR isn't a general loop like in C, it's just an iterator. If we need a general loop we should add one, even though general loops are more expensive to use in interpreted languages than specific loops (which is why we have specific loops rather than one general loop). However, "I want to skip x values ahead" does sound like an argument for allowing index changes to affect the looping process, as a power-user feature. |
MarcS 12-Mar-2013 [1805x2] | (Sorry for the tangent:) Can anyone reproduce http://curecode.org/rebol3/ticket.rsp?id=1974 on OSX? For me, I obtain the expected result on OSX and see the erroneous 9.9.9 under Linux. |
s/For me, // | |
Maxim 12-Mar-2013 [1807] | Bo, I'd say don't use FOR its just about the worse fit for that algorithm . :-) |
BrianH 12-Mar-2013 [1808] | I came up with two models for the start/end/bump situation, both of which make sense. We can pick the one we like the most. I'll put it in the ticket. |
older newer | first last |