Pull to refresh

Comments 28

И потому при компиляции «раскручивается» в нечто типа
import scala.runtime.RichInt

object Demo {
  val tmp: Range = new RichInt(1).to(10)
  for (k <- tmp) {
    println(k)
  }
}


Ну на самом деле (но это не 100%) компилятор делает оптимизацию, и превращает def to(that: Int) в static def to(x1: Int, x2: Int), так как не имеет смысла создавать лишние объекты
А можно ссылку? Последний раз когда я смотрел, оно именно так и компилировалось.
Через пол-годика-годик будет в этой области улучшение:
github.com/lampepfl/dotty/pull/411
Скорее всего будут — массивы value-classов, value-class-ы поверх value-class-ов, отсуствие боксинга в аннонимных функциях.
Маловероятно, но возможно — специализация для value-class-ов.
Хз, надо разбираться, может надо это включать, но вот такой класс
class Demo {
  def f(x: Int) = 1 to x
}


у меня компилируется вот в это
public class tmp.Demo {
  public scala.collection.immutable.Range$Inclusive f(int);
    Code:
       0: getstatic     #16  // Field scala/runtime/RichInt$.MODULE$:Lscala/runtime/RichInt$;
       3: getstatic     #21  // Field scala/Predef$.MODULE$:Lscala/Predef$;
       6: iconst_1
       7: invokevirtual #25  // Method scala/Predef$.intWrapper:(I)I
      10: iload_1
      11: invokevirtual #29  // Method scala/runtime/RichInt$.to$extension0:(II)Lscala/collection/immutable/Range$Inclusive;
      14: areturn

  public tmp.Demo();
    Code:
       0: aload_0
       1: invokespecial #37  // Method java/lang/Object."<init>":()V
       4: return
}


т.е. ходят в
@inline implicit def intWrapper(x: Int)         = new runtime.RichInt(x)
/source>
и, судя по всему, возвращаются со свежей ссылкой на RichInt (так как дальше вызывают через invokevirtual)

почему метод называется RichInt$.to$extension0, надо копать.
Хотя сигнатура метода intWrapper (I)I — как будто int -> int, а RichInt$ — может быть companion object с «статическими методами» (на самом деле методами одного синглетонного экземпляра, что лежит в статическом scala.runtime.RichInt$.MODULE$)
Вот все, надо смотреть

D:\Program Files\Java\jdk1.8.0\bin>javap -p -c -v Demo
Classfile /D:/Program Files/Java/jdk1.8.0/bin/Demo.class
  Last modified Apr 22, 2015; size 1076 bytes
  MD5 checksum 7f7e8e8353c9bf7f6bf70c6c4858c5b8
  Compiled from "Demo.scala"
public class tmp.Demo
  SourceFile: "Demo.scala"
  InnerClasses:
       public static #42= #39 of #41; //Inclusive=class scala/collection/immutable/Range$Inclusive of class scala/collection/immutable/Range
  RuntimeVisibleAnnotations:
    0: #6(#7=s#8)
Error: unknown attribute
    ScalaSig: length = 0x3
     05 00 00
  minor version: 0
  major version: 50
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Utf8               tmp/Demo
   #2 = Class              #1             //  tmp/Demo
   #3 = Utf8               java/lang/Object
   #4 = Class              #3             //  java/lang/Object
   #5 = Utf8               Demo.scala
   #6 = Utf8               Lscala/reflect/ScalaSignature;
   #7 = Utf8               bytes
   #8 = Utf8               ♠☺§2A!☺☻☺♂\t!A)Z7p§♣↓◄a☺;na♫☺1C☺☺!\t9!\"D☺\t§♣I◄!B:dC
2♀↨BA♠\t♣↓\te.▼*fM\")Q☻☺C☺↔♣1A(←8jiz\"↕a♦\t♥!☺i◄A☺♣♠%☺!\taE☺☻MR◄A♥\t\t♥+uq!AF♫♫♥
]Q!☺G\r☻‼%lW.▲;bE2,'B☺♫\t♥)↓w♫∟7fGRLwN\♣♥9]\tQAU1oO▬L!AH►♥‼%s7\r\;tSZ,'B☺☼↑◄§\t‼
♥1☺#♥CA♦$‼\t!♥BA☻J]R♦
   #9 = Utf8               f
  #10 = Utf8               (I)Lscala/collection/immutable/Range$Inclusive;
  #11 = Utf8               scala/runtime/RichInt$
  #12 = Class              #11            //  scala/runtime/RichInt$
  #13 = Utf8               MODULE$
  #14 = Utf8               Lscala/runtime/RichInt$;
  #15 = NameAndType        #13:#14        //  MODULE$:Lscala/runtime/RichInt$;
  #16 = Fieldref           #12.#15        //  scala/runtime/RichInt$.MODULE$:Lscala/runtime/RichInt$;
  #17 = Utf8               scala/Predef$
  #18 = Class              #17            //  scala/Predef$
  #19 = Utf8               Lscala/Predef$;
  #20 = NameAndType        #13:#19        //  MODULE$:Lscala/Predef$;
  #21 = Fieldref           #18.#20        //  scala/Predef$.MODULE$:Lscala/Predef$;
  #22 = Utf8               intWrapper
  #23 = Utf8               (I)I
  #24 = NameAndType        #22:#23        //  intWrapper:(I)I
  #25 = Methodref          #18.#24        //  scala/Predef$.intWrapper:(I)I
  #26 = Utf8               to$extension0
  #27 = Utf8               (II)Lscala/collection/immutable/Range$Inclusive;
  #28 = NameAndType        #26:#27        //  to$extension0:(II)Lscala/collection/immutable/Range$Inclusive;
  #29 = Methodref          #12.#28        //  scala/runtime/RichInt$.to$extension0:(II)Lscala/collection/immutable/Range$Inclusive;
  #30 = Utf8               this
  #31 = Utf8               Ltmp/Demo;
  #32 = Utf8               x
  #33 = Utf8               I
  #34 = Utf8               <init>
  #35 = Utf8               ()V
  #36 = NameAndType        #34:#35        //  "<init>":()V
  #37 = Methodref          #4.#36         //  java/lang/Object."<init>":()V
  #38 = Utf8               scala/collection/immutable/Range$Inclusive
  #39 = Class              #38            //  scala/collection/immutable/Range$Inclusive
  #40 = Utf8               scala/collection/immutable/Range
  #41 = Class              #40            //  scala/collection/immutable/Range
  #42 = Utf8               Inclusive
  #43 = Utf8               Code
  #44 = Utf8               LocalVariableTable
  #45 = Utf8               LineNumberTable
  #46 = Utf8               SourceFile
  #47 = Utf8               InnerClasses
  #48 = Utf8               RuntimeVisibleAnnotations
  #49 = Utf8               ScalaSig
{
  public scala.collection.immutable.Range$Inclusive f(int);
    descriptor: (I)Lscala/collection/immutable/Range$Inclusive;
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=2
         0: getstatic     #16                 // Field scala/runtime/RichInt$.MODULE$:Lscala/runtime/RichInt$;
         3: getstatic     #21                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
         6: iconst_1
         7: invokevirtual #25                 // Method scala/Predef$.intWrapper:(I)I
        10: iload_1
        11: invokevirtual #29                 // Method scala/runtime/RichInt$.to$extension0:(II)Lscala/collection/immutable/Range$Inclusive;
        14: areturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      15     0  this   Ltmp/Demo;
            0      15     1     x   I
      LineNumberTable:
        line 4: 3

  public tmp.Demo();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #37                 // Method java/lang/Object."<init>":()V
         4: return
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Ltmp/Demo;
      LineNumberTable:
        line 5: 0
}
scala компилятор никогда не делает статические методы. Он только делает статические forwarders для методов в синглтон-обьектах.
Ну я это утрировано сказал
Спасибо автору за данную статью. Да и вообще побольше бы статей про Scala на хабре.
Вообще довольно таки странно, что есть постоянные рубрики Дайджест + php / python / веб-разработки / мобильной разработки и т.д. Но при этом нет не то чтобы дайджеста по Java / Scala / Groovy / Clojure etc., а хотя бы по JVM в целом. Имхо, такая рубрика бы взлетела… Разные подкасты(например «Разбор полетов») очень хорошо заходят, вот бы еще более подробную инфу в виде статьи-сборки последних событий получать. Может кто-то из людей в теме попробует организовать «Дайджест из мира JVM»? )
А что Вы имеете в виду под 'дайджестом'?
1) Глубокий обзор фич всех времен и народов («Все что только можно делать c gc, java.lang.references.*, ...», «Все 100500 способов работать с многопоточностью», ...)?
2) Обзор новинок («Все новые трюки с Java 8», «Что нового в Scala 2.11», ...)?
3) Просто новости рынка (по примеру ленты у theserverside.com, infoq.com/java/news/)?
Обзор новых фич, фрэймворков/либ(и мажорных изменениях в наиболее важных из них), нововведений и т.д… Сбор ссылок на хорошие статьи — тоже весьма удобная штука. Все это можно в интернете и так найти, но не всегда удается за всем следить.
Мне кажется, это уровень целого «сетевого издательства» или какого-то безумного гения. Отслеживать и публиковать изменения в 3-6 языках (Java, Scala, Clojure, Groovy, JRuby, Jython) с развитой системой фреймворков — это безумный труд. И странная специализация для одного человека.

Я сидел и в java 10 лет, но только местами узнавал, что Log4j2 догнал, а то и перегнал по фичам slf4j, или что асинхронное логирование в Log4J2 сделано на основе сверхбыстродействующего биржевого фреймворка Desruptor.

А остслеживать такое постоянно и на всех «фронтах» — респект такому мозгу!
Пока я жил в Москве, тоже не знал о таких вещах.
Как оказалось это вопрос «удаления» от тех людей, которые вершат изменения. Я не припоминаю чтобы кто-либо из моих знакомых в Москве ездил на конференции по другим странам, а тем более был докладчиком.

Сейчас, находясь в Швейцарии, работая над Scala я обычно узнаю все Scala-новости в течении недели.

сверхбыстродействующего биржевого фреймворка Desruptor


Disruptor это очень быстрая реализация фиксированного по размеру кольцевого буфера. Быстрая она не из за фундаментальных нововведений, а из за того что люди полезли в железо и учли мелкие детали, например порядок полей, выравнивание, конфликт строк памяти при запуске Cache Coherence Protocol, итд.
Ну это я так, для красного словца сказал.
Спасибо за статью, узнал кое-что новое (Infix types) и повторил старое, но редкоиспользуемое.

Парочка замечаний:
  • В примере с факториалом точка с запятой нужна, чтобы компилятор не искал «второй» операнд на следующей строке. Альтернатива странно смотрящейся точке с запятой будет просто одна пустая строка перед «println».
  • Почему-то в начале статьи вы пишете implicit с «d» на конце
  • Я знаю, что в комментариях не принято писать о TYPO, но все же, исправьте «type constcructor»

Как один из разработчиков компилятора говорю — не нужно бездумно совать всюду `@inline`. Тут — это не помогает компилятору никак, но замусоривает ваш код. Каждая такая аннотация должна быть хорошо продумана.
DelayedInit тоже не стоит описовать в курсе вообще! Oн deprecated и не будет поддерживаться в будущем компиляторе — Dotty.
Спасибо, не знал. Да, во второй части из ленивого, конечно, будут Streams как пример ленивых структур данных.
Streams тоже to-be deprecated, потому что они дают ложное впечатление контроля.
Они не deprecated потому что мы замену еще не сделали — она будет основана на инфраструктуре Dotty и будет иметь много общего со Stream Fusion из Haskell.
Слушайте доклад Мартина на scaladays.org 8 июня.
Мое мнение — скоро оба компилятора будут сосуществовать. Основные отличия для меня(это мое мнение и не факт что все выйдет так как я думаю):
  • появится другая екосистема, дружественная к оптимизаторам(моя область) и метапрограммированию(Женя Бурмако), если коротко — теперь scala будет компилироваться в некое промежуточное представление, а оно уже будет компилироваться в JVM bytecode\javascript\LLVM. LLVM — под вопросом. Но один активист делает титанические усилия в эту сторону.
  • Выдадим пользователю типа объединения(union) и типы пересечения(intersection). Для меня это заменяет enum-ы на чтото что разумно.
  • Изменится схема компиляции lazy val-ов. Теперь lazy val без `@volatile` не thread-safe, и доступ к таким быстрее раз в 10. `@volatile` lazy val будет быстрее на 10-20%, позволит инициализовывать несколько lazy полей одновременно в одном объекте(он почти не синхронизуется на this), и вообще в большинстве случаев будет lock-free и значит без дедлоков.
  • метапрограммирование — scalameta.org обычные макросы не поддерживаются.
  • частью экосистемы станет dotty linker: штукенция которая делает глобальный анализ программы, смотрит как вы используете библиотеки, тюнит их для вас и встраивает в ваше приложение. Это реинкарнация scala-blitz.github.io. Позволяет писать высокоуровневый код, зная что компилятор сможет заменить его на эффективный. Из спорных вещей — это аналог статической линковки, те при изменении зависимостей нужна перекомпиляция. Это не часть Dotty, тк в некоторых ситуациях люди привыкли менять один jar чтобы пофиксить баги в зависимостях. Это только для тех кому нужна максимальная производительность, или минимальный размер(Android например). Он же будет делать specialization только для тех классов которые используются. В теории это может позволить нам сделать reified generics но мы не решили хорошо ли это.
  • более быстрый компилятор — мы еще не тюнили его, но даже сейчас он примерно такойже по скорости компиляции как scalac
  • arrays of value classes
  • value classes over value classes
  • под вопросом — multifield value classes.


Как видите, мы хотим улучшить многое. А любое улучшение приходит с багами. Потому и будут два компилятора.
В последнее время, с момента появления Typesafe, scala стала намного более консервативной, и это понятно и разумно.
Нужно понимать что в dotty мы(лаборатория Мартина) хотим проводить исследования того, каким язык должен быть.
Нужна стабильность — scalac. Нужны новые фичи — Dotty.
Сколько продлится сосуществование — мне самому любопытно. Это уже вопрос граничащий с коммерческими вопросами для Typesafe, тк они продают многолетние контракты поддержки.
В список тем для курса ИМХО стоит добавить default arguments,
а в Pattern matching добавить name-based pattern matching.
Да, named и default аргументы я читаю в ООП/методах+конструкторах. Достаточно краткая тема. Или я чего-то не знаю?
Зависит от того насколько глубокий курс. Если вы рассказываете теорию множеств то можно пояснить почему default arguments не дружат с overload resolution.

Кстати, если курс предназначен для разработчиков, то из стандартного инструментария — macros, pickling(самый быстрый сериализатор, тк 90% работы делает во время компиляции и по возможности избегает reflection), spores(убеждается что лябмды не захватили чтото случайно в окружении, помогает с memory leak-ами бороться).

Из вещей которые стоит не рассказывать(точнее расказать что не стоит использовать) — xml как часть языка. Уже давно есть сильное намерение вынести его в string interpolation. В Dotty эта часть языка не поддерживается как таковая.
и, ИМХО, любой толковый курс по Scala сейчас должен включать String Interpolation,
А также лучше б ему включать хотябы минимум про blackbox macros.
Иначе вы упомянули shapeless, но не то на чем он построен.
Sign up to leave a comment.