Проблема в scala для-понимания de-сахара? - PullRequest
1 голос
/ 20 февраля 2020

У меня есть следующее для понимания, которое я удалил с помощью команды scala -Xprint:parser ForComprehensionDemo.scala. Когда я копирую метод обессахарения и вызываю его, он дает другой результат, чем для понимания. Любая идея, почему?

Для понимания:

    object ForComprehensionDemo {
      def main(args: Array[String]): Unit = {
        forWithIf(true)
      }

      def forWithIf(condition: Boolean) = {
        val x = for {
          a <- name(0)
          b <- if (condition) {
            name(1)
            name(2)
          } else {
            name(100)
          }
          c <- name(2)
        } yield {
          a + b + c
        }

        println(x)
      }

   def name(x: Int): Option[String] = {
     println("called for :" + x)
     x match {
       case 0 => Some(" aa ")
       case 1 => Some(" bb ")
       case 2 => Some(" cc ")
       case _ => Some(" not identified ")
     }
    }   
   }

Производит результат:

called for :0
called for :1
called for :2
called for :2
Some( aa  cc  cc )

Обезвоженный код

    def forWithIf(condition: Boolean) = {
      val x = name(0).flatMap(((a) => if (condition)
  {
    name(1);
    name(2)
  }
else
  name(100).flatMap(((b) => name(2).map(((c) => a.$plus(b).$plus(c)))))));
      println(x)
    };

Производит результат:

called for :0
called for :1
called for :2
Some( cc )

Ответы [ 2 ]

3 голосов
/ 21 февраля 2020

Просто ошибка в симпатичном принтере. Вокруг if-else пропущены парены.

В общем, scala 2 не очень точно соответствует паренсу, но scala 3 намного лучше.

package desugar {
  object ForComprehensionDemo extends scala.AnyRef {
    def main(args: Array[String]): Unit = forWithIf(true);
    def forWithIf(condition: Boolean) = {
      val x = name(0).flatMap(((a) => (if (condition)
  {
    name(1);
    name(2)
  }
else
  name(100)).flatMap(((b) => name(2).map(((c) => a.$plus(b).$plus(c)))))));
      println(x)
    };
    def name(x: Int): Option[String] = {
      println("called for :".$plus(x));
      x match {
        case 0 => Some(" aa ")
        case 1 => Some(" bb ")
        case 2 => Some(" cc ")
        case _ => Some(" not identified ")
      }
    }
  }
}

Я был Любопытно посмотреть, что говорит Scala 3. -Xprint:all говорит после типера:

          sugar.ForComprehensionDemo.name(0).flatMap[String](
            {
              def $anonfun(a: String): Option[String] = 
                (if condition then 
                  {
                    sugar.ForComprehensionDemo.name(1)
                    sugar.ForComprehensionDemo.name(2)
                  }
                 else 
                  {
                    sugar.ForComprehensionDemo.name(100)
                  }
                ).flatMap[String](
                  {
                    def $anonfun(b: String): Option[String] = 
                      sugar.ForComprehensionDemo.name(2).map[String](
                        {
                          def $anonfun(c: String): String = 
                            {
                              a.+(b).+(c)
                            }
                          closure($anonfun)
                        }
                      )
                    closure($anonfun)
                  }
                )
              closure($anonfun)
            }
          )

Это более непостижимо для замыканий, но у него есть парены. Печать после парсера бесполезна.

1 голос
/ 21 февраля 2020

Для сравнения приведен вывод IntelliJ Desugar Scala code... (с сокращением FQN вручную)

def forWithIf(condition: Boolean) = {
  val x = name(0)
    .flatMap(((a) =>
      (if (condition) {
        name(1);
        name(2)
      } else {
        name(100)
      })
        .flatMap(((b) =>
          name(2)
            .map(((c) => a.$plus(b).$plus(c)))))
      ));
  println(x)
};

, подтверждающий ответ сом-снитта.

...