Running an Example with spire.macros.Checked#tryOrElse

18 views
Skip to first unread message

Kevin Meredith

unread,
Jun 23, 2015, 10:33:00 AM6/23/15
to type...@googlegroups.com
Looking at spire.macros.Checked#tryOrElse:

  /**
   * Performs overflow checking for Int/Long operations.
   *
   * If no errors are detected, the expected result will be
   * returned. If there are errors, the 'orElse' block will be
   * evaluated and returned.
   */
  def tryOrElse[A](n: A)(orElse: A): A = macro tryOrElseImpl[A]

  def tryOrElseImpl[A: c.WeakTypeTag](c: Context)(n: c.Expr[A])(orElse: c.Expr[A]): c.Expr[A] = {
    val tree = CheckedRewriter[c.type](c).rewriteSafe[A](n.tree, orElse.tree)
    val resetTree = resetLocalAttrs(c)(tree) // See SI-6711
    c.Expr[A](resetTree)
  }

I tried to run this macro with an example from sbt console:

scala> lazy val overflowedLong: Long = 1L + Long.MaxValue
overflowedLong: Long = <lazy>

scala> Checked.tryOrElse[Long](overflowedLong)(0L)
res12: Long = -9223372036854775808

Naively, I was expecting that the orElse (0L) would've returned. In this example, why does  -9223372036854775808... get returned?

Erik Osheim

unread,
Jun 23, 2015, 10:36:49 AM6/23/15
to Kevin Meredith, type...@googlegroups.com
On Tue, Jun 23, 2015 at 07:33:00AM -0700, Kevin Meredith wrote:
> I tried to run this macro with an example from *sbt console*:
>
> scala> lazy val overflowedLong: Long = 1L + Long.MaxValue
> overflowedLong: Long = <lazy>
>
> scala> Checked.tryOrElse[Long](overflowedLong)(0L)
> res12: Long = -9223372036854775808
>
> Naively, I was expecting that the *orElse (0L)* would've returned. In this
> example, why does -9223372036854775808... get returned?

Hi Kevin,

As with many macro-related things, the usage is very particular. In
this case, you need to put the addition literally inside the macro. By
the time you've defined overflowedLong it's already "too late".

Try calling the checked macro there insead:

val mv = Long.MaxValue
val cv = Checked.tryOrElse(mv + 1L)(0L)

The macro literally unpacks all the arithmetic operations it sees in
the AST it is given. So if the AST has no arithmetic (because it's
already been encoded in a method or lazy val) then there is nothing
that can be done -- for all it knows you are just working with
Long.MinValue.

-- Erik
Reply all
Reply to author
Forward
0 new messages