REBOL 3.0

Comments on: Do we dare add ++ and -- ?

Carl Sassenrath, CTO
REBOL Technologies
7-Feb-2007 20:30 GMT

Article #0057
Main page || Index || Prior Article [0056] || Next Article [0058] || 41 Comments || Send feedback

Here's a question to think about for 3.0. (I'm sure I asked this before, but let's revisit it again).

Do we dare add the C-style ++ and -- functions as a standard part of REBOL 3.0?

 Advantagea handy shortcut used by most C programmers.
 Disadvantagemodifies a word without using the SET-WORD notation (of course, you can already do that in REBOL) and adds noise to expressions (looks like an infix operator, but is not -- see examples at end).

Examples:

count: 0
++ count ; add one
-- count ; sub one

Notes:

  1. increments or decrements value by one
  2. returns the new value
  3. could also be allowed for series values to change index position
  4. only prefix. No postfix form (e.g. n ++).
  5. function precedence, same as negate. (Makes it less useful in non paren expressions.)

Example of last point, this is not valid:

if ++ count > 10 [...]

Just like you cannot write:

if negate count > 10 [...]

You either need to use prefix, reverse the comparison, or paren it:

if greater? ++ count 10 [...]
if 10 <= ++ count [...]
if (++ count) > 10 [...]

So, there you are. Useful or not useful as a standard part of REBOL? Tell us.

41 Comments

Comments:

Henrik
7-Feb-2007 16:13:13
I think it would be confusing, if it didn't work like in C. Using assembler style words like INC or DEC or just plain out INCREASE or DECREASE make more sense to me.
Maxim Olivier-Adlhoch
7-Feb-2007 17:12:10
I second henrik's observation. anyone can just rename the function later in his code, as long as that function (native :-) exists.

I've been missing in-place index skipping for a long time. Somehow I've always thought skip should not have needed the set notation.

skip myserie 3

should modifiy myserie directly. (and return the value)

Volker
7-Feb-2007 17:14:20
Other syntax: count: + 1 ?
tomc
7-Feb-2007 17:19:25
if it is not a native with a good performance boost I could do without it. if there is a good performance boost using if 10 = ++ count [...] seems painless.

there is also the confusion brought in by pre/post inc it looks like pre so a C programmer may expect the behavior to be "use the current value first then increment"

Brian Hawley
7-Feb-2007 17:53
I like the idea of these, as long as they are native and atomic actions (for threading purposes). I prefer the INC and DEC words for this, instead of ++ and --, because these act like native functions rather than the C operators. REBOL operators don't have side effects, so far.

You could always do ++: :inc and --: :dec if you really prefer those words.

John Niclasen
7-Feb-2007 18:49:48
Is it possible to make functions with current REBOL, that does what ++ and -- are supposed to do? That is: take a value, add one and expose the result to the context, where the function was called, so the original value is changed?

Does it makes sense to do this: ++ 4

The answers to my questions might give a clue, if it's a good idea or not. Isn't this a completely new concept to REBOL?

John Niclasen
7-Feb-2007 19:02:08
I came to think of op! datatypes. Afaik it isn't possible to make new operators (of type op!). Why not? If ++ and -- (or INC and DEC or whatever) are introduced, I would expect programmers would like to make their own, which does other things.

So if only ++ and -- are added, and no other functionality in that sense is added to the language, maybe it isn't such a good idea!?
Brian Hawley
7-Feb-2007 19:41:27
John, you could do ++ in REBOL code, although it would look different when applied to variables, be slower than a native version, and not be atomic.

I would like INC x to be a native equivalent to this pseudo-REBOL:

inc: func ['x /local y] [
    y: either word? :x [get x] [:x]
    case [
        series? :y y: next :y
        number? :y y: y + 1
        true return :y
    ]
    either word? :x [set x :y] [:y]
]
But more optimized, of course.
Anton Rolls
7-Feb-2007 19:55:19
I agree with the general feeling above. But the expression I would like to optimize the most is this one:
count: count + 1
which probably means I moreso want INC and DEC, which modify the word. What is the reason why ++ could not be made postfix ? We have infix operators, why not postfix ?
Peter Wood
7-Feb-2007 20:09:05
inc count seems so much more natural than count: count + 1.

Yes please.

Chris
7-Feb-2007 21:17:02
Brian, don't forget path! --

++ timer/count

Oldes
7-Feb-2007 22:47:44
In my rebol/flash dialect I have var++ and var-- which is compiled into much more efficient code than just (var: var + 1), but now as I see in Rebol I would prefer Brian's versions = I would rather use INC and DEC instead of ++/-- which can be confusing. And I really like Chris' path example. Of course we are talking about native version, as non native we can do even now.
Oldes
7-Feb-2007 22:51:37
sorry, I see the first was Henrik with the INC and DEC instead of ++/-- and I agree, that if it's not exactly like in C, I would not use ++/-- even when it's 2 chars shorter notation :-)
Oldes
7-Feb-2007 22:53:56
And I really like, that it could be used for series as well, as it's much more shorter than (var: next var)
Marco (Coccinelle)
8-Feb-2007 3:23:44
Would be nice if ++ behave like this :
>> f: does [print ++ 0]
>> f
1
>> f
2
>> f
3
...
Maarten
8-Feb-2007 7:31:55
Carl, I am opposed this because you *can* add it on the REBOL level, which in the end always boils down to less porting and more ports of REBOL.

In other words: if it is not in the functional domain where e.g. closures, apply, task! exist don't add it natively. Enhancing REBOl is best done in REBOL ;-)

John Niclasen
8-Feb-2007 10:56:58
Brian, of course! That's the way to do it. There are so many tricks in REBOL, that I forget about some of them from time to time.

I think, I'm for prefix INC and DEC, and that they should work on many datatypes.
John Niclasen
8-Feb-2007 11:37:32
Should there also be long versions of INC and DEC, that takes two arguments, like:

increase value 4

which will increase value by 4?

Brian Hawley
8-Feb-2007 12:13:18
Maarten, INC/DEC are really low level operations, and even optimized, my function is still a lot slower than the equivalent REBOL code with no function wrapped around it. Interpreter overhead is still significant for things like this. There are other operations that are being made native for performance reasons as well, like APPEND.
Brian Hawley
8-Feb-2007 14:53:39
I notice that this function, like all REBOL functions, returns the rvalue rather than the lvalue. Because of this you can't chain calls to these functions together. As such, I would have to agree with John about the need for his proposed longer versions as well.

Updated REBOL equivalent, tested on recent versions:

increment: func [
    [catch] 'x "Value to increase"
    y [integer!] "Amount to increase by"
    /local t
] [
    throw-on-error [
        if path? :x [
            x: in do copy/part :x back tail? :x last :x
        ]
        t: either any [word? :x paren? :x] [do :x] [:x]
        case [
            series? :t (t: skip :t y)
            number? :t (t: t + y)
        ]
        either word? :x [set/any x :t] [:t]
    ]
]
inc: func [[catch] 'x] [increment :x 1]
dec: func [[catch] 'x] [increment :x -1]
decrement: func [
    [catch] 'x "Value to decrease"
    y [integer!] "Amount to decrease by"
] [increment :x negate y]
These functions would have problems when their first argument is the result of a function call - evaluation would not be what you expect. This kind of thing would only come up when doing metaprogramming though, and you can solve this by wrapping the function call in a paren.

If you want more normal (for REBOL) evaluation, you can require that people use lit-word! or lit-path! at the call of these functions, and change them to look like this:

increment: func [
    [catch] x "Value to increase"
    y [integer!] "Amount to increase by"
    /local t
] [
    throw-on-error [
        if path? :x [
            x: in do copy/part :x back tail? :x last :x
        ]
        t: either word? :x [do :x] [:x]
        case [
            series? :t (t: skip :t y)
            number? :t (t: t + y)
        ]
        either word? :x [set/any x :t] [:t]
    ]
]
inc: func [[catch] x] [increment :x 1]
dec: func [[catch] x] [increment :x -1]
decrement: func [
    [catch] x "Value to decrease"
    y [integer!] "Amount to decrease by"
] [increment :x negate y]
Note that this would confuse people used to programming in other languages. For example:
>> a: 1
== 1
>> inc a
== 2
>> a
== 1
>> inc 'a
== 2
>> a
== 2
Because of that confusion under more the more common case, I prefer the prior version of these functions.

Of course, this all an example. Function call and evaluation overhead of these functions would make them more worth inlining than calling. They would only make sense to use if they were natives.

Brian Hawley
8-Feb-2007 18:10:14
Please fix the above code: I meant
back tail
instead of
back tail?
in both versions of the increment function.
Andreas Bolka
8-Feb-2007 22:10:14
Never really missed them in REBOL; so I'm with Maarten in thinking that this, if at all, should rather be added on the REBOL level.
Brian Hawley
8-Feb-2007 23:26:56
Andreas, I made the above code nearly as efficient as possible, short of rebcode. It should serve as a reasonably good example of what these functions would be like if added to the REBOL level.

Added to the REBOL level, there would be no reason to add them at all. They are nowhere near as efficient as just calling the code they would be replacing. Because of this, it is clear that these functions should not be added as mezzanines by default.

Added as natives, they would be much more efficient than the expressions they would be replacing. So there is a point to adding them as natives: Efficiency.

Maxim Olivier-Adlhoch
8-Feb-2007 23:33:26
andreas & maarten,

AFAIK the task which complicates much of porting rebol actually isn't in things which are within the domain of REBOL (i.e. the interpreter), but in how rebol Abstracts the environment it runs on.

typing count: count + 1 seems oddly cumbersome in rebol. When the rest is so expressive I find its strange such a simple thing as incrementing a counter doesn't already have its op since the begining... just like ASR and ASL ops.

Henrik
9-Feb-2007 4:43:07
I agree with Maxim. I never understood why INC and DEC were not in REBOL. I use this type of counting a lot, particuarly during UNTIL and count: count + 1 is not the most readable thing, if you have it embedded in one line of code. If you have multiple counters in the same loop, this shaves off even more code.

If it further speeds up calculation a little bit by having them natively, then we have a useful argument beyond "mere" code beauty. :-)

John Niclasen
9-Feb-2007 16:44:40
If INC and DEC are introduced, would it be a good idea to add a new way of defining arguments to functions, which will act like a set-word in combination with a function? Say I would like to make a function working like INC and DEC, but that I would like the function to multiply a value by 2, so I write

>> mult2: func [value:] [value * 2]

I can now do

>> mult2 4
== 8
>> a: 3
>> mult2 a
== 6
>> a
== 6

Will the language be more complete this way, or is it confusing?

Brian Tiffin
9-Feb-2007 23:34:23
I'd definitely use increment, decrement. I rarely use pre-increment when I code in C so I wouldn't even mind if it was post-increment only.

My two canadian cents.

From the 'who cares' files; At my first ever official C programming course I wondered allowed (to complete silence) what ++var-- should compile as.

John Niclasen
11-Feb-2007 15:24:41
Carl, I think, it'll be confusing, that something like
++ count
does change the variable, why
negate count
doesn't. But as you said, it's already possible to do something similar in REBOL using 'argument. It's a dilemma.
John Niclasen
12-Feb-2007 11:23:22
Call-by-word, the REBOL way of call-by-reference.
What if INC/DEC works this way:

>> a: 4
>> inc a
== 5
>> a
== 4
>> inc 'a
== 5
>> a
== 5

To have this working, INC has to check, if it's called with a word argument. If it is, it get the value, add one and set the value back. Other existing functions (actions) like NEGATE can be programmed to work like this too. Is that an idea?

Brian Hawley
12-Feb-2007 14:51:11
John, that is how my second set of functions above works. Do you prefer that method?
John Niclasen
12-Feb-2007 16:33:09
Brian, yes, the more I think about it, I feel the method is more consistent with the soul of REBOL. Isn't it a bit of a problem, that when a user of a function write:

>> b: some-function a

the function might change a, because the author of the function choosed to define the argument like

some-function: func ['value] [...]

Actually if an author changed something like this from version to version of a function library, it'll be very confusing for the user of the library. I think, it's much better and easier to understand to do this:

>> some-function 'a

Brian Hawley
12-Feb-2007 23:36:08
You have a good point: Requiring explicit call-by-name is more REBOL-like. It might confuse C or assembler programmers, but those coming from higher-level languages like Scheme will definitely understand.
John Niclasen
13-Feb-2007 3:15:58
In C we do "some-function (&argument)", when we call a function, that should change the variable, so it shouldn't be too weird for C programmers. The same with assembler. They either specify the value of the variable or the address of the variable.

Maybe it would be fine, if these REBOL functions of type action! would take lit-word arguments too:

abs, back, complement, head, negate, next, tail

Maybe also: first, second, ...

Oldes
13-Feb-2007 11:12:22
I think, increment should change the value. I would prefer this:
inc some/object/some/value
instead of:
some/object/some/value: inc some/object/some/value
John Niclasen
13-Feb-2007 12:06:06
Maybe one of these:

inc some/object/some/'value
inc some/object/some/('value)
inc '(some/object/some/value)

My list of functions, that maybe should work on lit-words too can continue with many others:

exp, log-10, log-2, log-e, cosine, sine, etc...

Brian Hawley
13-Feb-2007 12:26:48
The code above (second set) will take this:
inc 'some/object/some/value
You know, lit-path! expressions. Keep in mind that these lit-word! and lit-path! expressions get evaluated to word! and path! values before they are passed to the function. You can also return word! or path! values from other functions or expressions to pass along.

It might be a good idea to implement trampoline actions on word! and path! datatypes. These trampoline actions would just pass along the call to the referenced values, if any, and then perhaps change the reference to the result on the way back.

Gregg Irwin
15-Feb-2007 16:44:06
Wasn't this already discussed somewhere? It's deja vu all over again.
W^L+
17-Mar-2007 12:32:18
Those of us who are used to C-style languages will find the space between the operator and the variable confusing/distracting. While I would immediately grok the increment/decrement, I would (more often than not) miss that space.

Also, when I deploy something with REBOL, it is often to a multi-user computer. It would be nice to have a single installation that would function for all users. As it is, on XP, a non-admin user does not automatically get the .r file association, even after an administrator has installed REBOL. Perhaps an all-users install option could be added to r3?

Gregg Irwin
19-Mar-2007 2:03:09
"Do we dare..." -- No. Just call them INCR and DECR; only two more letters for a much more REBOLish solution.

For moving through a series, I would make that a separate func and call it STEP or something. That said, INCR/DECR could work on series, to increase the current value, or all values. See: http://snippets.dzone.com/posts/show/2118

I called that STEP, but it really should be INCR; I did that since I had a numeric oriented INCR func already and didn't want to combine them at the time.

Gregg Irwin
19-Mar-2007 2:07:13
And before Ladislav beats me to it, maybe it should evaluate its arg. Yes, it forces you to use a lit-word!, but the alternative is that it's really a pain to use computed values otherwise. It also makes it more like SET, in that it's clearer that the arg will be modified.
Brian Hawley
19-Mar-2007 9:37:02
We had a long discussion about this in the previous set of comments on this post, even with test code. Should I repost the code?

Post a Comment:

You can post a comment here. Keep it on-topic.

Name:

Blog id:

R3-0057


Comment:


 Note: HTML tags allowed for: b i u li ol ul font span div a p br pre tt blockquote
 
 

This is a technical blog related to the above topic. We reserve the right to remove comments that are off-topic, irrelevant links, advertisements, spams, personal attacks, politics, religion, etc.

REBOL 3.0
Updated 24-Apr-2024 - Edit - Copyright REBOL Technologies - REBOL.net