Scala magicАлександр Подхалюзин    19 мая 2012 г.                       1 / 19
Syntactic sugarForcomprehensionsBy-nameparametersNon local returnLocal functionsLazy valuesGeneratedByteCodeBinary        ...
For comprehensionsSyntactic sugarFor                   В Scala for является синтаксическим сахаром, тем неcomprehensionsBy...
By-name parametersSyntactic sugarFor                   Возможность в вызов метода передавать выраженияcomprehensionsBy-nam...
Non local returnSyntactic sugarFor                   Return statement внутри closure на деле компилируется вcomprehensions...
Local functionsSyntactic sugarFor                   В Java любой вспомогательный код оформляется в видеcomprehensionsBy-na...
Lazy valuesSyntactic sugarFor                   Это тоже синтаксический сахар, который надоcomprehensionsBy-name          ...
Syntactic sugarGeneratedByteCodeClasses and namesObjectsTraitsTrait subclassesLinearizationInitialisation orderBinary     ...
Classes and namesSyntactic sugar                       Для классов ничего магического не происходит.GeneratedByteCode     ...
ObjectsSyntactic sugar                       Объект всегда компилируется в два класса.GeneratedByteCodeClasses and names  ...
TraitsSyntactic sugar                       Если trait отличается от обычного интерфейса в JavaGeneratedByteCode          ...
Trait subclassesSyntactic sugar                       Если в Java попытаться реализовать Trait, в котором естьGeneratedByt...
LinearizationSyntactic sugar                       Этот алгоритм требуется компилятору, чтобы определить,GeneratedByteCode...
Initialisation orderSyntactic sugar                       Инициализация происходит в порядке, обратномGeneratedByteCode   ...
Syntactic sugarGeneratedByteCodeBinarycompatibilityMethodsValuesLazy valuesQuestions?        Binary compatibility         ...
MethodsSyntactic sugar                  Здесь все очень похоже на Java. Чаще всего проблем неGeneratedByteCode          бу...
ValuesSyntactic sugar                  Если переменная находится в классе или объекте, тоGeneratedByteCode          переме...
Lazy valuesSyntactic sugar                  В подклассах не генерируется field bitmap, если он есть вGeneratedByteCode    ...
Syntactic sugarGeneratedByteCodeBinarycompatibilityQuestions?                  Questions?                               19...
Upcoming SlideShare
Loading in...5
×

Scala Magic, Alexander Podhaliusin

1,000

Published on

Talk given by Alexander Podhaliusin at scaladev'12 (scaladev.ru)

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,000
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
5
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Scala Magic, Alexander Podhaliusin

  1. 1. Scala magicАлександр Подхалюзин 19 мая 2012 г. 1 / 19
  2. 2. Syntactic sugarForcomprehensionsBy-nameparametersNon local returnLocal functionsLazy valuesGeneratedByteCodeBinary Syntactic sugarcompatibilityQuestions? 2 / 19
  3. 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. 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. 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. 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. 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. 8. Syntactic sugarGeneratedByteCodeClasses and namesObjectsTraitsTrait subclassesLinearizationInitialisation orderBinary Generated ByteCodecompatibilityQuestions? 8 / 19
  9. 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. 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. 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. 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. 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. 14. Initialisation orderSyntactic sugar Инициализация происходит в порядке, обратномGeneratedByteCode линеаризации. Если к переменной обратиться до того, какClasses and namesObjects она проинициализирована, можно получить NPE.TraitsTrait subclasses Есть два способа избавится от подобных проблем:LinearizationInitialisation order Использовать lazy valBinarycompatibility Использовать early definitionsQuestions? 14 / 19
  15. 15. Syntactic sugarGeneratedByteCodeBinarycompatibilityMethodsValuesLazy valuesQuestions? Binary compatibility 15 / 19
  16. 16. MethodsSyntactic sugar Здесь все очень похоже на Java. Чаще всего проблем неGeneratedByteCode будет.Binarycompatibility Добавлять метод можно даже в Trait, но только еслиMethodsValues старые методы не ссылаются на новые, так какLazy values имплементации в классы наследники добавлены неQuestions? будут. В класс опасно добавлять методы, имена которых совпадают с именем методов из Companion Object, так как статические реализации будут удалены компилятором, что может вызвать проблемы с кодом написанным не на Scala. 16 / 19
  17. 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. 18. Lazy valuesSyntactic sugar В подклассах не генерируется field bitmap, если он есть вGeneratedByteCode базовом классе.Binarycompatibility Поэтому в этих случаях добавлять lazy value в классыMethodsValues нельзяLazy values В Trait добавлять можно, если эта переменная неQuestions? будет использована в старом коде Так как компиляция lazy val в Trait от компиляции метода не отличается совсем, то их можно заменять друг на друга, учитывая только, что в наследниках подобная семантика не изменится 18 / 19
  19. 19. Syntactic sugarGeneratedByteCodeBinarycompatibilityQuestions? Questions? 19 / 19
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×