LINUX.ORG.RU

Поступило предложение добавить поддержку динамических языков в OpenJVM


0

0

Джон Роуз (Sun Microsystems), предложил "Многоязыковую Виртуальную Машину" (MLWM), как часть проекта OpenJDK. Такая машина, не теряя совместимости с существующей JVM, добавит поддержку следующих функций:
* Tail Recursion (так любимую анонимусами на лоре :)
* Continuations
* Closures
* Tulpes
* Value-Oriented Types
* И многое другое

>>> Подробности

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

Extremal
()

Раньше на лоре жабу ненавидели за отсутствие хвостовой рекурсии. Теперь будут ненавидеть за наличие. Технологии изменчивы --- лор вечен.

ugoday ★★★★★
()
Ответ на: комментарий от Absurd

>Есть мнение что каждый класс, включая анонимный класс который при компиляции становится явным и приобретает имя вида EmbracingClass$1, EmbracingClass$2 ... EmbracingClass$N, отжирает 3 кб на метаинформацию в jvm. В результате на каждый хандлер события в swing требуется 3 кб. Или это FUD?

Так точно. Кто заставляет делать каждый хэндлер в отдельном классе?

anonymous
()
Ответ на: комментарий от r

Сигнатура:

public Index( String path, String name, String query, String keyFunction, String matchFunction, AtomicFileManager fileManager, Marshaller marshaller )

Вызов:

Index<CollectionBean> x = new Index<CollectionBean>( "test", "criteria", "bean, criteria | bean.criteria.contains(criteria)", "bean | bean.criteria", "criteria | criteria", fileManager, marshaller );

Кто из защищавших анонимные классы рискнет переписать c оными?

r ★★★★★
()
Ответ на: комментарий от Fice

>Возможно, неудачная архитектура. У меня таких проблем не возникало.

Я думаю у тебя таких архитектур не возникало. Они знаешь ли в голову с анонимными классами не приходят потому что в случае анонимных классов от маразматического вида до невозможности реализации имеют вид. Вон сверху код - перепиши.

r ★★★★★
()
Ответ на: комментарий от r

> ППКС. Тупизма какого-то напридумывали, хрен разберешься, нефига не понятно. Нет бы взяли и писали что нибудь полезное.

ну почитай http://blog.morrisjohns.com/javascript_closures_for_dummies и http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons

может поймешь..

anonymous
()
Ответ на: комментарий от Extremal

>Java - полноценный ООП язык и анонимные классы, это нормальное решение. А замыкания это из оперы функциональных языков.

РАсскажи это смолтолку где замыкание основной компонент языка, без него он не реализуем в принципе. Уж не говоря о том что объектность и функциональность суть перпендикулярные явления. В функциональных языках тоже есть ОО.

r ★★★★★
()
Ответ на: комментарий от anonymous

задолбали тупые пхпшники.

ты пишешь на жаве? нет? тогда тебе просто не понять необходимость и актуальных этих изменения в сабже.

кому не нравится ява - есть полно "хороших тру-языков" типа Си, асма, пхп. И предложение работы на них тоже есть. вперед. не мешайте людям заниматься своим делом.

anonymous
()
Ответ на: комментарий от anonymous

>может поймешь..

Стеба неаценил?:))) Ну и анонимусы пошли...

r ★★★★★
()
Ответ на: комментарий от Extremal

>Я тоже думаю что замыкуния - хрень полная. Java - полноценный ООП язык и анонимные классы, это нормальное решение.

Это не отменяет желание получить сахар и поддержку его на уровне вм.

Громоздкоть раздражает и мешает восприятию логики.

anonymous
()

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

anonymousI
()
Ответ на: комментарий от Extremal

> Я тоже думаю что замыкуния - хрень полная.

А я думаю, что "херь полная" - это тот, кто говорит о том, в чём ни хрена не разбирается.

> Java - полноценный ООП язык и анонимные классы, это нормальное решение.

А язык ни кто трогать и не предлагал. Хотят "расширить" vm, чтобы другим языкам не приходилось извращаться и/или тормозить.

> А замыкания это из оперы функциональных языков.

Про ортогональность тебе уже сказали.

> Я даже статическими импортами не пользуюсь, потому что они меняют восприятие кода и думаешь что вызов статического метода из этого класса или родительского.

С проблемами личного восприятия - это к психиатрам.

yyk ★★★★★
()
Ответ на: комментарий от anonymous

>>Есть мнение что каждый класс, включая анонимный класс который при компиляции становится явным и приобретает имя вида EmbracingClass$1, EmbracingClass$2 ... EmbracingClass$N, отжирает 3 кб на метаинформацию в jvm. В результате на каждый хандлер события в swing требуется 3 кб. Или это FUD?

>Так точно. Кто заставляет делать каждый хэндлер в отдельном классе?

А что, делать говно-switch как на чистом С в чистом Win32 API ?! Java это ООП язык или нет?

Absurd ★★★
()
Ответ на: комментарий от anonymous

Вот тож занятно что:

"C#, Javascript,Ruby, Scala, and Smalltalk (to name just a few) have direct language support for function types and inline function-valued expression, called closures.A proposal for closures is working its way through the C++ standards committees as well." (C) Java Closures Proposal.

К стати один из С++ пропосалов как близнец с жабским:

http://blogs.sun.com/ahe/resource/closures.pdf http://val.samko.info/lambda/lambda_proposal.pdf

r ★★★★★
()
Ответ на: комментарий от anonymousI

>Ну вот они и признались, что жабка - это вчерашний день.

База хорошего Enterprise кода для Java в общем-то всех устраивает. Не устраивает SWING из-за того что там надо искать какие-то компромиссы между одинаково плохими switch, Anonymous classes & java.lang.reflect.Method.invoke().

Absurd ★★★
()

>Джон Роуз (Sun Microsystems), предложил "Многоязыковую Виртуальную Машину" (MLWM), как часть проекта OpenJDK. Такая машина, не теряя совместимости с существующей JVM, добавит поддержку следующих функций:

Уже страшно. У SUN в последнее время очень плохо с добавлением новых функций в JVM. Те же generic'и были сделаны через Ж., по сравнению даже с Microsoft.

Когда я сейчас смотрю на очередные мегапропозалы по поводу "superpackages" (аналог сборок) и замыканий - плохо становится.

anonymous
()

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

gaa ★★
()
Ответ на: комментарий от gaa

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

Ты рискуешь проснуться одновременно с Ктулху :-D

anonymous
()
Ответ на: комментарий от anonymous

>Уже страшно. У SUN в последнее время очень плохо с добавлением новых функций в JVM.

Кому страшно, могут использовать проверенную временем 1.4.2. Нам страшно и мы используем эту версию. :)

vtVitus ★★★★★
()
Ответ на: комментарий от vtVitus

>>Уже страшно. У SUN в последнее время очень плохо с добавлением новых функций в JVM.

>Кому страшно, могут использовать проверенную временем 1.4.2. Нам страшно и мы используем эту версию. :)

Ну не скажи - народу аннотации понравились. Да и над перформансом они работают.

Absurd ★★★
()
Ответ на: комментарий от vtVitus

>Кому страшно, могут использовать проверенную временем 1.4.2. Нам страшно и мы используем эту версию. :)

Да ну, сейчас ее все меньше проектов нормально поддерживает. Да и generic'и с аннотациями все же лучше, чем ничего.

anonymous
()
Ответ на: комментарий от anonymous

> У SUN в последнее время очень плохо с добавлением новых функций в JVM. Те же generic'и были сделаны через Ж., по сравнению даже с Microsoft.

А что именно там через Ж, можно чуточку подробнее?

Bohtvaroh ★★★★
()
Ответ на: комментарий от gaa

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

Шаблоны C++ являются Turing-complete языком http://www.codeproject.com/cpp/crc_meta.asp

Можно сделать так что все вычисления производятся во время компиляции, а развернутый код будет иметь вид main(){ printf(result) }. Гентушнеги будут довольны.

Absurd ★★★
()
Ответ на: комментарий от Absurd

>Можно сделать так что все вычисления производятся во время компиляции, а развернутый код будет иметь вид main(){ printf(result) }. Гентушнеги будут довольны.

Это можно в любой программе, которая не взаимодействует с внешним миром. Причем здесь шаблоны С++?

anonymous
()
Ответ на: комментарий от Bohtvaroh

>> У SUN в последнее время очень плохо с добавлением новых функций в JVM. Те же generic'и были сделаны через Ж., по сравнению даже с Microsoft.
>А что именно там через Ж, можно чуточку подробнее?

В .NET generic'и при инстанцировании создают реально новые типы. То есть, ArrayList<Integer> и ArrayList<String> будут разными типами. Причем, можно делать генерики от value-типов, что позволяет без оверхеда на боксинг сделать нормальные контейнеры примитивных типов.

В Java generic'и просто работают как "автоматический вставлятель кастов". То есть, ArrayList<Integer> и ArrayList<String> в байт-коде будут реально одним и тем же ArrayList, хранящим Object'ы.

anonymous
()
Ответ на: комментарий от anonymous

>>Можно сделать так что все вычисления производятся во время компиляции, а развернутый код будет иметь вид main(){ printf(result) }. Гентушнеги будут довольны.

>Это можно в любой программе, которая не взаимодействует с внешним миром. Причем здесь шаблоны С++?

Это треп

Absurd ★★★
()
Ответ на: комментарий от r

> Index<CollectionBean> x = new Index<CollectionBean>( "test", "criteria", "bean, criteria | bean.criteria.contains(criteria)", "bean | bean.criteria", "criteria | criteria", fileManager, marshaller );

И что мешает создать три интерфейса Query, Key и Match и передавать в конструктор "new Query() {...}"? Немного больше кода, зато логично, понятно и объектно-ориентировано. И где тут будет "туча типов, и анонимных реализаций с жуткий оверхедом в синтаксисе"? Каждое замыкание - это тоже тип, ничем не лучше анонимного класса.

Ну не нужны в Java эти лишние сущности.

Fice ★★
()
Ответ на: комментарий от anonymous

>и нах этот синтаксический сахар не сдался

Во всем виновата МС. Она просрала всем мозги по-поводу Common Language Runtime, что по-сути является не VM, а ОС поверх другой ОС (для прикрывания дыр и архитектурных ошибок в первой). А теперь красноглазые кричат на Яву, почему она такая однобокая. Да Sun и не собиралась заниматься деструктивной и империалистической политикой аля мелкософт, не собиралась и умышленно закручивать винтики молотком во благо пользователя и стандартизации. А теперь и приходиться поддакивать всяким придуркам, ибо мозг их уже зактулхуирован.

xTERM ★★
()
Ответ на: комментарий от anonymous

> Уже страшно. У SUN в последнее время очень плохо с добавлением новых функций в JVM. Те же generic'и были сделаны через Ж., по сравнению даже с Microsoft.

Как раз наоборот, реализация generics в Java такова, что не потребовала изменения (усложнения) JVM, и это хорошо.

Fice ★★
()
Ответ на: комментарий от anonymous

> В Java generic'и просто работают как "автоматический вставлятель кастов". То есть, ArrayList<Integer> и ArrayList<String> в байт-коде будут реально одним и тем же ArrayList, хранящим Object'ы.

И почему это плохо? Необходимость преобразования встроенных типов к объектам (boxing) никак с этим не связана.

Fice ★★
()
Ответ на: комментарий от Fice

>И что мешает создать три интерфейса Query, Key и Match и передавать в конструктор "new Query() {...}"? Немного больше кода,

Напиши.

> зато логично,

Потрясающе.

> понятно

Спросим у общественности.

> и объектно-ориентировано.

Ахренеть! ОО тут минус - реально передается кусок кода, алгоритм, функция. Необходимость заворачивать это в объект - маразм.

>Каждое замыкание - это тоже тип, ничем не лучше анонимного класса.

Это кусок кода как first-class object.

r ★★★★★
()
Ответ на: комментарий от xTERM

>А теперь и приходиться поддакивать всяким придуркам, ибо мозг их уже зактулхуирован.

Если не поддакивать всяким придуркам с джава отправится насвалку. ТАм сейчас пылиться VB, Delphi и прочая ежу понятная бойда без лишних сущьностей.

r ★★★★★
()
Ответ на: комментарий от Fice

>Как раз наоборот, реализация generics в Java такова, что не потребовала изменения (усложнения) JVM, и это хорошо.

Ты хоть видел КАК оно реализовано внутри? Оно ПОТРЕБАВАЛО изменений в VM, в куче мелочей.

И что хорошего в том, что делаются полумеры - я не понимаю. Generic'и в Java не добавили реальной типобезопасности (их можно обойти) - так что VM все так же должна проверять типы.

В то время, как в .NET generic'и реально принесли УВЕЛИЧЕНИЕ ПРОИЗВОДИТЕЛЬНОСТИ из-за избавления от ненужных кастов.

anonymous
()
Ответ на: комментарий от Fice

>Как раз наоборот, реализация generics в Java такова, что не потребовала изменения (усложнения) JVM, и это хорошо.

Ахренеть. То что там полно тупых дурацких ограничений - это хорошо?

То что нельзя написать:

class A { void method(List<String> strings){...}

void method(List<Integer> ints){...} }

это хорошо?

То что не работает:

class C<T> { T t = new T(); T[] array = new T[10]; }

это хорошо?

То что нельзя написать T.class или a instanceof T или T.gedDeclaredMethods() это хорошо?

Ахренеть.

Причем некоторые хрени беспроблем разруливаются даже без моификации VM: generic array creation например - почему нихрена не работает new T[10] если это тупо обходится T[] create(T.... array) {return array}? Хрень с ambiguous method call обходится даже синтетическим класс лоадером с соглашением об именовании производных типов (Я пару лет назад постил реализацию в ru.java).

ДА и что мешает изменить VM при условии сохранения совместимости? Байткод-то все равно поменялся необратимо в классах 49.0 (1.5).

r ★★★★★
()
Ответ на: комментарий от anonymous

>В то время, как в .NET generic'и реально принесли УВЕЛИЧЕНИЕ ПРОИЗВОДИТЕЛЬНОСТИ из-за избавления от ненужных кастов.

А он никогда не декомпилировал то что там нагенерилось и потому не знает какой там рак.

r ★★★★★
()
Ответ на: комментарий от Fice

>> В Java generic'и просто работают как "автоматический вставлятель кастов". То есть, ArrayList<Integer> и ArrayList<String> в байт-коде будут реально одним и тем же ArrayList, хранящим Object'ы.
>И почему это плохо? Необходимость преобразования встроенных типов к объектам (boxing) никак с этим не связана.

В .NET _реально_ может создаваться тип, который хранит не забоксированые примитивы, а реальные value-типы. Это дает реальный выигрыш в скорости и памяти.

В Java это невозможно - все обобщенные контейнеры вынуждены храить Object'ы, что требует обязательного боксирования. Причем, защиту generic'ов очень просто пробить.

Вот это скомпилируется без ошибок:
========
ArrayList<Integer> test=new ArrayList<Integer>();
ArrayList test2=test;

ArrayList<Float> test3=(ArrayList<Float>)test2;
Float first=test3.get(0); //Упс... В runtime получим ClassCastException
========

anonymous
()
Ответ на: комментарий от anonymous

> В Java generic'и просто работают как "автоматический вставлятель кастов". То есть, ArrayList<Integer> и ArrayList<String> в байт-коде будут реально одним и тем же ArrayList, хранящим Object'ы.

Ну так и отлично, без велосипедостроения обошлись.

Bohtvaroh ★★★★
()
Ответ на: комментарий от anonymous

>В Java это невозможно - все обобщенные контейнеры вынуждены храить Object'ы, что требует обязательного боксирования. Причем, защиту generic'ов очень просто пробить.

Вообще-то IDEA или Eclipse будут ругать за неиспользование type-safety при обращении с коллекциями, подсвечивать желтым такие места, и выводить их глобально в списке "проблем". По поводу боксинга/анбоксинга - трах с массивами октетов в Джаве нормально реализуется, ведь есть например нормально работающий SSL и Zip, и thin драйвера к Ораклу/MSSQL на чистой Джаве.

Absurd ★★★
()
Ответ на: комментарий от anonymous

>Вот это скомпилируется без ошибок:
>========
>ArrayList<Integer> test=new ArrayList<Integer>();
>ArrayList test2=test;

>ArrayList<Float> test3=(ArrayList<Float>)test2;
>Float first=test3.get(0); //Упс... В runtime получим ClassCastException
>========

Ты тоже самое можешь сделать и на C++ и на .Net. Кастинг для этого и предназначен.

А autoboxing это не такой уж много ресурсов требует.

Кстати, кто может объяснить - почему JDBC драйверы быстрее, чем ODBC (под юниксами, по крайней мере)?

dimag
() автор топика
Ответ на: комментарий от anonymous

Все описанные здесь проблемы с generics - причина того, что их нет в runtime. Их там и не должно быть. Конструкции вроде "new T()" потребовали бы вносить в тип ещё и требуемую сигнатуру конструктора.

Отсутсвие generics во время выполнения не создает никакой опасности: приведение типов все-равно проверяется и, если что не так, выбрасывается ClassCastException. Были бы generics в runtime, имели бы какой-нибудь GenericError, который работал бы аналогично NoSuchMethodError. Чем это лучше?

Проблемы с boxing'ом не имеют никакого отношения к generics.

Все существующие сейчас в Java средства позволяют достаточно просто и красиво реализовать практически любой шаблон из "Design patterns". Этого не достаточно? При правильном подходе к проектированию (используя те же "Design patterns") необходимости во увсех этих лишних конструкциях не возникает.

Почему люди, не понимающие философию Java, пытаются придумывать какие-то костыли вместо того, чтобы просто использовать C#/.NET/Mono?

Fice ★★
()
Ответ на: комментарий от Fice

>Конструкции вроде "new T()" потребовали бы вносить в тип ещё и требуемую сигнатуру конструктора.

И что? Где проблема? В С# она есть.

>Отсутсвие generics во время выполнения не создает никакой опасности:

Кроме той что нельзя даже пару методов обявить с параметризованными параметрами потому что джава их не различает да?

>Чем это лучше?

1. можно было бы обявлять методы с одинаковым типом и различным параметром.

2. не было бы маразма который генерит компилятор - ты как нить возьми напиши просту параметризованную иерархию а потом декомпилируй ее - увидишь сколько методов нагенерил компилер. вот тебе пример:

Исходник:

abstract class A<T> { abstract T method (T t); }

class B extends A<Integer> { Integer method(Integer i) { return i; } }

Результат декомпиляции:

abstract class A { abstract Object method(Object obj); }

class B extends A { Integer method(Integer integer) { return integer; }

volatile Object method(Object obj) { return method((Integer)obj); } }

Догадайся нафига это надо?

3. Работает интроспекшен в рантайме. Это значит что когда я попытаюсь в рантайме запихнуть какую-то мутотень несоотвествующую типу через какой нить method.invoke или field.set я отгребу исключение именно там а хрен его знает где когда я это достану из Object переменной и пытаюсь всунуть в типизированную переменную, хотя исходники были якобы статически типизированно откомпилированы.

>необходимости во увсех этих лишних конструкциях не возникает.

Уже написал мою строчку анонимными классами?

>Почему люди, не понимающие философию Java

Люди понимают недостатки. А ты видать их не видишь. Может ты и нужды в генериках не видел до 1.5 и в боксинге? Не видел нужды в аннотациях? Ведь там тоже все работало.

r ★★★★★
()
Ответ на: комментарий от r

> Уже написал мою строчку анонимными классами?

Можно так (переопределяем три метода в классе Index, типы выбраны условно):

Index<CollectionBean> x = new Index<CollectionBean>
    ("test", "criteria", fileManager, marshaller) {
    
    protected boolean executeQuery(CollectionBean bean, Criteria criteria) {
        return bean.criteria.contains(criteria);
    }

    protected Object getKey(CollectionBean bean) {
        return bean.criteria;
    }

    protected Criteria match(Criteria criteria) {
        return criteria;
    }
};

По моему, это более читабельный код, чем ваша одна длинная строчка.
Класс Index можно снабдить реализациями этих методов по умолчанию
и переопределять только те из них, которые нужно.

Другой вариант - обявить интерфейсы Query, Key и Matcher и передать
реализации в конструктор Index.
Ещё вариант - объявить один интерфейс с тремя функциями и передать
его в конструктор Index.

Fice ★★
()
Ответ на: комментарий от Fice

> При правильном подходе к проектированию (используя те же "Design patterns")

Если ты хоть что-то понимал в проектировании и знал больше 0.5 парадигмы, то знал бы, что больше половины паттернов из книжки GoF - это обходные пути для задач, у которых есть элегантные решения в ФП, настоящем ООП и т.д., но эти решения из-за различных ограничений C++ не могут не него быть портированы напрямую.

grob ★★★★★
()
Ответ на: комментарий от Fice

>По моему, это более читабельный код

Не вижу анонимных классов (кроме Index). критерий там поле типа стринг. keyfunction и matchfunction может быть сложным и содержать мешок полей - с методами не получится вследствие того что количество параметров там зависит от индекса - это я тебе дал простой индекс. Далее ты не учел тот факт что эти штуки как замыкания вляются first-class objects и например по критерию запроса может быть выбран индекс в котором надо искать - то есть запрос может выступать в качестве ключа. Этот аспект полностью отсутствует в твоем случае - это так не реализуемо в принципе.

вот тебе более сложный пример чтобы ты оценил что таким образом делается:

Collections.select( getStandardRemoteServers(), "server, incoming | !server.satellite && ((incoming && server.incomingTransferAllowed)||(!incoming && server.outgoingTransferAllowed))", incoming );

На самом деле этот запрос - это часть фреймворка коллекций. Вот еще примеры:

Collections.min( Collections.<Server, Long>collect( Collections.reject( servers, "server | server.satellite" ), "server | server.maxJobSize" ), DEFAULT_MAX_JOB_SIZE );

List<P> result = collect( sublist( sort( indices.forQuery( query ).lookup( params ), order( order, Comparators.<String>compareToComparator() ) ), offset, count ), new Closure<String, P>() { public P evaluate( String id ) throws Exception { log.debug( "processing..." + id ); return get( id ); } } );

Последнее Closure я хочу заменить на P(String id) {return get(id)}; -как это предложено в пропосале.

Сравни это с кложурой которую надо делать анонимным класом:

new Closure<String, P>() {

public P evaluate( String id ) throws Exception {

return get( id );

}

}

А так будет:

List<P> result = collect( sublist( sort( indices.forQuery( query ).lookup( params ), order( order, Comparators.<String>compareToComparator() ) ), offset, count ),{return get(id)});

Уж не говоря о том что компаратор тоже будет кложурой в этом случае.

>Другой вариант - обявить интерфейсы Query, Key и Matcher и передать реализации в конструктор Index.

Классно. Вместо того чтобы описать десяток индексов в 10 строк я объявлю 3 интерфейса и сделаю 30 наследников или 30 анонимных реализаций и превращу код в ацкую мешанину букав - если представить что каждый аноним (которых 3 на строчку скушает 3 строки (реально больше)) но вместо кода в 10 строк имеем код в 90 строк + обявление 3х новых интерфейсов.

Нука обясника мне ради чего я на порядок увеличил объем кода? Я что-то запамятовал.

r ★★★★★
()
Ответ на: комментарий от grob

>то больше половины паттернов из книжки GoF - это обходные пути для задач, у которых есть элегантные решения в ФП,

+мильен

r ★★★★★
()
Ответ на: комментарий от Fice

> Отсутсвие generics во время выполнения не создает никакой опасности: приведение типов все-равно проверяется и, если что не так, выбрасывается ClassCastException. Были бы generics в runtime, имели бы какой-нибудь GenericError, который работал бы аналогично NoSuchMethodError. Чем это лучше?

Были бы generic'и в runtime'е - ClassCastException выдавался бы при подобных операторах: "ArrayList<Float> test3=(ArrayList<Float>)test", а не при использовании методов контейнера.

Проблемы с боксингом ИМЕЮТ отношение к generic'ам. Напиши мне обобщенный контейнер, в котором можно хранить все примитивы без боксинга. Жду.

Про "Design Patterns" вообще лучше не заикаться - это детская книжка про то как надо писать. Если язык с ООП не позволяет их делать - то такой язык сразу отправляется на свалку. Тут нечем гордится.

А "философия Java" привела к тому, что Java в конце 90-х слила на desktop'е, где пользователям было абсолютно плевать на философию (а вот скорость и удобство очень даже приветствовались).

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.