What's the Point of the Prefix? Operator in Ruby 1.9

What's the Point of the prefix ? operator in Ruby 1.9

It's mainly for backwards compatibility. In versions prior to 1.9, ? evaluated to a Fixnum corresponding to the ASCII value of the character in question. Indexing into a String also returned a Fixnum.

So, if you wanted to check, for example, if the third character of a string was the letter 'a' you would do

s[2] == ?a

In Ruby 1.9, strings are no longer treated as an array of fixnums but as an iterator of characters (single-character strings, actually). As a result, the above code would no longer work: s[2] would be a string, ?a would be a number, and those two would never be equal.

Therefore, ? was also changed to evaluate to a single-character string, so that the above code continues to work.

What's the Point of the prefix ? operator in Ruby 1.9

It's mainly for backwards compatibility. In versions prior to 1.9, ? evaluated to a Fixnum corresponding to the ASCII value of the character in question. Indexing into a String also returned a Fixnum.

So, if you wanted to check, for example, if the third character of a string was the letter 'a' you would do

s[2] == ?a

In Ruby 1.9, strings are no longer treated as an array of fixnums but as an iterator of characters (single-character strings, actually). As a result, the above code would no longer work: s[2] would be a string, ?a would be a number, and those two would never be equal.

Therefore, ? was also changed to evaluate to a single-character string, so that the above code continues to work.

Ruby: Curious usage of ? operator in comparing strings for equality

This is old syntax for one char strings.

?- means '-'

EDIT: turns out, I couldn't be more wrong. See @Jörg's comment below.

ruby 1.9.x, weird parsing, what's going on?

Ruby 1.8.7 also supports unary +, and gives the same error for +'='.

I would assume something changed in the parsing logic, and a +'=' is parsed as an unary plus in your expression. I wouldn't consider that a bug.

What does the (unary) * operator do in this Ruby code?

The * is the splat operator.

It expands an Array into a list of arguments, in this case a list of arguments to the Hash.[] method. (To be more precise, it expands any object that responds to to_ary/to_a, or to_a in Ruby 1.9.)

To illustrate, the following two statements are equal:

method arg1, arg2, arg3
method *[arg1, arg2, arg3]

It can also be used in a different context, to catch all remaining method arguments in a method definition. In that case, it does not expand, but combine:

def method2(*args)  # args will hold Array of all arguments
end

Some more detailed information here.

How to use ampersand prefix with other arguments

Try

raw = File.open(fname).read

Edit: The problem with this is that it doesn't close the file, as OP stated.

However this does work with ruby 1.9.3p448:

raw = File.open(fname, &:read)

This is just to demonstrate the use of the &/symbol representation of a block in ruby. As sawa points out, in actual practice one would ordinarily do:

raw = File.read(fname)

ruby double question mark

Ruby 1.8 has a ?-prefix syntax that turns a character into its ASCII code value. For example, ?a is the ASCII value for the letter a (or 97). The double question mark you see is really just the number 63 (or the ASCII value for ?).

?a    # => 97
?b # => 98
?c # => 99
?\n # => 10
?? # => 63

To convert back, you can use the chr method:

97.chr   # => "a"
10.chr # => "\n"
63.chr # => "?"

??.chr # => "?"

In Ruby 1.9, the ?a syntax returns the character itself (as does the square bracket syntax on strings):

??           # => "?"

"What?"[-1] # => "?"

Space before star breaks syntax in ruby multiplication statement

* is used for both an operator (42 * 42) and argument unpacking (myfun *[42, 42]).

When you do:

m.x *m.x  
2/m.x *m.x

Ruby interprets this as argument unpacking, rather than the * operator (ie. multiplication).

In case you're not familiar with it, argument unpacking (sometimes also called "splat", or "splats") means that you can have a function like this:

def myfun arg1, arg2; end

And call it like this:

myfun(*['Hello', 'World'])

arg1 is set to Hello, and arg2 is set to World.

I believe the rules are to determine which to use is:

  • Space before but not after a * -> Argument unpacking
  • Start of function parenthesis -> Argument unpacking
  • Everything else -> Multiplication (or rather, the * operator, since Ruby does operator overloading).

Good guidelines are:

  1. Use the "optional" function parenthesis when you intend argument unpacking;
  2. use spaces before and after * when you intend the * operator (multiplication).

Ruby will actually warn you about this when you run ruby -v:

test.rb|11 warning| `*' interpreted as argument prefix                                    
test.rb|12 warning| `*' interpreted as argument prefix


Related Topics



Leave a reply



Submit