Overloaded operators: Difference between revisions

→‎{{header|Raku}}: Add a Raku example
(Added precision regarding types.)
(→‎{{header|Raku}}: Add a Raku example)
Line 90:
}
<!--</lang>-->
 
=={{header|Raku}}==
While it is very easy to overload operators in Raku, it isn't really common...
at least, not in the traditional sense. One of the founding principles of Raku is
that: "Different things should look different". It follows that "Similar things
should look similar".
 
To pick out one tiny example: Adding numbery things together shouldn't be easily confusable with concatenating
strings. Instead, Raku has the "concatenation" operator: ~ for joining stringy
things together.
 
Using a numeric-ish operator implies that you want a numeric-ish answer... so Raku
will try very hard to give you what you ask for, no matter what operands you
pass it.
 
Raku operators have multiple candidates to try to fulfil your request and will
try to coerce the operands to a sensible value.
 
Addition:
<lang perl6>say 3 + 5; # Int plus Int
say 3.0 + 0.5e1; # Rat plus Num
say '3' + 5; # Str plus Int
say 3 + '5'; # Int plus Str
say '3' + '5'; # Str plus Str
say '3.0' + '0.5e1'; # Str plus Str
say (2, 3, 4) + [5, 6]; # List plus Array</lang>
 
{{out}}
<pre>8
8
8
8
8
8
5 # a list or array evaluated numerically returns the number of elements</pre>
 
 
Concatenation:
<lang perl6>say 3 ~ 5; # Int concatenate Int
say 3.0 ~ 0.5e1; # Rat concatenate Num
say '3' ~ 5; # Str concatenate Int
say 3 ~ '5'; # Int concatenate Str
say '3' ~ '5'; # Str concatenate Str
say '3.0' ~ '0.5e1'; # Str concatenate Str
say (2, 3, 4) ~ [5, 6]; # List concatenate Array</lang>
 
{{out}}
<pre>35
35
35
35
35
3.00.5e1
2 3 45 6 # default stringification, then concatenate</pre>
 
There is nothing preventing you from overloading or overriding existing
operators. Raku firmly believes in not putting pointless restrictions on
what you can and can not do. Why make it hard to do the "wrong" thing when
we make it so easy to do it right?
 
There is no real impetus to "overload" existing operators to do ''different''
things, it is '''very''' easy to add new operators in Raku, and nearly '''any'''
Unicode character or combination may used to define it. They may be infix,
prefix, postfix, (or post-circumfix!) The precedence, associativity and arity
are all easily defined.
 
Borrowed from the [[Nimber_arithmetic#Raku|Nimber arithmetic]] task:
 
New operators, defined in place. Arity is two (almost all infix operators are
take two arguments), precedence is set equivalent to similar existing operators,
default (right) associativity. The second, ⊗, actually uses itself to define
itself.
 
<lang perl6>sub infix:<⊕> (Int $x, Int $y) is equiv(&infix:<+>) { $x +^ $y }
 
sub infix:<⊗> (Int $x, Int $y) is equiv(&infix:<×>) {
return $x × $y if so $x|$y < 2;
my $h = exp $x.lsb, 2;
return $h ⊗ $y ⊕ (($x ⊕ $h) ⊗ $y) if $x > $h;
return $y ⊗ $x if $y.lsb < $y.msb;
return $x × $y unless my $comp = $x.lsb +& $y.lsb;
$h = exp $comp.lsb, 2;
(($x +> $h) ⊗ ($y +> $h)) ⊗ (3 +< ($h - 1))
}
 
say 123 ⊗ 456;</lang>
{{out}}
<pre>31562</pre>
 
 
That's all well and good, but suppose you have a new class, say, a Line class, and
you want to be able to do arithmetic on Lines. No need to override the built
in arithmetic operators, just add a multi candidate to do the right thing. A multi
allows ''adding'' a new definition of the operator without disturbing the existing ones.
 
Very, '''very''' basic Line class:
<lang perl6>class Line {
has @.start;
has @.end;
 
method gist { "Line: start: {self.start.join: ','} end: {self.end.join: ','}" }
}
 
# New infix + operator to add two Lines together
multi infix:<+> (Line $x, Line $y) {
Line.new(
:start(
sqrt($x.start[0]² + $y.start[0]²),
sqrt($x.start[1]² + $y.start[1]²)
),
:end(
sqrt($x.end[0]² + $y.end[0]²),
sqrt($x.end[1]² + $y.end[1]²)
)
)
}
 
# In operation:
say Line.new(:start(-4,7), :end(5,0)) + Line.new(:start(1,1), :end(2,3));</lang>
 
{{out}}
<pre>Line: start: 4.123105625617661,7.0710678118654755 end: 5.385164807134504,3</pre>
 
=={{header|Wren}}==
10,333

edits