import java.util.concurrent.atomic.AtomicInteger
object Nat:
inline def unapply(x: AtomicInteger): Option[Int] = x.get() match {
case n if n > 0 => Some(n)
case _ => None
}
object Main:
def test(n: AtomicInteger): String =
n match
case Nat(m) => s"$m is a natural number"
case _ => s"$n is not a natural number"
def main(args: Array[String]): Unit =
println(test(new AtomicInteger(5))) // Output: 5 is a natural number
// class version 52.0 (52)
// access flags 0x31
public final class Main$ implements java/io/Serializable {
// compiled from: main.scala
ATTRIBUTE Scala : unknown
// access flags 0x19
public final static LMain$; MODULE$
// access flags 0x2
private <init>()V
L0
LINENUMBER 9 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this LMain$; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x9
public static <clinit>()V
L0
LINENUMBER 10 L0
NEW Main$
DUP
INVOKESPECIAL Main$.<init> ()V
PUTSTATIC Main$.MODULE$ : LMain$;
RETURN
MAXSTACK = 2
MAXLOCALS = 0
// access flags 0x2
private writeReplace()Ljava/lang/Object;
L0
LINENUMBER 9 L0
NEW scala/runtime/ModuleSerializationProxy
DUP
LDC LMain$;.class
INVOKESPECIAL scala/runtime/ModuleSerializationProxy.<init> (Ljava/lang/Class;)V
ARETURN
L1
LOCALVARIABLE this LMain$; L0 L1 0
MAXSTACK = 3
MAXLOCALS = 1
// access flags 0x1
public test(Ljava/util/concurrent/atomic/AtomicInteger;)Ljava/lang/String;
// parameter final n
L0
LINENUMBER 11 L0
ALOAD 1
ASTORE 2
L1
LINENUMBER 12 L1
ALOAD 2
IFNULL L2
L3
LINENUMBER 12 L3
ALOAD 2
INVOKEVIRTUAL java/util/concurrent/atomic/AtomicInteger.get ()I
ISTORE 4
L4
LINENUMBER 5 L4
ILOAD 4
ISTORE 5
L5
ILOAD 5
ICONST_0
IF_ICMPLE L6
GETSTATIC scala/Some$.MODULE$ : Lscala/Some$;
ILOAD 5
INVOKESTATIC scala/runtime/BoxesRunTime.boxToInteger (I)Ljava/lang/Integer;
INVOKEVIRTUAL scala/Some$.apply (Ljava/lang/Object;)Lscala/Some;
GOTO L7
L6
LINENUMBER 6 L6
GETSTATIC scala/None$.MODULE$ : Lscala/None$;
GOTO L7
L7
ASTORE 3
L8
LINENUMBER 12 L8
ALOAD 3
INVOKEVIRTUAL scala/Option.isEmpty ()Z
IFNE L2
ALOAD 3
INVOKEVIRTUAL scala/Option.get ()Ljava/lang/Object;
INVOKESTATIC scala/runtime/BoxesRunTime.unboxToInt (Ljava/lang/Object;)I
ISTORE 6
ILOAD 6
ISTORE 7
L9
NEW java/lang/StringBuilder
DUP
LDC 20
INVOKESPECIAL java/lang/StringBuilder.<init> (I)V
ILOAD 7
INVOKEVIRTUAL java/lang/StringBuilder.append (I)Ljava/lang/StringBuilder;
LDC " is a natural number"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ARETURN
L2
LINENUMBER 13 L2
NEW java/lang/StringBuilder
DUP
LDC 24
INVOKESPECIAL java/lang/StringBuilder.<init> (I)V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder;
LDC " is not a natural number"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ARETURN
L10
LOCALVARIABLE n I L5 L6 5
LOCALVARIABLE m I L9 L2 7
LOCALVARIABLE this LMain$; L0 L10 0
LOCALVARIABLE n Ljava/util/concurrent/atomic/AtomicInteger; L0 L10 1
MAXSTACK = 3
MAXLOCALS = 8
// access flags 0x1
// signature ([Ljava/lang/String;)V
// declaration: void main(java.lang.String[])
public main([Ljava/lang/String;)V
// parameter final args
L0
LINENUMBER 16 L0
GETSTATIC scala/Predef$.MODULE$ : Lscala/Predef$;
ALOAD 0
NEW java/util/concurrent/atomic/AtomicInteger
DUP
ICONST_5
INVOKESPECIAL java/util/concurrent/atomic/AtomicInteger.<init> (I)V
INVOKEVIRTUAL Main$.test (Ljava/util/concurrent/atomic/AtomicInteger;)Ljava/lang/String;
INVOKEVIRTUAL scala/Predef$.println (Ljava/lang/Object;)V
RETURN
L1
LOCALVARIABLE this LMain$; L0 L1 0
LOCALVARIABLE args [Ljava/lang/String; L0 L1 1
MAXSTACK = 5
MAXLOCALS = 2
}
I was thinking , the unapply is inline method, and the compiler will treat Some(n) and None special and rewrite the code to something like :
import java.util.concurrent.atomic.AtomicInteger
object Main:
def main(args: Array[String]): Unit =
println({
(new AtomicInteger(5)).get() match
case n if n > 0 => s"$n is a natural number"
case x => s"$x is not a natural number"
}) // Output: 5 is a natural number