Почему Scala не был реализован с C или C ++

28

Кто-нибудь знает, почему Scala был реализован на Java и .NET вместо C или C ++? Большинство языков реализованы с помощью Cor C ++ [т.е. Erlang, Python, PHP, Ruby, Perl]. Каковы преимущества для Scala, реализованные в Java и .NET, помимо предоставления доступа к библиотекам Java и .NET?

ОБНОВИТЬ

Разве Scala не получит больше пользы, если он будет реализован в C, потому что его можно настраивать лучше, чем полагаться на JVM?

Джошуа Партоги
источник
18
Кроме того, возможность использовать существующие библиотеки Java и тесно взаимодействовать с Java-кодом - ОГРОМНОЕ преимущество, а не незначительная вещь.
Тамас Селеи,
6
@OP: вы говорите так, как будто плохо реализовывать язык поверх JVM (или CLR в этом отношении). Упомянутая вами настройка, которая возможна в C, далеко не так велика, как настройка CLR или JVM. И если платформа улучшается, ваш язык автоматически получает ее бесплатно. Учитывая выбор, никто не должен реализовывать свой язык поверх good'ol C больше imho.
Чии
8
@Chii, просто признай это, Java все еще медленнее, чем C.
Джошуа Партоги
19
@jpartogi, Java не может быть медленнее или быстрее, чем C. Это оба языка, а не жеребцы. В некоторых конкретных условиях некоторый конкретный код, скомпилированный компилятором Java и выполняемый с определенной JVM, работает медленнее, чем примерно сопоставимый код, сгенерированный компилятором C. В некоторых других условиях последнее будет медленнее.
SK-logic
4
Среда выполнения Scala - это программа на C ++; JVM.
mike30

Ответы:

59

Вопрос сбивает с толку, поскольку C и C ++ являются языками , а JVM - это виртуальная машина, а .Net - платформа . Scala может быть реализован на C или C ++ и может генерировать машинный код вместо байт-кода для виртуальной машины.

Отвечая на вопрос, который был задан:

Scala не был реализован в C или C ++, потому что Scala, язык, на котором он фактически реализован, гораздо лучше.

Почему лучше? Ну, иди почитай о целях Одерского для языка Скала .

Отвечая на вопрос, который мог быть задуман:

Scala генерирует в основном байт-код JVM, поскольку он обеспечивает отличную переносимость, а также такие функции, как надежный и эффективный сборщик мусора, оптимизация во время выполнения и своевременная компиляция JVM .

Позвольте мне повторить последнее: JVM будет компилироваться в «горячие точки» машинного кода в коде, который он запускает. Это компилируется так же, как компиляторы C и C ++.

Доступны и другие виртуальные машины, но Одерски, создатель Scala, уже был хорошо знаком с JVM. Он намеревался использовать CLR в качестве альтернативы, но усилия, чтобы добиться этого, еще не достигли успеха.

Отвечая на вопрос, который можно / нужно было задать:

Компиляция в машинный код не дает достаточных преимуществ по сравнению с компиляцией в байт-код JVM.

Конечно, можно создавать микробенчмарки в C или C ++, которые превосходят JVM-эквиваленты. Также верно, что чрезвычайно оптимизированный код на C или C ++ будет превосходить чрезвычайно оптимизированный код на Java или Scala. Однако разница не так уж велика для длительной программы.

Обратите внимание, что Scala не является особенно хорошим языком сценариев именно потому, что накладные расходы для краткосрочных программ слишком велики.

Однако в большинстве случаев скорость разработки и простота обслуживания важнее, чем скорость выполнения . В тех случаях, когда люди больше озабочены написанием кода очень высокого уровня, который легко понять и изменить, оптимизация времени выполнения, предоставляемая JVM, может легко превзойти оптимизацию времени компиляции, сделанную компиляторами C или C ++, делая JVM (и CLR) ) цель, которая на самом деле будет выполняться быстрее.

Таким образом, независимо от того, был ли вопрос о том, является ли компилятор Scala исполняемым машинным кодом или программы Scala являются машинным кодом, потенциальное увеличение скорости не обязательно приводит к реальному увеличению скорости.

И кстати,

Я приведу контрпример: Хаскелл. Haskell генерирует машинный код, и, тем не менее, программы на Haskell хуже в перестрелке Debian, чем Scala. Учитывая это, кто-нибудь может быть уверен, что программы Scala будут быстрее, если скомпилированы непосредственно в машинный код?

Даниэль С. Собрал
источник
3
@ mike30 Scala будет работать на любой JVM, даже если она не была написана на C ++, поэтому этот аргумент не сохраняется. И во время выполнения нет кода C ++, только машинный код. Я не уверен, о чем этот комментарий, хотя.
Даниэль С. Собрал
3
Суть в том, что генерация машинного кода является гораздо более сложной, чем генерация байт-кода, и она требует конкретной реализации для каждой операционной системы, а также настройки ЦП и различных архитектур (ARM, x86, x86_64) и расширенных инструкций (MMX, SSE). ...). Таким образом, делегировать JVM этот аспект.
Раффаэлло
2
Если вы так много говорите о производительности выполнения, почему вы не говорите о производительности памяти? Вы боитесь, что все может сложиться не так хорошо, как вы себе представляете?
luke1985
3
@ lukasz1985 Это влияет на производительность, но обсуждение производительности охватывает это, так что это не имеет значения в этом отношении. Все, что остается, - это заботиться о том, сколько памяти занимает приложение, и тогда вам придется выбирать между GC и этим, и я буду выбирать GC каждый раз, за ​​исключением очень специфических областей разработки, ни одна из которых не занята Scala. И «разве никто не вправе говорить» - это чушь собачья - все имеют это право. И хотя C / C ++ очень важен из-за устаревшего, они никогда не станут популярными, если бы они были выпущены за последние пять лет.
Даниэль С. Собрал
3
@ lukasz1985 Ваше единственное доказательство того, что я не понимаю, что я не согласен с вами. Альтернативное объяснение тому, что вы не правы. И, как кто-то живой и программирующий «тогда», я имею непосредственное представление о принятии решений, связанных с выбором С и С ++ по сравнению с современными альтернативами, которые я упоминаю не для того, чтобы доказать свою точку зрения, а для того, чтобы противопоставить их вашей: сходство к разговорной речи не имеет никакого отношения, тогда как сходство с машинным кодом было.
Даниэль С. Собрал
31

Одним из основных препятствий, с которыми сталкиваются языки при представлении миру в целом, является наличие библиотек. Традиционный ответ на это состоял в том, чтобы предоставить FFI (интерфейс внешней функции) на основе C, чтобы предоставить вам доступ к библиотекам на основе C. Это не идеально по ряду причин, главная из которых:

  • Существует множество способов взаимодействия библиотек, которые несовместимы со многими языками более высокого уровня. Например, если библиотека хочет указатель на a struct, как справляются языки без указателей и без указателей struct?
  • Существуют жесткие взаимодействия между моделями памяти различных библиотек и языков, которые часто не разрешимы или, если они разрешимы, очень подвержены ошибкам и ошибкам.
  • Клеевой код для многих FFI нетривиален и предполагает знание, которое на самом деле не может быть универсальным. (Хотите верьте, хотите нет, не все программисты являются гуру C, и они не хотят и не должны быть!)

Это становится еще хуже с C ++. C ++ даже не совместим с C ++ (я имею в виду на двоичном уровне) от компилятора до компилятора на той же платформе (!), Не говоря уже о других языках.

Ориентация на JVM решает многие из этих проблем, предоставляя вам доступ к абсолютно огромному набору библиотек на основе Java. (Как громадно? Просто рассмотрите огромный выбор Apache Software Foundation для начинающих.)

  • Соглашения Java о вызовах и владении являются более регулярными, чем C.
  • JVM также предоставляет единую модель памяти (включая сборку мусора) для языков и библиотек, с которыми можно взаимодействовать. Нет необходимости следить за тем, кто чем владеет, а кто где должен убирать. Среда выполнения делает это за вас.
  • Клеевой код для FFI, для большинства языков, построенных на JVM, отсутствует (так как он предоставляется в качестве основы закулисного языка). Нет необходимости программировать на Java, например, для доступа к библиотекам Java в Scala, Clojure, JRuby и т. Д. Вы обращаетесь к объектам Java так же, как к собственным «объектам» (пугают кавычки, потому что, например, Clojure не иметь реальные объекты в смысле ООП) и на вашем родном языке.

Помимо этих преимуществ у вас также есть дополнительные преимущества запуска в любом месте, где Java работает без перекомпиляции (но с тестированием!: Пишите один раз, тестируйте везде) и имеете доступ к довольно впечатляющей технологии JIT Java.

CLR обеспечивает аналогичные преимущества, но добавляет то, что является слабым местом IMO: это в значительной степени среда для привязки к поставщикам. (Да, я знаю о Mono. Я все еще думаю, что это среда блокировки поставщиков.)

ПРОСТО МОЕ правильное мнение
источник
3
Вы понимаете, что C # и CLR на самом деле являются открытым стандартом, который может использовать каждый.
Эрин
7
Я думаю, что немного о том, откуда я «знаю о Mono», а затем «все еще думаю, что это среда привязки к поставщикам», должно дать вам некоторую подсказку, Эрин.
ТОЛЬКО МОЕ правильное МНЕНИЕ
3
@ Эрин не все .NET Framework, хотя
альтернатива
1
@alternative: Если это слишком сложно, учтите, что тесты на соответствие Java по-прежнему не бесплатны, и в лучшем случае это 6 из полутора десятков других для Java.
Дедупликатор
18

Согласно этому интервью , доступ к существующей инфраструктуре Java и библиотекам был основной причиной.

... Java - это существующий язык с очень жесткими ограничениями. В результате я не мог сделать много вещей так, как хотел бы, - то, как я был убежден, было бы правильным способом сделать это. Поэтому после того времени, когда моя работа была направлена ​​на улучшение Java, я решил, что пришло время сделать шаг назад. Я хотел начать с чистого листа и посмотреть, смогу ли я разработать что-то лучше Java. Но в то же время я знал, что не могу начать с нуля. Мне пришлось подключиться к существующей инфраструктуре, потому что в противном случае просто нецелесообразно загружать себя из ничего без каких-либо библиотек, инструментов и тому подобного.

Поэтому я решил, что, хотя я хотел разработать язык, отличный от Java, он всегда будет подключаться к инфраструктуре Java - к JVM и его библиотекам . Это была идея ...

Иеремия
источник
10

Все другие языки, которые вы упоминаете, Erlang, Python, PHP, Ruby, Perl - все они были созданы до Java & .NET. Если создатели этих языков в то время имели в своем распоряжении среду выполнения Java или .NET, то, возможно, они могли использовать их при создании своего языка.

Конечно, я не могу говорить за разработчиков этих языков, поэтому не могу с уверенностью сказать , что они использовали бы .NET и / или Java при их создании, если бы они были доступны, но мне кажется, что отличная идея. В конце концов, разработав свой язык для компиляции с байт-кодом Java / .NET, вы получаете все преимущества компиляторов / оптимизаторов JIT, ваш язык автоматически работает на всех платформах, на которых работает Java / .NET, у вас есть доступ ко всем библиотеки Java / .NET и так далее.

Дин Хардинг
источник
2
Описанные преимущества являются некоторыми из причин того, что, например, Python был переопределен как для JVM (Jython), так и для .NET (IronPython).
Dancek
2
-1: Предположение, что новые языки могли зависеть от конкретной платформы (.Net или JVM), потому что они были бы доступны, не выглядит для меня хорошим аргументом. Например, я не вижу веских причин для запуска Python или Erlang на такой платформе. История не говори всего этого.
Klaim
1
И даже PHP никогда не сможет делать то, что он делает через JVM или .Net. @Dean Harding> Я не думаю, что IronPython или Jython действительно что-то доказали.
Klaim
1
Извините, я не понял, что я имел в виду, что у него не было бы «успеха» (PHP или Python), потому что работа над JVM или .Net подразумевает много вещей, которые раздражали бы многих разработчиков, делая их более нишевой язык, чем они есть в настоящее время. С технической стороны, платформа (.Net или JVM) была бы проблемой, потому что она влияет на то, как вы строите язык. Заявление с машиной - это способ сделать именно тот язык, который вы хотите. Итак, с доступной JVM или без нее, я вижу 0 веских причин для создания поверх .Net и JVM. Помимо быстрой реализации.
Klaim
2
Небольшое исправление: Java старше PHP. Но PHP начинался как CGI-программа, позже стал httpd-модулем Apache, и как таковой он стал большим. Обе вещи (модуль cgi и httpd) не работают хорошо для Java. Так что все не так просто, JVM - это не платформа для всего. ;-)
Йоханнес
6

Код C статически компилируется в собственный код (машинный код).

Scala статически компилируется в байт-код Java, а затем, при необходимости, динамически компилируется в оптимизированный нативный код. Процесс:

Scala-код --- статически скомпилированный в ---> байт-код JVM --- динамически скомпилированный JVM-Hotspot-to ---> нативный код

Общие параметры для сборки / работы на любом языке:

  • а) интерпретировать исходный код напрямую через механизм интерпретатора времени выполнения
  • б) статически компилировать код в нативный код (возможно, через промежуточные этапы, например, source -> C -> native)
  • c) статически компилировать исходный код в промежуточный код более низкого уровня и интерпретировать его во время выполнения
  • d) статически компилировать исходный код в промежуточный код более низкого уровня, затем использовать первоначальную интерпретацию, а затем методы динамической компиляции и оптимизации для преобразования в собственный код. Код интерпретируется до тех пор, пока не будут найдены типичные пути выполнения и узкие места, затем код компилируется для наиболее быстрого выполнения в типичных условиях. Он перекомпилируется / переустанавливается, когда условия выполнения изменяются настолько, чтобы это

Ваш вопрос: «Почему Java использует (d) с JVM, а не (b) с промежуточным кодом C?»

Ответ:

Во-первых, обратите внимание, что Scala оченьязык более высокого уровня, чем C, предоставляя мощь программирования, простоту программирования и лаконичность. Это примерно на «1 уровень выше», чем в Java, благодаря функциям первого класса и высшего порядка, неявным функциям, функциям в качестве объектов, замыканиям и каррированию, поддержке компиляции хвостовой рекурсии в быстрые циклы, сохраняющие стеки, всему как объекты, всем операторам как методам которые могут быть (пере) определены в библиотеках, классах дел и редукции (сопоставление с образцом), неявном выводе типов, более сильном полиморфизме за счет расширенных мульти-наследуемых признаков и расширенных обобщенных типов, встроенного синтаксиса для пар и кортежей и минусов (списков и деревьев) ) и карты, поддержка неизменяемых структур данных, поддержка мощных «реактивных» параллельных и параллельных вычислений с копированием и передачей сообщений между участниками, расширенная поддержка произвольных доменных DSL, сценариев и REPL. Java примерно на «1 уровень выше», чем C, благодаря объектной ориентации, управлению указателями и сборке мусора, поддержке строк, поддержке многопоточности и управлению параллелизмом, а также стандартным API-библиотекам.

  1. Производительность: для языка высокого уровня (d) дает более высокую производительность, чем (a) - (c).
    Непосредственно написанный и оптимизированный вручную C-код работает быстро. Однако языки высокого уровня, статически скомпилированные в C, относительно медленны. Дизайнеры Java хорошо это знали. Их нынешний дизайн «Hotspot» повышает производительность на порядок. На одном ядре код Java HotSpot в среднем «на 50% быстрее», чем оптимизированный человеком C (в лучшем случае «120% быстрее», в худшем случае «30% быстрее»). Но, конечно, это сравнивает яблоки с апельсинами - низкоуровневый код v высокоуровневый код. И это было бы многохуже, если оптимизация Hotspot не использовалась. Для подтверждения просто отключите компиляцию точки доступа через аргументы JVM! Или рассмотрите производительность java 1 & 2, когда точка доступа не существовала или была незрелой. Или попробуйте скомпилировать другой язык через C - например, perlcc. Таким образом, вышесказанное является отличным результатом для мощного и продуктивного языка. С дальнейшим развитием возможно (или даже вероятно), что JVM может скоро опередить C-код, написанный вручную. Scala на 70-80% медленнее, чем Java в среднем. Но scala сильно масштабируется по нескольким ядрам (дальнейшие улучшения будут продолжаться), тогда как java делает частично, а C - нет. Производительность Single Core для таких языков высокого уровня оценивается:

    интерпретированный <статически скомпилированный <динамически скомпилированный

    Многоядерная производительность / масштабируемость оценивается:

    интерпретируемый динамический код <статически скомпилированный императивный код <статически скомпилированный функциональный / декларативный код <динамически скомпилированный функциональный / декларативный код

    Это ставит scala на первое место, потому что скорость процессора достигла своего предела, и теперь количество ядер увеличивается по закону Мура. Scala работает очень быстро на многоядерных процессорах и в будущем может стать в несколько раз быстрее, чем C или Java. Статическая компиляция в C - явно не самый быстрый вариант.

  2. Функциональная совместимость: языки на широко поддерживаемой ВМ имеют лучшую совместимость с языками, чем «изолированные» языки, Scala «автоматически играет» с Java-классами, интерфейсами и объектами, просто импортируя их и используя их, как если бы они были классами, чертами и объектами scala Подобное возможно с другими языками JVM, такими как Groovy, Clojure, JRuby и JPython - с простотой взаимодействия, зависящей от того, насколько чисто каждый язык был создан для компиляции в понятные и используемые классы / интерфейсы / объекты среды выполнения Java. Это очень много значит «бесплатно» (как в «близко к»). Scala взаимодействует с C через JNA, преемника JNI, что требует определенных усилий, но со временем инструменты были довольно хорошо отлажены. JNA может фактически взаимодействовать с скомпилированным нативным кодом из любого произвольного языка - но вы должны знать точную структуру скомпилированных типов данных и функций. Если не,

  3. Портативность: JVM работает на десятках платформ / версий операционных систем «из коробки». Scala автоматически переносится на них. Заметное исключение - iOS (iPad / iPhone / iPod) - блокируется «коммерчески», а не «технически» Apple. Этого нельзя было ожидать 12 лет назад, во время первоначального проектирования JVM. JVM отлично работает на десятках других серверов, настольных ПК, мобильных и встроенных устройствах, включая те, которые не поддерживают C - включая Android с Google Dalvik VM (50% + новых проданных телефонов). Конечно, код C работает на множестве платформ, поэтому может быть оценен как «там, где возможно, так и за пределами» Java (в частности, C является подмножеством Objective-C). Но C придет за счет (1), (2) и (3). Конечно, уровень представления HTML5 / javascript / webkit (или target-C) на iOS может взаимодействовать с удаленным приложением scala - так что разработчики должны очень сильно это делать. Конечно, они будут менее продуктивными.

  4. Инструменты и библиотеки . Очевидно, что существуют тысячи коммерческих и открытых библиотек и инструментов Java, которые могут использовать / использовать Scala - больше, чем для C.

  5. Безопасность: - запуск на управляемом сервере приложений или в среде JVM обеспечивает более эффективную поддержку политик и ограничений безопасности, которые могут быть очень полезны в корпоративной среде.

Глен Бест
источник
4

JVM / CLR

JVM (и CLR) предоставляют уникальные преимущества с точки зрения оптимизации и переносимости кода.

Насколько я знаю, поддерживается только текущая версия Scala для JVM, а для версии .NET - нет.

Джош К
источник
3

Похоже, вы смешиваете две несвязанные вещи.

Во-первых, какой язык программирования используется авторами Scala для реализации Scala?

На что ответ, сама Скала. И на самом деле это единственный приемлемый ответ, потому что, если вы изобрели этот новый язык, но не используете его сами для его реализации - для чего он нужен?

Во-вторых, какова целевая платформа для запуска программ, написанных на Scala?

Здесь выбор становится более интересным, но пока единственной целью, которая работает на 100%, является JVM. Поддержка .NET все еще находится в стадии разработки. Кроме того, некоторые люди работают над тем, чтобы заставить Scala компилировать в javacsript. Теоретически, ничто не мешает кому-то добавлять дополнительные «бэкэнды» для компиляции в C, C ++, LLVM, нативный код или что-то еще.

Почему JVM была выбрана в качестве основной платформы? Я думаю, потому что

  • все хотят сборку мусора
  • большое количество готовых к использованию хороших библиотек
  • большое количество программистов, которым надоела Java, готовы перейти к чему-то новому, но остаются в рамках ограничений JVM (никто не хочет переносить свой существующий код на другую платформу)
артем
источник
Я не понимаю, почему сборщик мусора не может быть реализован с помощью C или C ++? Я не вижу в этом веской причины. Python сделал это. Руби сделали это. Черт, даже Эрланг сделал это. Кто знает, что Scala может в итоге получить лучший сборщик мусора, если он написан на C или C ++?
Джошуа Партоги
1
Я имел в виду «настоящую» сборку мусора. Я не думаю , что сбор мусора , который вызывает такие вопросы , как этот является достаточно хорошим. Черт возьми, даже JVM недостаточно хороша, иначе такие люди, как AzulSystems, не смогли бы зарабатывать на жизнь, помогая другим людям преодолевать недостатки JVM.
Артем
Также библиотеки. Действительно трудно использовать библиотеки, написанные для явного управления памятью на языке с сборкой мусора. Одним из признаков является своеобразное стремление людей, живущих в Яве, иметь все в «чистой Яве».
Артем
0

Прежде всего - я думаю, вы действительно хотели спросить, почему Scala не является компилируемым языком в строгой манере. Я скажу тебе, я не знаю. Но я также скажу вам, что нет причин отдавать предпочтение JVM над нативным кодом.

Зачем? Причина проста: любая технология виртуализации требует много памяти, приводит к ненужным накладным расходам и другому уровню косвенности. Это не вопрос их реализации, это вопрос логики, лежащей в основе концепции виртуализации. Независимо от того, что вы делаете, вы всегда будете в конечном итоге с плохими характеристиками. Особенно JVM жаждет памяти. Он больше не такой медленный, потому что у него есть собственный компилятор времени выполнения, работающий за спиной, но все же - он должен запустить процесс компилятора, чтобы иметь возможность обнаружить наиболее перегруженные части кода и превратить их в двоичный код.

Сказал, что - единственная причина, по которой я думаю, что создание Scala на основе JVM, вероятно, была популярность языка. Я также предполагаю, что за этим решением стояла некоторая лень, потому что реализовать язык поверх JVM проще, чем выяснить, как все должно выглядеть в собранном виде для работы кроссплатформенно - и даже использование существующих бэкэндов C требует гораздо больше работы из-за того, что что вещи не так хорошо стандартизированы, как с JVM.

Это причина, о которой я могу думать, но имейте в виду, что могут быть и другие причины - например, выдача лицензий и связанная с этим политика (это грязные вещи, в которые я никогда не буду ввязываться).

luke1985
источник
-2

Не ясно, что иметь возможность для лучшей настройки было бы хорошим компромиссом. JVM могут выполнять оптимизацию во время выполнения, и это обычно, по крайней мере, достаточно хорошо, если не превосходит того, что обычно происходит со статической компиляцией. (Очевидно, что в принципе для конкретного приложения и рабочей нагрузки должна быть возможность превзойти JIT со статической оптимизацией, но практически у вас не всегда есть точная рабочая нагрузка или даже целое приложение.)

Брюс Стивенс
источник
это больше похоже на комментарий, см. Как ответить
gnat