Created
June 4, 2019 19:52
-
-
Save greggirwin/4dd6deb56dcba704bf6d418aff244373 to your computer and use it in GitHub Desktop.
Red Incr/Decr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Re: WRT: func ['name content][] | |
WRT incr { | |
The most common case will be to change state, but incr does add meaning, and has | |
benefits, in my mind, when used with scalars. | |
- By default, there is no step value, so you can't get the + 1 part wrong. | |
- Incr is often used when looping, making loop variables stand out from other add | |
ops that might be in expressions. | |
- Incr generally means the step is small. Another mental hint. | |
- If we use a lit-word! param how do you use a computed incr arg? | |
- It's not a terrible thing to use lit-word! params. They are a tool. But they can | |
make you think a bit more, especially in mixed expressions. For incr that may | |
not be as much of an issue, but it may be used a lot, and that means that many | |
more cases where a non-evaluated arg isn't directly visible when reading code. | |
} | |
incr: function [ | |
"Increments a value or series index" | |
value [scalar! series! any-word! any-path!] "If value is a word, it will refer to the incremented value" | |
/by "Change by this amount" | |
amount [scalar!] | |
][ | |
amount: any [amount 1] | |
if integer? value [return add value amount] ;-- This speeds up our most common case by 4.5x | |
; though we are still 5x slower than just adding | |
; 1 to an int directly and doing nothing else. | |
; All this just to be smart about incrementing percents. | |
; The question is whether we want to do this, so the default 'incr | |
; call seems arguably nicer. But if we don't do this it is at | |
; least easy to explain. | |
if all [ | |
integer? amount | |
1 = absolute amount | |
any [percent? value percent? attempt [get value]] | |
][amount: to percent! (1% * sign? amount)] ;-- % * int == float, so we cast. | |
case [ | |
scalar? value [add value amount] | |
any [ | |
any-word? value | |
any-path? value ;!! Check any-path before series. | |
][ | |
op: either series? get value [:skip][:add] | |
set value op get value amount | |
:value ;-- Return the word for chaining calls. | |
] | |
series? value [skip value amount] ;!! Check series after any-path. | |
] | |
] | |
decr: function [ | |
"Decrements a value or series index" | |
value [scalar! series! any-word! any-path!] "If value is a word, it will refer to the decremented value" | |
/by "Change by this amount" | |
amount [scalar!] | |
][ | |
incr/by value negate any [amount 1] | |
] | |
w: 1 | |
incr w | |
w | |
incr 'w | |
w | |
b: [1 2 3 x 4 y 5 z [6 7 8]] | |
incr b | |
b | |
incr 'b | |
b | |
incr 'b/1 | |
b | |
incr 'b/x | |
b | |
incr/by 'b/y 2 | |
b | |
incr 'b/z | |
b | |
incr 'b/z/1 | |
b | |
o: object [i: 0 b: [a b c]] | |
incr 'o/i | |
incr 'o/b | |
o | |
v: 1.2.3 | |
incr v | |
v | |
incr 'v | |
v | |
incr/by v 2.3.4 | |
incr #"A" | |
incr 1:2:3 | |
incr 1x2 | |
incr 1% | |
decr 10% | |
i: 0 | |
; i will now refer to 'i, just as if you'd done `i: 'i` | |
i: incr 'i | |
get i |
Lit-args, yes. The workarounds just aren't very nice.
% * int
Seems to be fixed now. This code is quite old.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You mean like this?
That forbids
incr incr x
but notincr (incr x)
- which can be better thanincr/by
with complex scalars like time.Do you have an example of this behavior?