Александр Подхалюзин, «Магия Scala изнутри»
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

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

on

  • 6,860 views

В своем докладе Александр расскажет о байткоде и о том, как сохранить его совместимость и повысить ...

В своем докладе Александр расскажет о байткоде и о том, как сохранить его совместимость и повысить производительность.

Statistics

Views

Total Views
6,860
Views on SlideShare
849
Embed Views
6,011

Actions

Likes
0
Downloads
12
Comments
0

7 Embeds 6,011

http://habrahabr.ru 5981
http://m.habrahabr.ru 19
http://indieweb.ru 6
http://translate.googleusercontent.com 2
http://3lp.cx 1
http://gaeproxyhttp.appspot.com 1
http://sysmagazine.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

  • 1. Scala magicАлександр Подхалюзин 19 мая 2012 г. 1 / 19
  • 2. Syntactic sugarForcomprehensionsBy-nameparametersNon local returnLocal functionsLazy valuesGeneratedByteCodeBinary Syntactic sugarcompatibilityQuestions? 2 / 19
  • 3. For comprehensionsSyntactic sugarFor В Scala for является синтаксическим сахаром, тем неcomprehensionsBy-name менее правила преобразования довольно сложныparametersNon local return Один генератор с ’yield’ тоже, что вызов метода ’map’Local functionsLazy values Один генератор без ’yield’ тоже, что ’foreach’Generated Несколько генераторов транслируются во ’flatMap’ByteCodeBinarycompatibilityQuestions? 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 parametersSyntactic sugarFor Возможность в вызов метода передавать выраженияcomprehensionsBy-name лениво это другой пример того, где неявно могут бытьparametersNon local return зашиты closures. Следующие два примера идентичны:Local functionsLazy values d e f foo ( x : => Int ) { d e f foo ( x : ( ) => Int ) {GeneratedByteCode println ( x ) println ( x ( ) ) } }Binarycompatibility foo ( 1 ) foo ( ( ) => 1 )Questions? Что изредка может приводить к ошибке (параметр будет вычисляться каждый раз, когда к нему будет производится обращение). 4 / 19
  • 5. Non local returnSyntactic sugarFor Return statement внутри closure на деле компилируется вcomprehensionsBy-name код, который бросает NonLocalReturnControl. ВparametersNon local return большинстве случаев это удобно, но нужно учитыватьLocal functions следующееLazy valuesGenerated В критичных по производительности кусках кода этотByteCodeBinary exception следует избегатьcompatibility Нельзя ловить Throwable в том месте, где этотQuestions? exception бросается В силу синтаксического сахара описанного ранее, все это может происходить неявно (for-comprehensions и by-name parameters) 5 / 19
  • 6. Local functionsSyntactic sugarFor В Java любой вспомогательный код оформляется в видеcomprehensionsBy-name private методов на уровне класса. В Scala это можноparametersNon local return сделать более структурированным, если использоватьLocal functions локальные методы, хотя на уровне bytecode получаетсяLazy valuesGenerated примерно тоже самое:ByteCodeBinarycompatibility 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 valuesSyntactic sugarFor Это тоже синтаксический сахар, который надоcomprehensionsBy-name использовать аккуратно (так как возможны deadlock иparametersNon local return проблемы производительности). Независимо отLocal functions расположения lazy val, компилируется он таким образомLazy valuesGeneratedByteCode 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 sugarGeneratedByteCodeClasses and namesObjectsTraitsTrait subclassesLinearizationInitialisation orderBinary Generated ByteCodecompatibilityQuestions? 8 / 19
  • 9. Classes and namesSyntactic sugar Для классов ничего магического не происходит.GeneratedByteCode Как преобразуются имена. Для большинства символовClasses and namesObjects есть его текстовый эквивалентTraitsTrait subclasses :   $colonLinearizationInitialisation order +   $plusBinary ©   $u00A9compatibilityQuestions? Внутри Scala кода можно использовать оба варианта подобных идентификаторов Подробнее можно изучить преобразования с помощью методов NameTransfomer.encode/decode из scala-compiler.jar. 9 / 19
  • 10. ObjectsSyntactic sugar Объект всегда компилируется в два класса.GeneratedByteCodeClasses and names Object$ содержит в себе статическое поле MODULE$,Objects а также код всех методовTraitsTrait subclasses Object содержит в себе все статические методыLinearizationInitialisation order объекта, с телом вида Object$.MODULE$.foo()Binarycompatibility Важно понимать, что статические методы добавлены дляQuestions? удобства вызова из Java. Тем не менее они добавляются не всегда. В Companion Trait не добавляется ничего. В Companion Class не добавляются методы с таким именем, которое уже есть в этом классе Методы класса java.lang.Object 10 / 19
  • 11. TraitsSyntactic sugar Если trait отличается от обычного интерфейса в JavaGeneratedByteCode наличием конкретных методов, то к соответствующемуClasses and namesObjects интерфейсу будет создан класс Trait$class сTraitsTrait subclasses имплементацией этих методов.LinearizationInitialisation orderBinary 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 subclassesSyntactic sugar Если в Java попытаться реализовать Trait, в котором естьGeneratedByteCode уже имплементированые методы, то их все равноClasses and namesObjects пришлось бы реализовывать. Другой вопрос, что этоTraitsTrait subclasses можно сделать предельно легко:LinearizationInitialisation orderBinary i n t foo ( ) { r e t u r n Trait$class . foo ( t h i s ) ; }compatibilityQuestions? В случае наследников написанных на Scala, то же самое делает компилятор. 12 / 19
  • 13. LinearizationSyntactic sugar Этот алгоритм требуется компилятору, чтобы определить,GeneratedByteCode в каком порядке надо искать методы в базовых классах.Classes and namesObjectsTraitsTrait subclasses trait A extends BLinearization trait BInitialisation order class C extends BBinary class D extends C with AcompatibilityQuestions? Здесь порядок D, A, C, B. Если два метода с одинаковой сигнатурой без модификатора ’override’ приходят в класс наследник из супертрейтов, то ошибки не будет, так как обязательно надо будет переопределить эту сигнатуру. Если же у кого-то есть модификатор ’override’, может случится неявный override согласно правилам линеаризации. 13 / 19
  • 14. Initialisation orderSyntactic sugar Инициализация происходит в порядке, обратномGeneratedByteCode линеаризации. Если к переменной обратиться до того, какClasses and namesObjects она проинициализирована, можно получить NPE.TraitsTrait subclasses Есть два способа избавится от подобных проблем:LinearizationInitialisation order Использовать lazy valBinarycompatibility Использовать early definitionsQuestions? 14 / 19
  • 15. Syntactic sugarGeneratedByteCodeBinarycompatibilityMethodsValuesLazy valuesQuestions? Binary compatibility 15 / 19
  • 16. MethodsSyntactic sugar Здесь все очень похоже на Java. Чаще всего проблем неGeneratedByteCode будет.Binarycompatibility Добавлять метод можно даже в Trait, но только еслиMethodsValues старые методы не ссылаются на новые, так какLazy values имплементации в классы наследники добавлены неQuestions? будут. В класс опасно добавлять методы, имена которых совпадают с именем методов из Companion Object, так как статические реализации будут удалены компилятором, что может вызвать проблемы с кодом написанным не на Scala. 16 / 19
  • 17. ValuesSyntactic sugar Если переменная находится в классе или объекте, тоGeneratedByteCode переменная компилируется в getter, setter (для variables) иBinarycompatibility field, который инциализируется в конструкторе класса. АMethods значит все будет также хорошо как и с методами.ValuesLazy values Если переменная находится в Trait, то она компилируетсяQuestions? в getter и setter (всегда). Инициализация происходит в методе Trait$class.$init$ через вызов setter. Значит добавлять переменную в трейт нельзя. Так как будет вызван абстрактный setter. По аналогичным причинам нельзя изменять def на val Тем не менее val на def также изменять нельзя, так как тогда в классах наследниках, где как раз и хранится field, переменная не будет проинициализирована. 17 / 19
  • 18. Lazy valuesSyntactic sugar В подклассах не генерируется field bitmap, если он есть вGeneratedByteCode базовом классе.Binarycompatibility Поэтому в этих случаях добавлять lazy value в классыMethodsValues нельзяLazy values В Trait добавлять можно, если эта переменная неQuestions? будет использована в старом коде Так как компиляция lazy val в Trait от компиляции метода не отличается совсем, то их можно заменять друг на друга, учитывая только, что в наследниках подобная семантика не изменится 18 / 19
  • 19. Syntactic sugarGeneratedByteCodeBinarycompatibilityQuestions? Questions? 19 / 19