What's the Point of Unary Plus Operator in Ruby

What's the point of unary plus operator in Ruby?

Perhaps it's just a matter of consistency, both with other programming languages, and to mirror the unary minus.

Found support for this in The Ruby Programming Language (written by Yukihiro Matsumoto, who designed Ruby):

The unary plus is allowed, but it has no effect on numeric operands—it simply returns the value of its operand. It is provided for symmetry with unary minus, and can, of course, be redefined.

Why would one use the unary operator on a property in ruby? i.e &:first

Read the answers in the duplicate questions for the meaning and usage of &:.... In this case, entries is an array, and there are three methods map, sort_by, and map chained. sort_by(&:last) is equivalent to sort_by{|x| x.last}. map(&:first) is the same as map{|x| x.first}. The reason the first map does not use &:... is because (i) the receiver of accept_entry is not e, and (ii) it takes an argument e.

What does +@ mean as a method in ruby

Ruby contains a few unary operators, including +, -, !, ~, & and *. As with other operators you can also redefine these. For ~ and ! you can simply just say def ~ and def ! as they don't have a binary counterpart (e.g. you cannot say a!b).

However for - and + there is both a unary, and a binary version (e.g. a+b and +a are both valid), so if you want to redefine the unary version you have to use def +@ and def -@.

Also note that there is a unary version of * and & as well, but they have special meanings. For * it is tied to splatting the array, and for & it is tied to converting the object to a proc, so if you want to use them you have to redefine to_a and to_proc respectively.

Here is a more complete example showing all kinds of the unary operators:

class SmileyString < String
def +@
SmileyString.new(self + " :)")
end

def -@
SmileyString.new(self + " :(")
end

def ~
SmileyString.new(self + " :~")
end

def !
SmileyString.new(self + " :!")
end

def to_proc
Proc.new { |a| SmileyString.new(self + " " + a) }
end

def to_a
[SmileyString.new(":("), self]
end
end

a = SmileyString.new("Hello")
p +a # => "Hello :)"
p ~a # => "Hello :~"
p *a # => [":(", "Hello"]
p !a # => "Hello :!"
p +~a # => "Hello :~ :)"
p *+!-~a # => [":(", "Hello :~ :( :! :)"]
p %w{:) :(}.map &a # => ["Hello :)", "Hello :("]

In your example the Module just simply defines an unary + operator, with a default value of not doing anything with the object (which is a common behaviour for the unary plus, 5 and +5 usually mean the same thing). Mixing in with any class would mean the class immediately gets support for using the unary plus operator, which would do nothing much.

For example (using ruby <=2.2):

module M
def +@
self
end
end

p +"Hello" # => NoMethodError: undefined method `+@' for "Hello":String

class String
include M
end

p +"Hello" # => "Hello"

Note that in this example you can clearly see from the error message that the +@ method is missing from the class

Note that the above example will be different from Ruby 2.3, as the unary minus and plus are defined for Strings since that version, and they refer to returning a frozen and unfrozen string from the original.

Why doesn't the unary plus have the meaning of absolute value?

It's not implemented that way because math doesn't work that way.

In math:

note: the following is math on a blackboard, not a programming language

+ -5 = -5

- -5 = 5

Doing it any other way will confuse anyone who's ever finished highschool.

Obviously, the above is fairly weak answer since you can indeed implement the action taken by the ASCII character '+' in the code to work differently from math. In Lisp for example, the + operator does not work like regular highschool math:

;;; Adding two numbers:
+ 1 2

And on TI calculators, it's even reversed:

1 2 +

You could argue that implementing + the way you describe in your programming language makes sense. There are a number of different arguments on why it should not be done including the principle of least surprise, a language should model the problem domain, it's what we've been taught at school etc. All of them are essentially weak arguments because they don't provide a fundamental reason for a machine to treat + the same way as math.

But here's the thing, humans are emotional creatures. We like what's familiar and cringe at something that goes against something we've been taught. And programmers don't like being surprised by + behaving differently from normal. And programmers are the ones who create programming languages so it makes sense that they implement + the way they do.

One programmer may not think like that, or a small group, and they are free to create a programming language that implements + differently. But they'll have a hard time convincing the programming community at large they what they did was right.

So it doesn't matter so much that all the arguments that can be made against + acting as abs() are essentially weak. As long as the majority feels it's right + will behave the same as regular math.

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.

Why does F# have a unary plus operator?

I'll summarize the extended comments. Possible reasons (until a more authoritative answer is given):

  1. Consistency with OCaml, from which F# is derived (if you're doing something wrong/unnecessary it's best to keep doing it so people know what to expect :-))
  2. Overloading (mostly for custom types)
  3. Symmetry with unary negation

Does the unary + operator have any practical use?

char ch = 'a';
std::cout << ch << '\n';
std::cout << +ch << '\n';

The first insertion writes the character a to cout. The second insertion writes the numeric value of ch to cout. But that's a bit obscure; it relies on the compiler applying integral promotions for the + operator.

Is unary minus supposed to have higher precedence for numeric literals?

The reason is that in the literal number case, the - in front isn't an unary operator, but part of the literal syntax.

However, the - operator itself has lower precedence than method invocation. Given that there is no -'string' literal syntax for strings, this rule always applies regardless of if the string was literal or not.

class Integer
def -@
puts 'Called'
end
end

class String
def -@
puts 'Called'
end
end

-1 # nothing, the - wasn't an unary operation, but part of the number construction
x = 1
-x # Called

-'a' # Called
a = 'a'
-a # Called

Another interesting thing is that if you put a space between the number and the -, the - is no longer part of the literal syntax.

- 1 # Called

Here is the semantic explanation:

  • There is such thing as "the number negative one". It makes sense that there should be literal syntax for it (as there is for any positive number). And the most intuitive syntax for it is -1.
  • We still want to be able to call the unary operator on literal positive numbers. The most intuitive (and easy to implement) way for that would be not to make the parser super fancy as to ignore any random amount of whitespaces in the literal syntax for negative numbers. Hence why - 1 accounts to "apply the unary minus to the number (positive) one".
  • There is no such thing as "the string negative 'a'". That is why -'a' means "apply the unary minus to the string 'a'".

What happens when we use operators in ruby

Ruby knows that + is an operator because the language's grammar says so. There's also a unary + operator (that is converted to the +@ method) and the language's grammar allows Ruby to know which is which. The language definition says that operators are implemented as method calls and specifies which method each operator maps to.

What you're asking is the same as asking how o.m a is a call to the m method on o with a as an argument. That's just how Ruby's syntax and semantics are defined.

Operators are functions even in theoretical mathematics. The a + b notation is really just a convenient notation for +(a, b) (where +:R2R or a function from R×R to R, for example). I think you're reading too much into the notation and thinking that operators are something special, they're not, they're just function calls in computer languages and mathematics alike.

In short, it works because that's how Ruby is defined to work.

As far as

could 3 be an method method called on '+' method ?

is concerned, 3 is an argument or parameter to the + method on the Fixnum object 2.

String concatenation?

++ just looks like the increment operator. It's actually two unary + operators, so it's just the same as plain old counter



Related Topics



Leave a reply



Submit