SlideShare une entreprise Scribd logo
1  sur  19
Télécharger pour lire hors ligne
Scala magic

Александр Подхалюзин

    19 мая 2012 г.




                       1 / 19
Syntactic sugar
For
comprehensions
By-name
parameters
Non local return
Local functions
Lazy values
Generated
ByteCode
Binary
                   Syntactic sugar
compatibility

Questions?




                                     2 / 19
For comprehensions

Syntactic sugar
For
                   В Scala for является синтаксическим сахаром, тем не
comprehensions
By-name
                   менее правила преобразования довольно сложны
parameters
Non local return        Один генератор с ’yield’ тоже, что вызов метода ’map’
Local functions
Lazy values             Один генератор без ’yield’ тоже, что ’foreach’
Generated               Несколько генераторов транслируются во ’flatMap’
ByteCode
Binary
compatibility

Questions?          f o r ( i <− 1 t o    5)       (1 to 5) . map { i = i    > i }
                        yield i       i            (1 to 5) . f o r e a c h {
                    f o r ( i <− 1 t o
                        println ( i )
                                          5)       }
                                                     i = println ( i )
                                                        >

                    f o r { i <− 1 t o    5        (1 to 5) . f l a t M a p {
                            j <− 1 t o    5}         i = (1 to 5) . map { j = i + j }
                                                        >                       >
                        yield i + j                }


                   Подробнее можно почитать в спецификации.



                                                                                        3 / 19
By-name parameters

Syntactic sugar
For
                   Возможность в вызов метода передавать выражения
comprehensions
By-name
                   лениво это другой пример того, где неявно могут быть
parameters
Non local return
                   зашиты closures. Следующие два примера идентичны:
Local functions
Lazy values
                    d e f foo ( x : => Int ) {   d e f foo ( x : ( ) => Int ) {
Generated
ByteCode               println ( x )                println ( x ( ) )
                    }                            }
Binary
compatibility
                    foo ( 1 )                    foo ( ( ) => 1 )
Questions?

                   Что изредка может приводить к ошибке (параметр будет
                   вычисляться каждый раз, когда к нему будет
                   производится обращение).




                                                                                  4 / 19
Non local return

Syntactic sugar
For
                   Return statement внутри closure на деле компилируется в
comprehensions
By-name
                   код, который бросает NonLocalReturnControl. В
parameters
Non local return
                   большинстве случаев это удобно, но нужно учитывать
Local functions    следующее
Lazy values
Generated             В критичных по производительности кусках кода этот
ByteCode
Binary
                      exception следует избегать
compatibility
                      Нельзя ловить Throwable в том месте, где этот
Questions?
                      exception бросается
                      В силу синтаксического сахара описанного ранее, все
                      это может происходить неявно (for-comprehensions и
                      by-name parameters)




                                                                        5 / 19
Local functions

Syntactic sugar
For
                   В Java любой вспомогательный код оформляется в виде
comprehensions
By-name
                   private методов на уровне класса. В Scala это можно
parameters
Non local return
                   сделать более структурированным, если использовать
Local functions    локальные методы, хотя на уровне bytecode получается
Lazy values
Generated
                   примерно тоже самое:
ByteCode
Binary
compatibility                                    import scala . runtime . IntRef ;
                                                 public class LocalFunctions {
Questions?          class LocalFunctions {
                                                     p u b l i c void foo () {
                      def foo {
                                                             I n t R e f i $ 1 = new I n t R e f ( 1 ) ;
                        var i = 1
                                                             i n t j$1 = 2;
                        val j = 2
                                                             l o c a l $ 1 ( i$1 , j$1 ) ;
                        def local {
                          i += j
                                                             l o c a l $ 1 ( i$1 , j$1 ) ;
                                                     }
                        }
                                                     p r i v a t e f i n a l void local$1 (
                        local
                                                         IntRef intref , i n t i ) {
                        local
                                                             i n t r e f . e l e m += i ;
                      }
                                                     }
                    }
                                                     p u b l i c L o c a l F u n c t i o n s ( ) {}
                                                 }




                                                                                                       6 / 19
Lazy values

Syntactic sugar
For
                   Это тоже синтаксический сахар, который надо
comprehensions
By-name
                   использовать аккуратно (так как возможны deadlock и
parameters
Non local return
                   проблемы производительности). Независимо от
Local functions    расположения lazy val, компилируется он таким образом
Lazy values
Generated
ByteCode
                                             import scala . runtime . BoxedUnit ;
Binary                                       p u b l i c c l a s s Lazy {
compatibility                                   public int x () {
                                                     i f ( ( b i t m a p $ 0 & 2 ) == 0 )
Questions?                                              synchronized ( this ) {
                                                           i f ( ( b i t m a p $ 0 & 2 ) == 0 ) {
                                                               x = 1;
                                                               bitmap$0 = bitmap$0 | 2;
                    c l a s s Lazy {
                        lazy val x = 1
                                                           }
                                                           BoxedUnit _tmp =
                    }
                                                               BoxedUnit . UNIT ;
                                                        }
                                                        return x ;
                                                    }
                                                p u b l i c L a z y ( ) {}
                                                private int x ;
                                                public v o l a t i l e i n t bitmap$0 ;
                                             }



                                                                                                    7 / 19
Syntactic sugar
Generated
ByteCode
Classes and names
Objects
Traits
Trait subclasses
Linearization
Initialisation order
Binary
                       Generated ByteCode
compatibility

Questions?




                                            8 / 19
Classes and names

Syntactic sugar
                       Для классов ничего магического не происходит.
Generated
ByteCode               Как преобразуются имена. Для большинства символов
Classes and names
Objects                есть его текстовый эквивалент
Traits
Trait subclasses          :   $colon
Linearization
Initialisation order
                          +   $plus
Binary                    ©   $u00A9
compatibility

Questions?             Внутри Scala кода можно использовать оба варианта
                       подобных идентификаторов
                       Подробнее можно изучить преобразования с помощью
                       методов NameTransfomer.encode/decode из
                       scala-compiler.jar.




                                                                           9 / 19
Objects

Syntactic sugar
                       Объект всегда компилируется в два класса.
Generated
ByteCode
Classes and names
                          Object$ содержит в себе статическое поле MODULE$,
Objects                   а также код всех методов
Traits
Trait subclasses          Object содержит в себе все статические методы
Linearization
Initialisation order      объекта, с телом вида Object$.MODULE$.foo()
Binary
compatibility          Важно понимать, что статические методы добавлены для
Questions?             удобства вызова из Java. Тем не менее они добавляются
                       не всегда.
                          В Companion Trait не добавляется ничего.
                          В Companion Class не добавляются методы с таким
                          именем, которое уже есть в этом классе
                          Методы класса java.lang.Object


                                                                         10 / 19
Traits

Syntactic sugar
                       Если trait отличается от обычного интерфейса в Java
Generated
ByteCode               наличием конкретных методов, то к соответствующему
Classes and names
Objects                интерфейсу будет создан класс Trait$class с
Traits
Trait subclasses
                       имплементацией этих методов.
Linearization
Initialisation order
Binary                                                      public abstract class   A$class {
compatibility                                                   public static int   foo ( A $this ,
                                                                                          int x) {
Questions?                                                          return   2;
                        trait A {
                                                                }
                          val x = 1                             public s t a t i c void $init$ (
                                                                  A $this
                            def foo ( x :   Int ) = 2
                                                                ) {
                        }
                                                                    $this .
                                                                      test$A$_setter_$x_$eq (1) ;
                                                                }
                                                            }




                                                                                                      11 / 19
Trait subclasses

Syntactic sugar
                       Если в Java попытаться реализовать Trait, в котором есть
Generated
ByteCode               уже имплементированые методы, то их все равно
Classes and names
Objects                пришлось бы реализовывать. Другой вопрос, что это
Traits
Trait subclasses
                       можно сделать предельно легко:
Linearization
Initialisation order
Binary                 i n t foo ( ) { r e t u r n Trait$class . foo ( t h i s ) ; }
compatibility

Questions?
                       В случае наследников написанных на Scala, то же самое
                       делает компилятор.




                                                                                       12 / 19
Linearization

Syntactic sugar
                       Этот алгоритм требуется компилятору, чтобы определить,
Generated
ByteCode               в каком порядке надо искать методы в базовых классах.
Classes and names
Objects
Traits
Trait subclasses       trait   A extends B
Linearization          trait   B
Initialisation order   class   C extends B
Binary                 class   D extends C with A
compatibility

Questions?
                       Здесь порядок D, A, C, B.
                       Если два метода с одинаковой сигнатурой без
                       модификатора ’override’ приходят в класс наследник из
                       супертрейтов, то ошибки не будет, так как обязательно
                       надо будет переопределить эту сигнатуру. Если же у
                       кого-то есть модификатор ’override’, может случится
                       неявный override согласно правилам линеаризации.

                                                                           13 / 19
Initialisation order

Syntactic sugar
                       Инициализация происходит в порядке, обратном
Generated
ByteCode               линеаризации. Если к переменной обратиться до того, как
Classes and names
Objects                она проинициализирована, можно получить NPE.
Traits
Trait subclasses
                       Есть два способа избавится от подобных проблем:
Linearization
Initialisation order      Использовать lazy val
Binary
compatibility
                          Использовать early definitions
Questions?




                                                                          14 / 19
Syntactic sugar
Generated
ByteCode
Binary
compatibility
Methods
Values
Lazy values

Questions?        Binary compatibility




                                         15 / 19
Methods

Syntactic sugar
                  Здесь все очень похоже на Java. Чаще всего проблем не
Generated
ByteCode          будет.
Binary
compatibility        Добавлять метод можно даже в Trait, но только если
Methods
Values               старые методы не ссылаются на новые, так как
Lazy values
                     имплементации в классы наследники добавлены не
Questions?
                     будут.
                     В класс опасно добавлять методы, имена которых
                     совпадают с именем методов из Companion Object, так
                     как статические реализации будут удалены
                     компилятором, что может вызвать проблемы с кодом
                     написанным не на Scala.




                                                                     16 / 19
Values

Syntactic sugar
                  Если переменная находится в классе или объекте, то
Generated
ByteCode          переменная компилируется в getter, setter (для variables) и
Binary
compatibility
                  field, который инциализируется в конструкторе класса. А
Methods           значит все будет также хорошо как и с методами.
Values
Lazy values       Если переменная находится в Trait, то она компилируется
Questions?        в getter и setter (всегда). Инициализация происходит в
                  методе Trait$class.$init$ через вызов setter.
                      Значит добавлять переменную в трейт нельзя. Так как
                      будет вызван абстрактный setter.
                      По аналогичным причинам нельзя изменять def на val
                      Тем не менее val на def также изменять нельзя, так как
                      тогда в классах наследниках, где как раз и хранится
                      field, переменная не будет проинициализирована.


                                                                         17 / 19
Lazy values

Syntactic sugar
                  В подклассах не генерируется field bitmap, если он есть в
Generated
ByteCode          базовом классе.
Binary
compatibility         Поэтому в этих случаях добавлять lazy value в классы
Methods
Values                нельзя
Lazy values
                      В Trait добавлять можно, если эта переменная не
Questions?
                      будет использована в старом коде
                      Так как компиляция lazy val в Trait от компиляции
                      метода не отличается совсем, то их можно заменять
                      друг на друга, учитывая только, что в наследниках
                      подобная семантика не изменится




                                                                        18 / 19
Syntactic sugar
Generated
ByteCode
Binary
compatibility

Questions?



                  Questions?




                               19 / 19

Contenu connexe

Tendances

Теории и практики фунционального программирования - GDG D2D
Теории и практики фунционального программирования - GDG D2DТеории и практики фунционального программирования - GDG D2D
Теории и практики фунционального программирования - GDG D2D0xffAA
 
Теории и практики функционального программирования.
Теории и практики функционального программирования.Теории и практики функционального программирования.
Теории и практики функционального программирования.Dev2Dev
 
Характерные черты функциональных языков программирования
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программированияAlex.Kolonitsky
 
Инкапсуляция и полиморфизм в ruby
Инкапсуляция и полиморфизм в rubyИнкапсуляция и полиморфизм в ruby
Инкапсуляция и полиморфизм в rubyEvgeny Smirnov
 
Ruby — Паттерны программирования
Ruby — Паттерны программированияRuby — Паттерны программирования
Ruby — Паттерны программированияEvgeny Smirnov
 
Динамическое программирование на ruby
Динамическое программирование на rubyДинамическое программирование на ruby
Динамическое программирование на rubyEvgeny Smirnov
 
C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.Igor Shkulipa
 
Алгоритмы на ruby: жадные алгоритмы
Алгоритмы на ruby: жадные алгоритмыАлгоритмы на ruby: жадные алгоритмы
Алгоритмы на ruby: жадные алгоритмыEvgeny Smirnov
 
Обработка коллекций наизнанку: как применить много функций к одному аргументу...
Обработка коллекций наизнанку: как применить много функций к одному аргументу...Обработка коллекций наизнанку: как применить много функций к одному аргументу...
Обработка коллекций наизнанку: как применить много функций к одному аргументу...corehard_by
 
Ruby: работа с массивами
Ruby: работа с массивамиRuby: работа с массивами
Ruby: работа с массивамиEvgeny Smirnov
 
Задачи по ООП в ruby
Задачи по ООП в rubyЗадачи по ООП в ruby
Задачи по ООП в rubyEvgeny Smirnov
 
Запись вспомогательный алгоритмов на языка Паскаль
Запись вспомогательный алгоритмов на языка ПаскальЗапись вспомогательный алгоритмов на языка Паскаль
Запись вспомогательный алгоритмов на языка ПаскальAndrey Dolinin
 
Cpp/cli types
Cpp/cli typesCpp/cli types
Cpp/cli typesmcroitor
 
чернякова г.в.
чернякова г.в.чернякова г.в.
чернякова г.в.sharikdp
 
Общие сведения о языке программирования Паскаль
Общие сведения о языке программирования ПаскальОбщие сведения о языке программирования Паскаль
Общие сведения о языке программирования ПаскальAndrey Dolinin
 
Способы записи алгоритмов
Способы записи алгоритмовСпособы записи алгоритмов
Способы записи алгоритмовAndrey Dolinin
 
C++ Базовый. Занятие 03.
C++ Базовый. Занятие 03.C++ Базовый. Занятие 03.
C++ Базовый. Занятие 03.Igor Shkulipa
 

Tendances (20)

Урок 1. Что такое функциональное программирование
Урок 1. Что такое функциональное программированиеУрок 1. Что такое функциональное программирование
Урок 1. Что такое функциональное программирование
 
Теории и практики фунционального программирования - GDG D2D
Теории и практики фунционального программирования - GDG D2DТеории и практики фунционального программирования - GDG D2D
Теории и практики фунционального программирования - GDG D2D
 
Теории и практики функционального программирования.
Теории и практики функционального программирования.Теории и практики функционального программирования.
Теории и практики функционального программирования.
 
Характерные черты функциональных языков программирования
Характерные черты функциональных языков программированияХарактерные черты функциональных языков программирования
Характерные черты функциональных языков программирования
 
Инкапсуляция и полиморфизм в ruby
Инкапсуляция и полиморфизм в rubyИнкапсуляция и полиморфизм в ruby
Инкапсуляция и полиморфизм в ruby
 
Ruby — Паттерны программирования
Ruby — Паттерны программированияRuby — Паттерны программирования
Ruby — Паттерны программирования
 
777
777777
777
 
Динамическое программирование на ruby
Динамическое программирование на rubyДинамическое программирование на ruby
Динамическое программирование на ruby
 
C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.C++ Базовый. Занятие 02.
C++ Базовый. Занятие 02.
 
Алгоритмы на ruby: жадные алгоритмы
Алгоритмы на ruby: жадные алгоритмыАлгоритмы на ruby: жадные алгоритмы
Алгоритмы на ruby: жадные алгоритмы
 
Обработка коллекций наизнанку: как применить много функций к одному аргументу...
Обработка коллекций наизнанку: как применить много функций к одному аргументу...Обработка коллекций наизнанку: как применить много функций к одному аргументу...
Обработка коллекций наизнанку: как применить много функций к одному аргументу...
 
Ruby: работа с массивами
Ruby: работа с массивамиRuby: работа с массивами
Ruby: работа с массивами
 
Задачи по ООП в ruby
Задачи по ООП в rubyЗадачи по ООП в ruby
Задачи по ООП в ruby
 
Запись вспомогательный алгоритмов на языка Паскаль
Запись вспомогательный алгоритмов на языка ПаскальЗапись вспомогательный алгоритмов на языка Паскаль
Запись вспомогательный алгоритмов на языка Паскаль
 
Cpp/cli types
Cpp/cli typesCpp/cli types
Cpp/cli types
 
чернякова г.в.
чернякова г.в.чернякова г.в.
чернякова г.в.
 
Общие сведения о языке программирования Паскаль
Общие сведения о языке программирования ПаскальОбщие сведения о языке программирования Паскаль
Общие сведения о языке программирования Паскаль
 
Способы записи алгоритмов
Способы записи алгоритмовСпособы записи алгоритмов
Способы записи алгоритмов
 
C++ Базовый. Занятие 03.
C++ Базовый. Занятие 03.C++ Базовый. Занятие 03.
C++ Базовый. Занятие 03.
 
Python
PythonPython
Python
 

En vedette

Functional Programming - Worth the Effort
Functional Programming - Worth the EffortFunctional Programming - Worth the Effort
Functional Programming - Worth the EffortBoldRadius Solutions
 
MBLT16: Andrey Maslak, Aviasales
MBLT16: Andrey Maslak, AviasalesMBLT16: Andrey Maslak, Aviasales
MBLT16: Andrey Maslak, Aviasalese-Legion
 
MBLT16: Marvin Liao, 500Startups
MBLT16: Marvin Liao, 500StartupsMBLT16: Marvin Liao, 500Startups
MBLT16: Marvin Liao, 500Startupse-Legion
 
MBLT16: Dmitriy Geranin, Afisha Restorany
MBLT16: Dmitriy Geranin, Afisha RestoranyMBLT16: Dmitriy Geranin, Afisha Restorany
MBLT16: Dmitriy Geranin, Afisha Restoranye-Legion
 
MBLT16: Vincent Wu, Alibaba Mobile
MBLT16: Vincent Wu, Alibaba MobileMBLT16: Vincent Wu, Alibaba Mobile
MBLT16: Vincent Wu, Alibaba Mobilee-Legion
 
MBLT16: Alexander Lukin, AppMetrica
MBLT16: Alexander Lukin, AppMetricaMBLT16: Alexander Lukin, AppMetrica
MBLT16: Alexander Lukin, AppMetricae-Legion
 
MBLT16: Elena Rydkina, Pure
MBLT16: Elena Rydkina, PureMBLT16: Elena Rydkina, Pure
MBLT16: Elena Rydkina, Puree-Legion
 

En vedette (8)

Functional Programming - Worth the Effort
Functional Programming - Worth the EffortFunctional Programming - Worth the Effort
Functional Programming - Worth the Effort
 
A new way to compile
A new way to compileA new way to compile
A new way to compile
 
MBLT16: Andrey Maslak, Aviasales
MBLT16: Andrey Maslak, AviasalesMBLT16: Andrey Maslak, Aviasales
MBLT16: Andrey Maslak, Aviasales
 
MBLT16: Marvin Liao, 500Startups
MBLT16: Marvin Liao, 500StartupsMBLT16: Marvin Liao, 500Startups
MBLT16: Marvin Liao, 500Startups
 
MBLT16: Dmitriy Geranin, Afisha Restorany
MBLT16: Dmitriy Geranin, Afisha RestoranyMBLT16: Dmitriy Geranin, Afisha Restorany
MBLT16: Dmitriy Geranin, Afisha Restorany
 
MBLT16: Vincent Wu, Alibaba Mobile
MBLT16: Vincent Wu, Alibaba MobileMBLT16: Vincent Wu, Alibaba Mobile
MBLT16: Vincent Wu, Alibaba Mobile
 
MBLT16: Alexander Lukin, AppMetrica
MBLT16: Alexander Lukin, AppMetricaMBLT16: Alexander Lukin, AppMetrica
MBLT16: Alexander Lukin, AppMetrica
 
MBLT16: Elena Rydkina, Pure
MBLT16: Elena Rydkina, PureMBLT16: Elena Rydkina, Pure
MBLT16: Elena Rydkina, Pure
 

Similaire à Александр Подхалюзин, «Магия Scala изнутри»

Язык программирования Go для Perl-программистов
Язык программирования Go для Perl-программистовЯзык программирования Go для Perl-программистов
Язык программирования Go для Perl-программистовAndrew Shitov
 
Михаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знанияМихаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знанияYandex
 
Михаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajaxМихаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajaxYandex
 
Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013ScalaNsk
 
Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияYandex
 
Back to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняBack to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняAlexander Granin
 
Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Stfalcon Meetups
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPython Meetup
 

Similaire à Александр Подхалюзин, «Магия Scala изнутри» (9)

Discovering Lambdas (Speech)
Discovering Lambdas (Speech)Discovering Lambdas (Speech)
Discovering Lambdas (Speech)
 
Язык программирования Go для Perl-программистов
Язык программирования Go для Perl-программистовЯзык программирования Go для Perl-программистов
Язык программирования Go для Perl-программистов
 
Михаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знанияМихаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знания
 
Михаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajaxМихаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajax
 
Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013Павел Павлов - Scala для профессионалов - Joker 2013
Павел Павлов - Scala для профессионалов - Joker 2013
 
Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знания
 
Back to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодняBack to the future: Функциональное программирование вчера и сегодня
Back to the future: Функциональное программирование вчера и сегодня
 
Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Discovering Lambdas in Java 8
Discovering Lambdas in Java 8
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стиль
 

Plus de e-Legion

MBLT16: Andrey Bakalenko, Sberbank Online
MBLT16: Andrey Bakalenko, Sberbank OnlineMBLT16: Andrey Bakalenko, Sberbank Online
MBLT16: Andrey Bakalenko, Sberbank Onlinee-Legion
 
Rx Java architecture
Rx Java architectureRx Java architecture
Rx Java architecturee-Legion
 
MBLTDev15: Hector Zarate, Spotify
MBLTDev15: Hector Zarate, SpotifyMBLTDev15: Hector Zarate, Spotify
MBLTDev15: Hector Zarate, Spotifye-Legion
 
MBLTDev15: Cesar Valiente, Wunderlist
MBLTDev15: Cesar Valiente, WunderlistMBLTDev15: Cesar Valiente, Wunderlist
MBLTDev15: Cesar Valiente, Wunderliste-Legion
 
MBLTDev15: Brigit Lyons, Soundcloud
MBLTDev15: Brigit Lyons, SoundcloudMBLTDev15: Brigit Lyons, Soundcloud
MBLTDev15: Brigit Lyons, Soundcloude-Legion
 
MBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&CoMBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&Coe-Legion
 
MBLTDev15: Alexander Orlov, Postforpost
MBLTDev15: Alexander Orlov, PostforpostMBLTDev15: Alexander Orlov, Postforpost
MBLTDev15: Alexander Orlov, Postforposte-Legion
 
MBLTDev15: Artemiy Sobolev, Parallels
MBLTDev15: Artemiy Sobolev, ParallelsMBLTDev15: Artemiy Sobolev, Parallels
MBLTDev15: Artemiy Sobolev, Parallelse-Legion
 
MBLTDev15: Alexander Dimchenko, DIT
MBLTDev15: Alexander Dimchenko, DITMBLTDev15: Alexander Dimchenko, DIT
MBLTDev15: Alexander Dimchenko, DITe-Legion
 
MBLTDev: Evgeny Lisovsky, Litres
MBLTDev: Evgeny Lisovsky, LitresMBLTDev: Evgeny Lisovsky, Litres
MBLTDev: Evgeny Lisovsky, Litrese-Legion
 
MBLTDev: Alexander Dimchenko, Bright Box
MBLTDev: Alexander Dimchenko, Bright Box MBLTDev: Alexander Dimchenko, Bright Box
MBLTDev: Alexander Dimchenko, Bright Box e-Legion
 
MBLTDev15: Konstantin Goldshtein, Microsoft
MBLTDev15: Konstantin Goldshtein, MicrosoftMBLTDev15: Konstantin Goldshtein, Microsoft
MBLTDev15: Konstantin Goldshtein, Microsofte-Legion
 
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank e-Legion
 
MBLTDev15: Ivan Kozlov, Aviasales
MBLTDev15: Ivan Kozlov, AviasalesMBLTDev15: Ivan Kozlov, Aviasales
MBLTDev15: Ivan Kozlov, Aviasalese-Legion
 
MBLTDev15: Ilya Krasilshchik, Meduza.io
MBLTDev15: Ilya Krasilshchik, Meduza.ioMBLTDev15: Ilya Krasilshchik, Meduza.io
MBLTDev15: Ilya Krasilshchik, Meduza.ioe-Legion
 
MBLTDev15: Svetlana Sonina, STS Media
MBLTDev15: Svetlana Sonina, STS MediaMBLTDev15: Svetlana Sonina, STS Media
MBLTDev15: Svetlana Sonina, STS Mediae-Legion
 
MBLTDev15: Marius Racwitz, Realm
MBLTDev15: Marius Racwitz, RealmMBLTDev15: Marius Racwitz, Realm
MBLTDev15: Marius Racwitz, Realme-Legion
 
MBLTDev15: Denis Legezo, Kaspersky Lab
MBLTDev15: Denis Legezo, Kaspersky LabMBLTDev15: Denis Legezo, Kaspersky Lab
MBLTDev15: Denis Legezo, Kaspersky Labe-Legion
 
MBLTDev15: Kyle Fuller, Apairy
MBLTDev15: Kyle Fuller, ApairyMBLTDev15: Kyle Fuller, Apairy
MBLTDev15: Kyle Fuller, Apairye-Legion
 

Plus de e-Legion (20)

MBLT16: Andrey Bakalenko, Sberbank Online
MBLT16: Andrey Bakalenko, Sberbank OnlineMBLT16: Andrey Bakalenko, Sberbank Online
MBLT16: Andrey Bakalenko, Sberbank Online
 
Rx Java architecture
Rx Java architectureRx Java architecture
Rx Java architecture
 
Rx java
Rx javaRx java
Rx java
 
MBLTDev15: Hector Zarate, Spotify
MBLTDev15: Hector Zarate, SpotifyMBLTDev15: Hector Zarate, Spotify
MBLTDev15: Hector Zarate, Spotify
 
MBLTDev15: Cesar Valiente, Wunderlist
MBLTDev15: Cesar Valiente, WunderlistMBLTDev15: Cesar Valiente, Wunderlist
MBLTDev15: Cesar Valiente, Wunderlist
 
MBLTDev15: Brigit Lyons, Soundcloud
MBLTDev15: Brigit Lyons, SoundcloudMBLTDev15: Brigit Lyons, Soundcloud
MBLTDev15: Brigit Lyons, Soundcloud
 
MBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&CoMBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&Co
 
MBLTDev15: Alexander Orlov, Postforpost
MBLTDev15: Alexander Orlov, PostforpostMBLTDev15: Alexander Orlov, Postforpost
MBLTDev15: Alexander Orlov, Postforpost
 
MBLTDev15: Artemiy Sobolev, Parallels
MBLTDev15: Artemiy Sobolev, ParallelsMBLTDev15: Artemiy Sobolev, Parallels
MBLTDev15: Artemiy Sobolev, Parallels
 
MBLTDev15: Alexander Dimchenko, DIT
MBLTDev15: Alexander Dimchenko, DITMBLTDev15: Alexander Dimchenko, DIT
MBLTDev15: Alexander Dimchenko, DIT
 
MBLTDev: Evgeny Lisovsky, Litres
MBLTDev: Evgeny Lisovsky, LitresMBLTDev: Evgeny Lisovsky, Litres
MBLTDev: Evgeny Lisovsky, Litres
 
MBLTDev: Alexander Dimchenko, Bright Box
MBLTDev: Alexander Dimchenko, Bright Box MBLTDev: Alexander Dimchenko, Bright Box
MBLTDev: Alexander Dimchenko, Bright Box
 
MBLTDev15: Konstantin Goldshtein, Microsoft
MBLTDev15: Konstantin Goldshtein, MicrosoftMBLTDev15: Konstantin Goldshtein, Microsoft
MBLTDev15: Konstantin Goldshtein, Microsoft
 
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
 
MBLTDev15: Ivan Kozlov, Aviasales
MBLTDev15: Ivan Kozlov, AviasalesMBLTDev15: Ivan Kozlov, Aviasales
MBLTDev15: Ivan Kozlov, Aviasales
 
MBLTDev15: Ilya Krasilshchik, Meduza.io
MBLTDev15: Ilya Krasilshchik, Meduza.ioMBLTDev15: Ilya Krasilshchik, Meduza.io
MBLTDev15: Ilya Krasilshchik, Meduza.io
 
MBLTDev15: Svetlana Sonina, STS Media
MBLTDev15: Svetlana Sonina, STS MediaMBLTDev15: Svetlana Sonina, STS Media
MBLTDev15: Svetlana Sonina, STS Media
 
MBLTDev15: Marius Racwitz, Realm
MBLTDev15: Marius Racwitz, RealmMBLTDev15: Marius Racwitz, Realm
MBLTDev15: Marius Racwitz, Realm
 
MBLTDev15: Denis Legezo, Kaspersky Lab
MBLTDev15: Denis Legezo, Kaspersky LabMBLTDev15: Denis Legezo, Kaspersky Lab
MBLTDev15: Denis Legezo, Kaspersky Lab
 
MBLTDev15: Kyle Fuller, Apairy
MBLTDev15: Kyle Fuller, ApairyMBLTDev15: Kyle Fuller, Apairy
MBLTDev15: Kyle Fuller, Apairy
 

Александр Подхалюзин, «Магия Scala изнутри»

  • 2. Syntactic sugar For comprehensions By-name parameters Non local return Local functions Lazy values Generated ByteCode Binary Syntactic sugar compatibility Questions? 2 / 19
  • 3. For comprehensions Syntactic sugar For В Scala for является синтаксическим сахаром, тем не comprehensions By-name менее правила преобразования довольно сложны parameters Non local return Один генератор с ’yield’ тоже, что вызов метода ’map’ Local functions Lazy values Один генератор без ’yield’ тоже, что ’foreach’ Generated Несколько генераторов транслируются во ’flatMap’ ByteCode Binary compatibility Questions? f o r ( i <− 1 t o 5) (1 to 5) . map { i = i > i } yield i i (1 to 5) . f o r e a c h { f o r ( i <− 1 t o println ( i ) 5)   } i = println ( i ) > f o r { i <− 1 t o 5 (1 to 5) . f l a t M a p { j <− 1 t o 5} i = (1 to 5) . map { j = i + j } > > yield i + j } Подробнее можно почитать в спецификации. 3 / 19
  • 4. By-name parameters Syntactic sugar For Возможность в вызов метода передавать выражения comprehensions By-name лениво это другой пример того, где неявно могут быть parameters Non local return зашиты closures. Следующие два примера идентичны: Local functions Lazy values d e f foo ( x : => Int ) { d e f foo ( x : ( ) => Int ) { Generated ByteCode println ( x ) println ( x ( ) ) } } Binary compatibility foo ( 1 ) foo ( ( ) => 1 ) Questions? Что изредка может приводить к ошибке (параметр будет вычисляться каждый раз, когда к нему будет производится обращение). 4 / 19
  • 5. Non local return Syntactic sugar For Return statement внутри closure на деле компилируется в comprehensions By-name код, который бросает NonLocalReturnControl. В parameters Non local return большинстве случаев это удобно, но нужно учитывать Local functions следующее Lazy values Generated В критичных по производительности кусках кода этот ByteCode Binary exception следует избегать compatibility Нельзя ловить Throwable в том месте, где этот Questions? exception бросается В силу синтаксического сахара описанного ранее, все это может происходить неявно (for-comprehensions и by-name parameters) 5 / 19
  • 6. Local functions Syntactic sugar For В Java любой вспомогательный код оформляется в виде comprehensions By-name private методов на уровне класса. В Scala это можно parameters Non local return сделать более структурированным, если использовать Local functions локальные методы, хотя на уровне bytecode получается Lazy values Generated примерно тоже самое: ByteCode Binary compatibility import scala . runtime . IntRef ; public class LocalFunctions { Questions? class LocalFunctions { p u b l i c void foo () { def foo { I n t R e f i $ 1 = new I n t R e f ( 1 ) ; var i = 1 i n t j$1 = 2; val j = 2 l o c a l $ 1 ( i$1 , j$1 ) ; def local { i += j   l o c a l $ 1 ( i$1 , j$1 ) ; } } p r i v a t e f i n a l void local$1 ( local IntRef intref , i n t i ) { local i n t r e f . e l e m += i ; } } } p u b l i c L o c a l F u n c t i o n s ( ) {} } 6 / 19
  • 7. Lazy values Syntactic sugar For Это тоже синтаксический сахар, который надо comprehensions By-name использовать аккуратно (так как возможны deadlock и parameters Non local return проблемы производительности). Независимо от Local functions расположения lazy val, компилируется он таким образом Lazy values Generated ByteCode import scala . runtime . BoxedUnit ; Binary p u b l i c c l a s s Lazy { compatibility public int x () { i f ( ( b i t m a p $ 0 & 2 ) == 0 ) Questions? synchronized ( this ) { i f ( ( b i t m a p $ 0 & 2 ) == 0 ) { x = 1; bitmap$0 = bitmap$0 | 2; c l a s s Lazy { lazy val x = 1   } BoxedUnit _tmp = } BoxedUnit . UNIT ; } return x ; } p u b l i c L a z y ( ) {} private int x ; public v o l a t i l e i n t bitmap$0 ; } 7 / 19
  • 8. Syntactic sugar Generated ByteCode Classes and names Objects Traits Trait subclasses Linearization Initialisation order Binary Generated ByteCode compatibility Questions? 8 / 19
  • 9. Classes and names Syntactic sugar Для классов ничего магического не происходит. Generated ByteCode Как преобразуются имена. Для большинства символов Classes and names Objects есть его текстовый эквивалент Traits Trait subclasses :   $colon Linearization Initialisation order +   $plus Binary ©   $u00A9 compatibility Questions? Внутри Scala кода можно использовать оба варианта подобных идентификаторов Подробнее можно изучить преобразования с помощью методов NameTransfomer.encode/decode из scala-compiler.jar. 9 / 19
  • 10. Objects Syntactic sugar Объект всегда компилируется в два класса. Generated ByteCode Classes and names Object$ содержит в себе статическое поле MODULE$, Objects а также код всех методов Traits Trait subclasses Object содержит в себе все статические методы Linearization Initialisation order объекта, с телом вида Object$.MODULE$.foo() Binary compatibility Важно понимать, что статические методы добавлены для Questions? удобства вызова из Java. Тем не менее они добавляются не всегда. В Companion Trait не добавляется ничего. В Companion Class не добавляются методы с таким именем, которое уже есть в этом классе Методы класса java.lang.Object 10 / 19
  • 11. Traits Syntactic sugar Если trait отличается от обычного интерфейса в Java Generated ByteCode наличием конкретных методов, то к соответствующему Classes and names Objects интерфейсу будет создан класс Trait$class с Traits Trait subclasses имплементацией этих методов. Linearization Initialisation order Binary public abstract class A$class { compatibility public static int foo ( A $this , int x) { Questions? return 2; trait A { } val x = 1   public s t a t i c void $init$ ( A $this def foo ( x : Int ) = 2 ) { } $this . test$A$_setter_$x_$eq (1) ; } } 11 / 19
  • 12. Trait subclasses Syntactic sugar Если в Java попытаться реализовать Trait, в котором есть Generated ByteCode уже имплементированые методы, то их все равно Classes and names Objects пришлось бы реализовывать. Другой вопрос, что это Traits Trait subclasses можно сделать предельно легко: Linearization Initialisation order Binary i n t foo ( ) { r e t u r n Trait$class . foo ( t h i s ) ; } compatibility Questions? В случае наследников написанных на Scala, то же самое делает компилятор. 12 / 19
  • 13. Linearization Syntactic sugar Этот алгоритм требуется компилятору, чтобы определить, Generated ByteCode в каком порядке надо искать методы в базовых классах. Classes and names Objects Traits Trait subclasses trait A extends B Linearization trait B Initialisation order class C extends B Binary class D extends C with A compatibility Questions? Здесь порядок D, A, C, B. Если два метода с одинаковой сигнатурой без модификатора ’override’ приходят в класс наследник из супертрейтов, то ошибки не будет, так как обязательно надо будет переопределить эту сигнатуру. Если же у кого-то есть модификатор ’override’, может случится неявный override согласно правилам линеаризации. 13 / 19
  • 14. Initialisation order Syntactic sugar Инициализация происходит в порядке, обратном Generated ByteCode линеаризации. Если к переменной обратиться до того, как Classes and names Objects она проинициализирована, можно получить NPE. Traits Trait subclasses Есть два способа избавится от подобных проблем: Linearization Initialisation order Использовать lazy val Binary compatibility Использовать early definitions Questions? 14 / 19
  • 16. Methods Syntactic sugar Здесь все очень похоже на Java. Чаще всего проблем не Generated ByteCode будет. Binary compatibility Добавлять метод можно даже в Trait, но только если Methods Values старые методы не ссылаются на новые, так как Lazy values имплементации в классы наследники добавлены не Questions? будут. В класс опасно добавлять методы, имена которых совпадают с именем методов из Companion Object, так как статические реализации будут удалены компилятором, что может вызвать проблемы с кодом написанным не на Scala. 16 / 19
  • 17. Values Syntactic sugar Если переменная находится в классе или объекте, то Generated ByteCode переменная компилируется в getter, setter (для variables) и Binary compatibility field, который инциализируется в конструкторе класса. А Methods значит все будет также хорошо как и с методами. Values Lazy values Если переменная находится в Trait, то она компилируется Questions? в getter и setter (всегда). Инициализация происходит в методе Trait$class.$init$ через вызов setter. Значит добавлять переменную в трейт нельзя. Так как будет вызван абстрактный setter. По аналогичным причинам нельзя изменять def на val Тем не менее val на def также изменять нельзя, так как тогда в классах наследниках, где как раз и хранится field, переменная не будет проинициализирована. 17 / 19
  • 18. Lazy values Syntactic sugar В подклассах не генерируется field bitmap, если он есть в Generated ByteCode базовом классе. Binary compatibility Поэтому в этих случаях добавлять lazy value в классы Methods Values нельзя Lazy values В Trait добавлять можно, если эта переменная не Questions? будет использована в старом коде Так как компиляция lazy val в Trait от компиляции метода не отличается совсем, то их можно заменять друг на друга, учитывая только, что в наследниках подобная семантика не изменится 18 / 19