# ðŸ”¬54. Going over the Bridge, part 2. Letâ€™s get rid of it

Today, we continue working with the Bridge method in Rakudo Perl 6. Yesterday, we saw the definitions of the methods in a few pre-defined data types. It is time to see how the method is used.

## Whatâ€™s inside?

The major use of the method is inside theÂ Real role, which contains the following set of methods:

```method sqrt() { self.Bridge.sqrt }
method rand() { self.Bridge.rand }
method sin() { self.Bridge.sin }
method asin() { self.Bridge.asin }
method cos() { self.Bridge.cos }
method acos() { self.Bridge.acos }
method tan() { self.Bridge.tan }
method atan() { self.Bridge.atan }
. . .
method sec() { self.Bridge.sec }
method asec() { self.Bridge.asec }
method cosec() { self.Bridge.cosec }
method acosec() { self.Bridge.acosec }
method cotan() { self.Bridge.cotan }
method acotan() { self.Bridge.acotan }
method sinh() { self.Bridge.sinh }
method asinh() { self.Bridge.asinh }
method cosh() { self.Bridge.cosh }
method acosh() { self.Bridge.acosh }
method tanh() { self.Bridge.tanh }
method atanh() { self.Bridge.atanh }
method sech() { self.Bridge.sech }
method asech() { self.Bridge.asech }
method cosech() { self.Bridge.cosech }
method acosech() { self.Bridge.acosech }
method cotanh() { self.Bridge.cotanh }
method acotanh() { self.Bridge.acotanh }
method floor() { self.Bridge.floor }
method ceiling() { self.Bridge.ceiling }
. . .
multi method log(Real:D: ) { self.Bridge.log }
multi method exp(Real:D: ) { self.Bridge.exp }```

There are a few routines with a different pattern, where the method is called twice: once for getting to the needed function; second to coerce the value:

```multi method atan2(Real \$x = 1e0) { self.Bridge.atan2(\$x.Bridge) }
multi method atan2(Cool \$x = 1e0) { self.Bridge.atan2(\$x.Numeric.Bridge) }
multi method atan2(Real \$x = 1e0) { self.Bridge.atan2(\$x.Bridge) }
multi method atan2(Cool \$x = 1e0) { self.Bridge.atan2(\$x.Numeric.Bridge) }
multi method log(Real:D: Real \$base) { self.Bridge.log(\$base.Bridge) }
. . .
multi sub atan2(Real \a, Real \b = 1e0) { a.Bridge.atan2(b.Bridge) }```

As you see, theÂ atan2 function is defined both as a method and as a subroutine. To confuse you a bit more, there are two versions of it:

```proto sub atan2(\$, \$?) {*}
multi sub atan2(Real \a, Real \b = 1e0) { a.Bridge.atan2(b.Bridge) }
# should really be (Cool, Cool), and then (Cool, Real) and (Real, Cool)
# candidates, but since Int both conforms to Cool and Real, we'd get lots
# of ambiguous dispatches. So just go with (Any, Any) for now.
multi sub atan2( \a, \b = 1e0) { a.Numeric.atan2(b.Numeric) }```

Finally, a couple of methods for type conversions:

```method Bridge(Real:D:) { self.Num }
method Int(Real:D:) { self.Bridge.Int }
method Num(Real:D:) { self.Bridge.Num }
multi method Str(Real:D:) { self.Bridge.Str }
method Rat(Real:D: Real \$epsilon = 1.0e-6) { self.Bridge.Rat(\$epsilon) }```

Notice that theÂ Bridge method of theÂ Real role returns a NumÂ value.

Some infix methods are also using the method in hand:

```multi sub infix:<+>(Real \a, Real \b) { a.Bridge + b.Bridge }
multi sub infix:<->(Real \a, Real \b) { a.Bridge - b.Bridge }
multi sub infix:<*>(Real \a, Real \b) { a.Bridge * b.Bridge }
multi sub infix:</>(Real \a, Real \b) { a.Bridge / b.Bridge }
multi sub infix:<%>(Real \a, Real \b) { a.Bridge % b.Bridge }
multi sub infix:<**>(Real \a, Real \b) { a.Bridge ** b.Bridge }
multi sub infix:Â«<=>Â»(Real \a, Real \b) { a.Bridge <=> b.Bridge }
multi sub infix:<==>(Real \a, Real \b) { a.Bridge == b.Bridge }
multi sub infix:Â«<Â»(Real \a, Real \b) { a.Bridge < b.Bridge }
multi sub infix:Â«<=Â»(Real \a, Real \b) { a.Bridge <= b.Bridge }
multi sub infix:Â«â‰¤Â» (Real \a, Real \b) { a.Bridge â‰¤ b.Bridge }
multi sub infix:Â«>Â»(Real \a, Real \b) { a.Bridge > b.Bridge }
multi sub infix:Â«>=Â»(Real \a, Real \b) { a.Bridge >= b.Bridge }
multi sub infix:Â«â‰¥Â» (Real \a, Real \b) { a.Bridge â‰¥ b.Bridge }
multi sub prefix:<->(Real:D \a) { -a.Bridge }```

## Trace the calls

To see when theÂ BridgeÂ method is called, let us do a few simple experiments. I added a fewÂ nqp::say calls and run the REPL console to invoke aÂ sin method on the variables of different types.

With theÂ Num data type, a direct method is called:

```> my Num \$n = 1e1;
10
> \$n.sin
Num.sin```

This method is calling the underlying NQP function:

```proto method sin(|) {*}
multi method sin(Num:D: ) {
nqp::p6box_n(nqp::sin_n(nqp::unbox_n(self)));
}```

With other data types, you travel via theÂ Real role:

```> my Int \$i = 1;
1
> \$i.sin
Real.sin
Num.sin

> my Rat \$r = 1/2;
0.5
> \$r.sin
Real.sin
Num.sin```

The same path you experience with your own types, if they are inherited from the built-in ones:

```> class MyInt is Int {}
> my MyInt \$mi = MyInt.new
0
> \$mi.sin
Real.sin
Num.sin```

## Get rid of it

I revised all the places where the method was used in my clone of Rakudo. Mostly, they are replaced with a direct call of theÂ Num method. In a few places it leads to double calls like \$x.Num.Num, which were also reduced, of course.

With the updated code, all the tests from Roast were passed. As a side effect, the speed in some cases is increased by around 3%:

`./perl6 -e'for 1..10_000_000 {Int.new(1).sin}'`

It is quite an extensive change, and still, there is one thing left: the thing that causes an infinite loop when you call the method on a newly created Real object. It looks like the wrong hierarchy of the numerical data types is the main cause, but I assume that we can safely remove theÂ BridgeÂ method at least.

Update. They core developers (although at first not clearly understanding why it the method was needed at all) decided to keep the method and updated the documentation, which is also a positive output ðŸ™‚