Комментарии 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-ов.
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»? )
Вообще довольно таки странно, что есть постоянные рубрики Дайджест + 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/)?
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.
А остслеживать такое постоянно и на всех «фронтах» — респект такому мозгу!
Я сидел и в java 10 лет, но только местами узнавал, что Log4j2 догнал, а то и перегнал по фичам slf4j, или что асинхронное логирование в Log4J2 сделано на основе сверхбыстродействующего биржевого фреймворка Desruptor.
А остслеживать такое постоянно и на всех «фронтах» — респект такому мозгу!
Пока я жил в Москве, тоже не знал о таких вещах.
Как оказалось это вопрос «удаления» от тех людей, которые вершат изменения. Я не припоминаю чтобы кто-либо из моих знакомых в Москве ездил на конференции по другим странам, а тем более был докладчиком.
Сейчас, находясь в Швейцарии, работая над Scala я обычно узнаю все Scala-новости в течении недели.
Disruptor это очень быстрая реализация фиксированного по размеру кольцевого буфера. Быстрая она не из за фундаментальных нововведений, а из за того что люди полезли в железо и учли мелкие детали, например порядок полей, выравнивание, конфликт строк памяти при запуске Cache Coherence Protocol, итд.
Как оказалось это вопрос «удаления» от тех людей, которые вершат изменения. Я не припоминаю чтобы кто-либо из моих знакомых в Москве ездил на конференции по другим странам, а тем более был докладчиком.
Сейчас, находясь в Швейцарии, работая над Scala я обычно узнаю все Scala-новости в течении недели.
сверхбыстродействующего биржевого фреймворка Desruptor
Disruptor это очень быстрая реализация фиксированного по размеру кольцевого буфера. Быстрая она не из за фундаментальных нововведений, а из за того что люди полезли в железо и учли мелкие детали, например порядок полей, выравнивание, конфликт строк памяти при запуске Cache Coherence Protocol, итд.
www.cakesolutions.net/teamblogs обзоры еженедельные.
Спасибо за статью, узнал кое-что новое (Infix types) и повторил старое, но редкоиспользуемое.
Парочка замечаний:
Парочка замечаний:
- В примере с факториалом точка с запятой нужна, чтобы компилятор не искал «второй» операнд на следующей строке. Альтернатива странно смотрящейся точке с запятой будет просто одна пустая строка перед «println».
- Почему-то в начале статьи вы пишете implicit с «d» на конце
- Я знаю, что в комментариях не принято писать о TYPO, но все же, исправьте «type constcructor»
Как один из разработчиков компилятора говорю — не нужно бездумно совать всюду `@inline`. Тут — это не помогает компилятору никак, но замусоривает ваш код. Каждая такая аннотация должна быть хорошо продумана.
DelayedInit тоже не стоит описовать в курсе вообще! Oн deprecated и не будет поддерживаться в будущем компиляторе — Dotty.
Спасибо, не знал. Да, во второй части из ленивого, конечно, будут Streams как пример ленивых структур данных.
Насколько близко будущее с Dotty и есть уже более конкретный список различий (относительно stackoverflow.com/questions/20130546/how-to-program-in-scala-to-be-forward-compatible-with-dotty), который может потребовать переписывания кода приложений?
Слушайте доклад Мартина на scaladays.org 8 июня.
Мое мнение — скоро оба компилятора будут сосуществовать. Основные отличия для меня(это мое мнение и не факт что все выйдет так как я думаю):
Как видите, мы хотим улучшить многое. А любое улучшение приходит с багами. Потому и будут два компилятора.
В последнее время, с момента появления Typesafe, scala стала намного более консервативной, и это понятно и разумно.
Нужно понимать что в dotty мы(лаборатория Мартина) хотим проводить исследования того, каким язык должен быть.
Нужна стабильность — scalac. Нужны новые фичи — Dotty.
Сколько продлится сосуществование — мне самому любопытно. Это уже вопрос граничащий с коммерческими вопросами для Typesafe, тк они продают многолетние контракты поддержки.
Мое мнение — скоро оба компилятора будут сосуществовать. Основные отличия для меня(это мое мнение и не факт что все выйдет так как я думаю):
- появится другая екосистема, дружественная к оптимизаторам(моя область) и метапрограммированию(Женя Бурмако), если коротко — теперь 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.
а в Pattern matching добавить name-based pattern matching.
Да, named и default аргументы я читаю в ООП/методах+конструкторах. Достаточно краткая тема. Или я чего-то не знаю?
Зависит от того насколько глубокий курс. Если вы рассказываете теорию множеств то можно пояснить почему default arguments не дружат с overload resolution.
Кстати, если курс предназначен для разработчиков, то из стандартного инструментария — macros, pickling(самый быстрый сериализатор, тк 90% работы делает во время компиляции и по возможности избегает reflection), spores(убеждается что лябмды не захватили чтото случайно в окружении, помогает с memory leak-ами бороться).
Из вещей которые стоит не рассказывать(точнее расказать что не стоит использовать) — xml как часть языка. Уже давно есть сильное намерение вынести его в string interpolation. В Dotty эта часть языка не поддерживается как таковая.
Кстати, если курс предназначен для разработчиков, то из стандартного инструментария — macros, pickling(самый быстрый сериализатор, тк 90% работы делает во время компиляции и по возможности избегает reflection), spores(убеждается что лябмды не захватили чтото случайно в окружении, помогает с memory leak-ами бороться).
Из вещей которые стоит не рассказывать(точнее расказать что не стоит использовать) — xml как часть языка. Уже давно есть сильное намерение вынести его в string interpolation. В Dotty эта часть языка не поддерживается как таковая.
и, ИМХО, любой толковый курс по Scala сейчас должен включать String Interpolation,
А также лучше б ему включать хотябы минимум про blackbox macros.
Иначе вы упомянули shapeless, но не то на чем он построен.
А также лучше б ему включать хотябы минимум про blackbox macros.
Иначе вы упомянули shapeless, но не то на чем он построен.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
«Перегрузка операторов» в Scala