9

I guess I just got used to saying things like:

x++

in PHP and Java land. But when I tried this in my Rails code it had a fit:

compile error
/users/gshankar/projects/naplan/app/views/answers/new.html.haml:19: syntax error, unexpected ';'
/users/gshankar/projects/naplan/app/views/answers/new.html.haml:23: syntax error, unexpected kENSURE, expecting kEND
...}\n", 0, false);_erbout;ensure;@haml_buffer = @haml_buffer.u...
                              ^
/users/gshankar/projects/naplan/app/views/answers/new.html.haml:26: syntax error, unexpected $end, expecting kEND

I googled around a bit for Ruby/Rails operators for a reference to ++ but couldn't find anything. For a language which focuses on writing less I find it a bit strange that there wouldn't be a ++ equivalent. Am I missing something?

Ganesh Shankar
  • 4,826
  • 8
  • 43
  • 56

4 Answers4

15

Try this:

x += 1
Trevor
  • 6,659
  • 5
  • 35
  • 68
  • x++ (and ++x) are both inline, and execute in different orders from this. As an example, it is not possible to duplicate this line (read: without splitting it) when using x+=1: `row_top = row_height * row_index++;` – Terra Ashley May 14 '15 at 22:01
5

x+=1 is the best you can do in Ruby.

For a detailed explanation, see Why doesn't Ruby support i++ or i--​ (increment/decrement operators)?

jva
  • 2,797
  • 1
  • 26
  • 41
igul222
  • 8,557
  • 14
  • 52
  • 60
2

While as other answers point out x += 1 and x -= 1 is one way to do this. The closest Ruby gets to the --/++ operators are the prev()/next() (next has an alias of succ()) methods which return the previous/next items in sequence and are available on unambiguous strictly ordered classes (like String).

x = 4     # => 4
x.succ    # => 5
x.prev    # => 3

y = 'ABC' # => 'ABC'
y.succ    # => 'ABD'
y.prev    # => 'ABB'

Unfortunately, none of these implicitly do assignment which is what the original question was asking about. igul222's answer links to a post from Ruby's creator explaining why this is not possible.

Ruby has very powerful collection processing capabilities that eliminate most needs for these kinds of assignments. In all but the most complex alogrithms, which involve processing multiple collections at different rates in parallel. You should be asking yourself why you need increment/decrement. Because the Ruby way to do operations where increment and decrement operators are commonly used is with an iterator.

Such as each_with_index which executes a given block for each element/index pair in the array.

For example, this code will iterate through an array outputting the string representation fo each element and the parity of its index.

array = ["first", "second", "third","fourth","last"]
array.each_with_index do |object,index|
   puts index % 2 ? "even" : "odd"
   puts object.to_s
end

Edit: Removed Fixnum extension providing postfix increment because it doesn't work. Upon closer inspection there's nothing stopping you from adding it, but it would involve writing your feature in C, and a recompile.

Edit 2022: Added comment about prev/next/succ functions which are closer in behaviour to the decrement/increment function of --/++ operators

EmFi
  • 23,435
  • 3
  • 57
  • 68
  • But what about `++x`? (Not that it should *ever* be used that way. I have to pause everytime I see something like `while(--x)` and think about what it's actually doing (will x ever be 0 in the body?)) – Ponkadoodle Feb 24 '10 at 00:53
  • This will not work at all. First, you can't just define arbitrary operators, and "++" won't even parse in Ruby — it would have to be called as `x.send('++')`. Second, you can't write `self =` anything. Remember, doing `x = something` just makes the name `x` refer to a new object — it doesn't change the value of the object that was there before. – Chuck Feb 24 '10 at 00:57
  • Thanks Chuck, that will teach me to post code without testing it. I'm sure there's a way to write a ++, but, upon closer inspection it would probably involve recompiling Ruby from C. – EmFi Feb 24 '10 at 01:08
  • @EmFi, that's a great point about questing one's use of incrementing variables. Anytime I've wanted to do something like `x+=1`, I've found a more elegant approach. – Peter Brown Feb 24 '10 at 01:20
  • Well the case here is where I just need a simple counter to give me row numbers in a list of items I'm displaying... if there's a way to do it without having a variable and incrementing it I'm keen to hear about it. I am using a .each loop so is there a way to know which iteration I'm in? – Ganesh Shankar Feb 24 '10 at 01:24
  • @gshankar Try Enumerable#each_with_index, I've updated my solution to contain an example using it as well as a link to its documentation. – EmFi Feb 24 '10 at 01:39
  • By changing the Ruby parser and adding a new operator to the language, you'd end up with something that isn't really valid Ruby anymore. (Not that that's necessarily a bad thing — it's just not Ruby.) – Chuck Feb 24 '10 at 02:21
  • using increment/decrement operators in loops is not the only use case, there are others such as if I was mapping a positional data structure e.g. CSV columns to a named data structure eg. JSON, it is nice to do something like col=0 followed by json = { name: csv_data[col++], description: csv_data[col++], some_other_field: csv_data[col++] } – David Cruwys Oct 23 '17 at 02:19
  • @DavidCruwys: There are other ways of accomplishing that with out using increment. col_headings = [:name , :description, : some_other_field] json=col_headings.zip(csv_data).to_h This also provides a singular definition of your column headings, so you don't have to hard code them every where they're needed. – EmFi Nov 01 '17 at 14:16
1

You have to use x+=1 instead.

http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Operators

thebretness
  • 632
  • 3
  • 13