## Bug #13815

### p args

**Description**

x=y=0 # outside defined vars!

3.times {|i| x,y=x+1,y+1 } # as expected: x==3

3.times {|i| p(x,y=x+1,y+1) } # NOT as expected: x not changed!

# x,y are the same vars as above. p shoudn't have any effect on scope

### History

#### Updated by opti (Andreas Opti) almost 2 years ago

**Subject**changed from*p changes scope of vars*to*p changes scope of *vars*

x=y=0 # outside defined vars!

3.times { x,y = x+1,y+1 } # as expected: x==3

3.times { p(x,y = x+1,y+1) } # NOT as expected: x not changed!

# x,y are the same vars as above. p shoudn't have any effect on scope¶

#### Updated by jeremyevans0 (Jeremy Evans) almost 2 years ago

**Status**changed from*Open*to*Rejected*

opti (Andreas Opti) wrote:

x=y=0 # outside defined vars!

3.times { x,y = x+1,y+1 } # as expected: x==3

3.times { p(x,y = x+1,y+1) } # NOT as expected: x not changed!## x,y are the same vars as above. p shoudn't have any effect on scope¶

This makes sense once you understand how ruby parses the p method call:

```
3.times { p((x),(y = x+1),(y+1)) }
```

If you want the same behavior, you need to use parentheses:

```
3.times { p((x,y = x+1,y+1)) }
```

#### Updated by opti (Andreas Opti) almost 2 years ago

**ruby -v**changed from*2.4 and 2.5*to*2.5.x***Status**changed from*Rejected*to*Open***Subject**changed from*p changes scope of *vars*to*p args*

If you want the same behavior, you need to use parentheses:

3.times { p((x,y = x+1,y+1)) }

# ok, but also with ((...)) [most people] would assume its meaning is (x, y=x+1, y+1)...¶

*Other example:

p(x+=1,x+=1) # ok

p (x+=1,x+=1) # error

p ((x,y)=[x+1,y+1]) # ok

p((x,y)=[x+1,y+1]) # ERROR! --- normally there should be NO space before (....)

So the parsing of p(Args) might be improved...

#### Updated by phluid61 (Matthew Kerwin) almost 2 years ago

opti (Andreas Opti) wrote:

If you want the same behavior, you need to use parentheses:

3.times { p((x,y = x+1,y+1)) }## ok, but also with ((...)) [most people] would assume its meaning is (x, y=x+1, y+1)...¶

Most people wouldn't write it in the first place.

You *could*, if you really, really wanted to do a multiple assignment **and** capture the result into an array **and** `p`

the array, all in one step.

I don't think it's a parser issue, though; the parser does a logical thing at each step. It's the author who's doing something weird.

*Other example:

p(x+=1,x+=1) # ok

p (x+=1,x+=1) # error

Well, yeah, but this is well known, well defined ruby. `p(x)`

is an unambiguous function call; `p (x)`

is a parenthesised `(x)`

being passed as the first positional argument to `p`

.

It might help illustrate by replacing the `p`

function call with, say, an assignment:

#p(x) a = x #p((x)) a = (x) #p x a = x #p (x) a = (x) #p (x+=1,x+=1) a = (x+=1,x+=1) #??? #p ((x,y)=[x+1,y+1]) a = ((x,y)=[x+1,y+1]) # Note: multiple assignment returns the whole array, so a == [x,y] # This can also be written: a = (x,y=[x+1,y+1]) or: a = (x,y=x+1,y+1) #p((x,y)=[x+1,y+1]) a = (x,y)=[x+1,y+1] #??? This part doesn't make sense: a = (x,y)

So the parsing of p(Args) might be improved...

I don't like saying this, but I think this is a case where you have to get familiar with ruby's syntax. It all makes sense once you understand how the parser sees what you've written.

#### Updated by matz (Yukihiro Matsumoto) almost 2 years ago

**Status**changed from*Open*to*Closed*

Andreas, it's easy to say "might be improved", but without the concrete design, it's worth nothing for us.

We designed for reasons, with the balance of features. Please submit the proposal, if you come up with the new idea.

Matz.