Para seguir el código de Scala cuando configuro un punto de depuración en la instrucción if y habilito "Registro: mensaje de hit de punto de interrupción"
object App1 { def main(args: Array[String]): Unit = { iftest() } def iftest(): Unit = { val setA: Set[String] = Set("a", "b", "c"); var setB: Set[String] = Set("d", "e", "f") if(setA.size > setB.size){ //here break point at line 8 println("bigger") } } }Obtuve el siguiente resultado en la consola. La pregunta es por qué este punto de interrupción se golpea dos veces.
Breakpoint reached at com.eguller.App1$.iftest(App1.scala:8) Breakpoint reached at com.eguller.App1$.iftest(App1.scala:8)Pero para seguir un código Java similar, el punto de interrupción se alcanza solo una vez.
Set<String> set1 = new HashSet<>(); set1.add("1"); set1.add("2"); Set<String> set2 = new HashSet<>(); set2.add("a"); set2.add("b"); if(set1.size() > set2.size()){ //here break point at line 8 System.out.println("size different"); }Obtuve el siguiente resultado
Breakpoint reached at com.eguller.JApp.main(JApp.java:8)¿Es un error en el depurador Intellij o es una característica del lenguaje de programación Scala?
IntelliJ IDEA 2021.3 Java - 11 Scala - 2.12.15
Esta es una peculiaridad de la generación de bytecode escalac. Por alguna razón, genera una posición adicional para el depurador justo antes de la instrucción de retorno y lo coloca en esa línea. Puede invocar la acción "Mostrar código de bytes" en el IDE y ver que hay 2 entradas LINENUMBER 8 :
// access flags 0x1 public iftest()V L0 LINENUMBER 6 L0 GETSTATIC scala/Predef$.MODULE$ : Lscala/Predef$; INVOKEVIRTUAL scala/Predef$.Set ()Lscala/collection/immutable/Set$; GETSTATIC scala/runtime/ScalaRunTime$.MODULE$ : Lscala/runtime/ScalaRunTime$; ICONST_3 ANEWARRAY java/lang/String DUP ICONST_0 LDC "a" AASTORE DUP ICONST_1 LDC "b" AASTORE DUP ICONST_2 LDC "c" AASTORE CHECKCAST [Ljava/lang/Object; INVOKEVIRTUAL scala/runtime/ScalaRunTime$.wrapRefArray ([Ljava/lang/Object;)Lscala/collection/immutable/ArraySeq; INVOKEVIRTUAL scala/collection/immutable/Set$.apply (Lscala/collection/immutable/Seq;)Ljava/lang/Object; CHECKCAST scala/collection/immutable/Set ASTORE 1 L1 LINENUMBER 7 L1 GETSTATIC scala/Predef$.MODULE$ : Lscala/Predef$; INVOKEVIRTUAL scala/Predef$.Set ()Lscala/collection/immutable/Set$; GETSTATIC scala/runtime/ScalaRunTime$.MODULE$ : Lscala/runtime/ScalaRunTime$; ICONST_3 ANEWARRAY java/lang/String DUP ICONST_0 LDC "d" AASTORE DUP ICONST_1 LDC "e" AASTORE DUP ICONST_2 LDC "f" AASTORE CHECKCAST [Ljava/lang/Object; INVOKEVIRTUAL scala/runtime/ScalaRunTime$.wrapRefArray ([Ljava/lang/Object;)Lscala/collection/immutable/ArraySeq; INVOKEVIRTUAL scala/collection/immutable/Set$.apply (Lscala/collection/immutable/Seq;)Ljava/lang/Object; CHECKCAST scala/collection/immutable/Set ASTORE 2 L2 LINENUMBER 8 L2 ALOAD 1 INVOKEINTERFACE scala/collection/immutable/Set.size ()I (itf) ALOAD 2 INVOKEINTERFACE scala/collection/immutable/Set.size ()I (itf) IF_ICMPLE L3 L4 LINENUMBER 9 L4 GETSTATIC scala/Predef$.MODULE$ : Lscala/Predef$; LDC "bigger" INVOKEVIRTUAL scala/Predef$.println (Ljava/lang/Object;)V GOTO L3 L3 LINENUMBER 8 L3 FRAME APPEND [scala/collection/immutable/Set scala/collection/immutable/Set] RETURN L5 LOCALVARIABLE setA Lscala/collection/immutable/Set; L1 L3 1 LOCALVARIABLE setB Lscala/collection/immutable/Set; L2 L3 2 LOCALVARIABLE this LApp1$; L0 L5 0 MAXSTACK = 6 MAXLOCALS = 3El compilador Scala 3 no agrega esto y los puntos de interrupción funcionan como se esperaba.