Обновить

Комментарии 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), так как не имеет смысла создавать лишние объекты
А можно ссылку? Последний раз когда я смотрел, оно именно так и компилировалось.
docs.scala-lang.org/overviews/core/value-classes.html

Позор мне, забыл. Только их использование сильно ограничено. И реально объект создается значительно чаще, чем хотелось бы.
Через пол-годика-годик будет в этой области улучшение:
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.
Насколько близко будущее с Dotty и есть уже более конкретный список различий (относительно stackoverflow.com/questions/20130546/how-to-program-in-scala-to-be-forward-compatible-with-dotty), который может потребовать переписывания кода приложений?
Слушайте доклад Мартина на 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, но не то на чем он построен.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Сайт
www.golovachcourses.com
Дата регистрации
Дата основания
Численность
2–10 человек
Местоположение
Украина