Нубский вопрос по java: массив пар/туплов?
поставь скалу. Используй её просто как яву на стероидах и забей на функциональные штуки.
оу
Задача не под андроид писать
задача - ванильную джаву освоить.
Можно и ванильную яву освоить. Только не стоит жаловаться на весьма пустозвонные конструкции.
Или ты про то, что стандартной библиотеке нет ни pair ни tuple?
Их много раз просили добавить и стандартный аргумент против был "заведите сами конкретный класс под вашу пару или что там у вас".
Да, в Android пара есть .
В том, что нет встроенного KeyValuePair? Ну создай себе один раз и используй его везде... Самые ленивые джава-разработчики знают про AbstractMap.Entry, но оно достаточно странно в коде выглядит для непривычного взгляда.
В остальном согласен. Зачем ява?
как это сделать в джаве не очень монструозно?В шарпе это вообще короче записывается, если тебе порядок элементов в массиве не важен:
http://msdn.microsoft.com/en-us/library/bb531208.aspx
new Dictionary<string, int>{
{"тонна", 1000000},
{"центнер", 100000},
{"килограмм", 1000},
{"грамм",1},
}.ToArray
в противном случае я бы использовал Map
private static Pair<String, Integer> BaseTable2[] =
{
new Pair<String, Integer>( "т", 1000000
new Pair<String, Integer>( "ц", 100000
new Pair<String, Integer>( "кг", 1000
new Pair<String, Integer>( "г", 1 )
}
;
error: generic array creation
private static Pair<String, Integer> BaseTable2[] =
new Pair[] {
new Pair<String, Integer>( "т", 1000000
new Pair<String, Integer>( "ц", 100000
new Pair<String, Integer>( "кг", 1000
new Pair<String, Integer>( "г", 1 )
}
;
да, в яве generics не такие, как в .net
ну это же не type-safe!
Я вот вообще всегда добавляю google guava в classpath, когда на яве пишу и твоя задача для меня тогда решается так:
import com.google.common.collect.ImmutableMap;
...
private static final ImmutableMap<String,Integer> BaseTable2 = ImmutableMap.of(
"т", 1000000,
"ц", 100000,
"кг", 1000,
"г", 1);
ImmutableMap гарантирует порядок итерации.
Кстати, если уж всё равно информация о типах исчезает - можешь делать список таплов в лиспостиле.
порядок важен. в противном случае я бы использовал MapЕще LinkedHashMap есть
В чем монструозность то?питонисты с
kva = {}; kva['тонна']=1000000
недоумевают
Это через касты что ли O_o? Нет кода под рукой. Казалось бы, билдером такое куда элегантнее бы смотрелось, да еще и со строгой типизацией
Там и билдер есть, для общего случая. Просто они ещё добавили методов of для n=0-5.
OMG. Напоминает один апачевский классик для создания массивов. И конечно, гугловские же, кажется, тюплы Pair, Triple, ..., Decade. Такие конструкции печалят
Почему печалят? Вроде понятно и коротко.
Потому что выразительность языка - очень важный параметр. И это применительно не только к жабе. Скала, конечно, норм, но и она не серебряная пуля. Все это позволяют делать утиные языки, но они же утиные...
Последнее неспроста непопулярно в мире массовой разработки.
В данном конкретном примере это все из категории "записать в 5 букв".
Код либы да, выглядит печально, но, учитывая, что ты этот код не суппортишь, а только юзаешь, а гугл его суппортит через кодогенерацию (афаик, не уверен то в принципе плевать.
Скала для меня по той же причине в категории "записать в 5 букв". Хотя, возможно, конечно, я про скалу не знаю что-то такое, что выводит ее из этой категории.
Из примеров, что для меня выходит за категорию "5 букв" - coroutines/fibers. Кто в теме знают, что без поддержки continuations на уровне языка сделать это можно только через жопу. В официальной джаве этой поддержки, к сожалению, до сих пор нету.
Недавно, правда, это таки запихали через javaagent. У меня, правда, руки не дошли попробовать, но все говорит за то, что continuations там честные (реализованы не через отдельные треды).
Во-первых, есть duck typing.
Во-вторых, есть типизация через implicit evidence. Это позволяет делать типоклассы в стиле хаскеля.
В-третьих, есть система акторов, которые по сути отдельная библиотека, а не часть языка.
В-четвёртых, скала умеет ограниченно преодолевать проклятие type erasure - если тип известен на этапе компиляции, компилятор может вставить хинт как дополнительный аргумент функции, к которому изнутри можно обращаться, чтобы получить информацию о типе.
Но всё это не мешает использовать скалу как просто яву с более удобны и продуманным синтаксисом.
Кто в теме знают, что без поддержки continuations на уровне языка сделать это можно только через жопу.Кстати, я сделал yield через генерацию байткода. Это было не так сложно. Но есть проблема, которую я не решил - это автоматическое освобождение итератора, в результате чего нельзя сделать корректный break из foreach. И ещё в конце метода приходится делать фиктивный return.
Я бы различал выразительность в смысле полноты по тьюрингу и выразительность в смысле "а я могу записать это в 5 букв".Я когда пописал на языке, где можно записать все в пять букв, то возвращался потом в язык с десятью буквами с болью и слезами.
Последнее неспроста непопулярно в мире массовой разработки.
Я когда пописал на языке, где можно записать все в пять букв, то возвращался потом в язык с десятью буквами с болью и слезами.Потому что ты либо никогда этого потом не читал, либо весь "проект" занимал один файл; либо два файла, и ты работал один. Чем код плотнее, тем его тяжелее читать, анализировать и поддерживать.
Это все, вероятно, получило бы большее распространение, если бы поддержка в иде была лучше. К сожалению, так как вся система сложнее, то и поддержку эту реализовать сложнее.
Так что пока потенциальный выигрыш от клевой тайп системы для меня не перевешивает минусы в поддержке иде. Код на скале может быть весело писать, но совсем невесело читать.
Акка - это вещь в себе и слабый аргумент в пользу скалы.
Про нее я уже как-то писал, что много людей, на мой взгляд, не понимают как это правильно использовать и рождают сложности на пустом месте, когда *все* объекты становятся акторами, и любой чих вырождается в посылку мессаги даже если вам нужно обычное синхронное однопоточное взаимодействие.
Если вы пишете под акку на скале, то написание такого неэффективного кода становится очень легким по синтаксису. Именно поэтому я считаю, что акку первоначально лучше использовать на чистой джаве.
не правда. Есть некоторый предел удобства, дальше которого раздувать синтаксис делает лишь хуже. Вот я часто встречал мнение, что json гораздо удобнее читается чем xml как раз потому, что более лаконичный.
Кстати, я сделал yield через генерацию байткода. Это было не так сложно.Для общего случая? В паблике на это можно посмотреть?
Это тебе не scala <-> java.
А какая поддержка в IDE тебе нужна? Все IDE (может кроме идеи, она как-то не тормозит в отличие от остальных) используют presentation compiler от самой скалы, который делает за них всю грязную работу по обработке синтаксиса.
Всё, что ты сказал про Акку, так же верно и для эрланга, даже в большей степени. И ничего, пишет народ на нём, не страдает. Правда при возвращении на си начинается ломка "как это сделать без акторов?".
ну значит высказывание про размер не верно в общем случае. Конкретно для пары java-scala, вполне возможно. Но можно провести эксперимент по сравнению кода.
Есть некоторый предел удобства, дальше которого раздувать синтаксис делает лишь хуже. Вот я часто встречал мнение, что json гораздо удобнее читается чем xml как раз потому, что более лаконичный.Я не отрицаю наличие золотой середины, но мы уже видели здесь код то ли на B, то ли на D++ Всё-таки dense конструкции тяжелее читать, и чем больше проект, тем хуже от них становится. Спорят с этим обычно те, кто по большей части разрабатывал небольшие проекты; или проекты, которые хорошо разбиваются на небольшие кусочки.
Для общего случая?Для общего или нет не знаю, когда я понял, сколько сил уйдёт на автоматическое освобождение итераторов, я перестал делать проект.
В паблике на это можно посмотреть?
В паблике нет, могу прислать куда-нибудь код. Без освобождения итераторов он всё равно бесполезен. Собственно, внизу то, что он не проглатывает. После foreach на getIterator2 поле b == false.
@Yields
public class Nested {
@Yields
public YieldIterable<Integer> getIterator1 {
try {
yieldReturn(1);
yieldReturn(2);
yieldReturn(3);
yieldReturn(4);
return yieldBreak;
}
finally {
b = true;
}
}
@Yields
public YieldIterable<Integer> getIterator2 {
int k = 0;
for (int i : getIterator1 {
if (k++ > 1) {
break;
}
yieldReturn(i);
}
return yieldBreak;
}
public boolean b;
}
С системой типов никаких сложностей нет - каждая из трёх реализованных в скале известна множеством своих применений в других языках, из которых можно почерпнуть опыт программирования на этих системах типов. Проблема случается только когда они встречаются вместе и когда нужно выбирать одну из них для конкретного use-case, что ещё осложнено двумя доступными способами получения higer-order types.В порядке нарастания градуса: 1 2 3 4 5
Проблема в том, что когда куча народа не умеет нормально использовать джаву, путаясь в ее средствах. Абстракцию от наследования люди научились отличать, но количество людей, которые без гугла могут сказать почему List<Integer> не является подтипом List<Number> исчезающе мало. Еще меньше знают определение слов covariance/contravariance/invariance. И так далее.
Мысль, что мне нужно будет читать код этих людей на скале, меня ужасает.
Всё, что ты сказал про Акку, так же верно и для эрланга, даже в большей степени. И ничего, пишет народ на нём, не страдает. Правда при возвращении на си начинается ломка "как это сделать без акторов?".Проблема не в концепции. Проблема в реализации. Мессага в акке - это синхронизация в executor'е твоего выбора. Даже с моднявыми (и нефигово сложными сами по себе) форкджойн пулами от раза к разу приходится иметь дело с вещами вроде такого.
Что там с имплементацией в ерланге я не знаю.
Итого - на поиграться акку можно, но в серьезный проект мне ее страшно брать.
автоматическое освобождение итераторовА что у тебя за каждым итератором стоит?
А что у тебя за каждым итератором стоит?За реализацией итератора ничего не стоит. Но освобождение вызывает механизм, через который отрабатывают finally. Собственно, из примера явно видно, что finally не отрабатывает.
Про "в 5 букв", я очень согласен с typing is not a bottleneck. В случае джавы это вдвойне так с IntelliJ, чуть меньше с Eclipse. Поэтому маниакальная погоня исключительно за "5 буквами" мне принципиально непонятна. Могу понять только когда с краткостью приходят какие-то новые фичи.
Те решения на кодогенерации, что мне приходят в голову, я бы не назвал простыми, но в них реализация файналли не выглядит таким уж безнадежным делом...
Те решения на кодогенерации, что мне приходят в голову, я бы не назвал простыми, но в них реализация файналли не выглядит таким уж безнадежным делом...Там нужно анализировать все foreach, смотреть на вызовы YieldIterator<T> iterator и при наличии этих вызовов перезаписывать метод, записывая YieldIterator<T>.close в правильное место после таблицы исключений, которую вначале надо аккуратно добавить, ведь она может быть или не быть. Не безнадёжно, но реализацию делать заебёшься.
Могу понять только когда с краткостью приходят какие-то новые фичи.Так переход xml -> json не добавляет новых фич. Он не нужен?
Look atСовершенно не напрягает. Может дело привычки. Вот народ на лисповые скобки западает так, что ненависть на всю жизнь зарабатывают. А на самом деле лисп очень близок к питону, только внешне и отличается. Начнёшь прогать, научишься эти скобочки не замечать.
flatMap [B, That] (f: (A) ⇒ Traversable[B]implicit bf: CanBuildFrom[List[A], B, That]) : That
and tell me that doesn't make you want to run screaming.
Я вот тоже не любил их сильно. А потом заметил структурное сходство и прогать стало легче. Правда от моего кода самих лисперов выворачивает и они бегут к ближайшей урне, потому что я следую стайлинг гиду от явы, а не лиспа.
Так и с выражением на скале. Оно простое и прекрасно подсказывает что будет внутри функции.
Абстракцию от наследования люди научились отличать, но количество людей, которые без гугла могут сказать почему List<Integer> не является подтипом List<Number> исчезающе мало. Еще меньше знают определение слов covariance/contravariance/invariance. И так далее.Потому что это мудреж, бесполезный при написании реальных программ, нужный только чтобы java-архитекторов было чем занять. Я видел как java-архитекторы писали код с адскими дженериками, который компилился javac, но не компилися eclipsec - значит у создателей компиляторов тоже понимания нет как это говно работает. Реально, уму непостижимо - создали в языке 4 разных типа:
List
List<?>
List<Object>
List<? extends Object>
но при этом в метод map.get(key) можно в качестве key передавать значение любого типа - дженерики его не проверяют.
После этого эпичного проеба, человеку который это напридумывал - Одерскому - показалось мало и он стал сочинять скалу.
Мне совершенно непонятно, почему этот человек имеет такую власть над java-программистами и за что он их так мучает? Сочинил дурацкие дженерики - их вставили в язык, сочинил скалу - люди мучают себя скалой.
И переход xml -> json совершен только в мире вокруг джаваскрипта по понятным причинам. И то не везде (с html/xhtml на json почему-то никому не приходит в голову перейти).
Отношения к скала вс джава и краткости записи кода это не имеет.
Вот тебе еще свежачок с баша.
Совершенно не напрягает. Может дело привычки.Дело не в напрягах, а в быстром понимании при чтении. Совсем недавно в разделе обсуждали трактаты по 9 строчкам на Haskell. Да, они тоже кого-то не напрягают. И даже приносят кому-то радость.
Но я лучше буду иметь 100 строк на C++, чем 9 таких строчек, для понимания которых нужно прочитать блог пост, а потом для закрепления и проверки написать ещё один блог пост.
Можно ли этот пост интерпретировать как заявление того, что ты готов завоевать мир ООП языком собственного изготовления без covariance/contravariance?
Но я лучше буду иметь 100 строк на C++, чем 9 таких строчек, для понимания которых нужно прочитать блог пост, а потом для закрепления и проверки написать ещё один блог пост.Я каждый день пишу аналог тех 9 строчек, только не на хаскеле, а на джаваскрипте, для примитивных тупых задач. Например, задача - пользователь жмет кнопку, показывается диалог выбора файлов, он выбирает файл с картинкой, мы проверяем что размер картинки подходит, потом проверяем что у пользователя есть дисковая квота для загрузки картинки, потом загружаем на сервер и выводим сообщение что все ок. Все операции асинхронные, если какая-то из проверок падает, то показываем сообщение об ошибке.
Код выглядит так:
openFile({accept: 'image/*'})
.then(checkImageSize({width: 200, height: 200})
.then(checkContentSize)
.then(upload({tag: 'userAvatar'}
.then(function{
showNotification('Image successfully uploaded');
})
На С++ ты такой код скорее всего вообще не сможешь написать.
В общем, монады жизненно необходимы, без них никуда.
Потому что это мудреж, бесполезный при написании реальных программ,Он не бесполезен, ты просто не умеешь пользоваться.
Реально, уму непостижимо - создали в языке 4 разных типа:Если ты ещё не догадался, они возникли от желания сохранить обратную совместимость на уровне байткода. Это скорее вопрос не инженерный, а для менеджеров. Сохранять или нет обратную совместимость.
После этого эпичного проеба, человеку который это напридумывал - Одерскому - показалось мало и он стал сочинять скалу.А ты уверен, что именно одерски писал библиотеку коллекций, которая так тебе не нравится? Одерски действительно сочинил скалу, потому что ему было мало явы. И в скале и с генериками, и с коллекциями всё гораздо лучше чем в скале.
Я вообще не понял откуда взялся миф о том, что скала - сложный язык и неудобный для новичков. Такое впечатление, что люди вообще не учились программировать, не пробовали лиспа и ML, пренебрегли питоном, впервые слышали об ООП и лямбда-кубе, пришли в скалу и обвиняют её в том, что она не очевидна. Тогда как она очевидна для любого, знакомого с концепциями computer science. Научиться владеть скалой, имея опыт программирования вообще - дело пары месяцев и то большая часть времени тратится не на язык, а на стандартную библиотеку.
На С++ ты такой код скорее всего вообще не сможешь написать.
openFile("image/*")
.then(checkImageSize(200, 200
.then(checkContentSize)
.then(upload("userAvatar"
.then(showNotification("Image successfully uploaded";
Но я лучше буду иметь 100 строк на C++, чем 9 таких строчек, для понимания которых нужно прочитать блог пост, а потом для закрепления и проверки написать ещё один блог пост.Ты хотел научиться программировать на хаскеле за один блогпост? Си ты знаешь небось со школьной скамьи и имеешь большой опыт работы с ним. Если бы ты столько же написал на хаскеле, то и с чтением его конструкций не было бы проблем.
И какой тип будет у функции then?
Если бы ты столько же написал на хаскеле, то и с чтением его конструкций не было бы проблем.Здесь две проблемы. Первая в том, что блог посты пишут как раз те, кто якобы всё время на нём программирует. Вторая в том, что в мире нет такого количества простых алгоритмов и задачек, которые я мог бы написать за эти годы.
И какой тип будет у функции then?Не знаю, я бы назвал его async_sequence. Кстати, на C# ещё можно вот так:
await openFile("image/*");
checkImageSize(200, 200);
checkContentSize;
await upload("userAvatar");
showNotification("Image successfully uploaded");
Или, если мы до 4.0 включительно:
yield return await(openFile("image/*";
checkImageSize(200, 200);
checkContentSize;
yield return await(upload("userAvatar";
showNotification("Image successfully uploaded");
И переход xml -> json совершен только в мире вокруг джаваскрипта по понятным причинам. И то не везде (с html/xhtml на json почему-то никому не приходит в голову перейти).Не только. Я ещё заметил переход в мире конфигов.
Отношения к скала вс джава и краткости записи кода это не имеет.На сравни new Pair<A,B>(a, b имеющее тип Pair<A,B>; и просто (a,b) с типом (A,B)
Второе - лучше читается, несмотря на то, что короче.
Мне это вот что напоминает. Есть стандартный формат bmp, который просто хранит массив пикселей. Есть формат jpg, который гораздо сложнее для чтения и записи, зато сокращает размер. И я не будут спорить, что в данном случае читаемость вошла в противоречие с объёмом. Но ведь тот же битмап можно запихать внутрь xml как массив записей вида <point x="0" y="0">#000000</point>, который будет одновременно и более объёмным и хуже читаемым.
Первая в том, что блог посты пишут как раз те, кто якобы всё время на нём программирует.Уверен?
Уверен?Да, уверен. Если бы блог посты писали идиоты, то язык имел бы репутацию не только слишком сложного и бесполезного для реальной жизни; но и полного багов и дебильных решений.
Не знаю, я бы назвал его async_sequence.В ФП нотации, у функции openFile тип IO File, у функции checkImageSize тип (Int, Int) -> File -> IO Boolean, у функции then - IO a -> (a -> IO b) -> IO b.
Что-то я сомневаюсь, что в рамках C++ это все выразимо.
Кстати, на C# ещё можно вот так:Я бы сам предпочел async/await, но сейчас джаваскрипт в браузерах не поддерживает.
На С++ ты такой код скорее всего вообще не сможешь написать.Дадада, асинхронное программирование на си++ не существует.
В общем, монады жизненно необходимы, без них никуда.
Особенно забавно это утверждение потому, что о монадах в рамках джаваскрипта говорят как о паттерне, а не как о конструкции языка или хотя бы библиотечном классе.
Но я лучше буду иметь 100 строк на C++, чем 9 таких строчек, для понимания которых нужно прочитать блог пост, а потом для закрепления и проверки написать ещё один блог пост.Хаскель - это особый язык. А вот питон или js на порядок лаконичнее крестов в силу целого ряда причин, без какого-либо утяжеления понимаемости
И вообще, ты недавно писал пафосный пост про полеты програмерской фантазии и творчества, а тут пишешь, что лучше в 10 раз больше простого кода, чем в 10 раз меньше сложного
В блог могут писать неофиты и делиться друг с другом познаниями. Коллективная учёба - это естественно.
Что-то я сомневаюсь, что в рамках C++ это все выразимо.Весь код, который ты написал, вполне можно реализовать. Будет выглядеть прямо так, как я написал.
ты недавно писал пафосный пост про полеты програмерской фантазии и творчества, а тут пишешь, что лучше в 10 раз больше простого кода, чем в 10 раз меньше сложногоИ в чём ты видишь противоречие? Какой может быть полёт фантазии, когда мозг постоянно занят попытками понять, что же написано в этих чёртовых 10 строчках? Я лучше расходую его ресурсы на более интересные дела.
мозг приспосабливается. Если он постоянно видит одну и ту же парадигму программирования, он к ней привыкает. В программах на хаскеле есть внутренняя логика. Если ты имеешь опыт, ты знаешь, куда смотреть.
И в чём ты видишь противоречие? Какой может быть полёт фантазии, когда мозг постоянно занят попытками понять, что же написано в этих чёртовых 10 строчках? Я лучше расходую его ресурсы на более интересные дела.Ну как бы это и есть полет творчества и фантазии - разбираться со сложными конструкциями, применять различные парадигмы, писать красиво и лаконично.
Так, как ты предлагаешь - это типичная индусятина.
Если он постоянно видит одну и ту же парадигму программирования, он к ней привыкает.Привыкает, но если она сложная, то мозгу всё равно требуется сначала прочитать чей-то блог пост, потом написать свой блог пост, и только потом приходит понимание смысла, заложенного в 9 строчек кода. Как следствие у языка микроскопическая аудитория и ограниченная область реального применения.
В программах на хаскеле есть внутренняя логика.Зачем мне внутренняя логика, когда меня интересует только внешняя, которую я в данный момент описываю.
Если ты имеешь опыт, ты знаешь, куда смотреть.А если я имею опыт на Си++, то мне вообще не нужно никуда смотреть. Я сразу читаю код.
Ну как бы это и есть полет творчества и фантазии - разбираться со сложными конструкциями, применять различные парадигмы, писать красиво и лаконично.Нужно сначала покраснеть, потом позеленеть и рискнуть посинеть, чтобы упаковать простейший алгоритм в конструкцию, на тему которой потом можно написать диссертацию. Не знаю, как это называется у тебя, а я называю это каторгой.
Привыкает, но если она сложная, то мозгу всё равно требуется сначала прочитать чей-то блог пост, потом написать свой блог пост, и только потом приходит понимание смысла, заложенного в 9 строчек кода. Как следствие у языка микроскопическая аудитория и ограниченная область реального применения.В результате получаем nodejs, потому что людям сложно прочитать блог пост и они не знают лучшего подхода к асинхронному программированию. По последним данным, к nodejs уже 100 000 пакетов написали, в каждом пакете все функции парные - типа readFileSync и readFileAsync. 50% кода - перетасовывание колбэков. Зато аудитория широкая и применяется в больших масштабах.
Привыкает, но если она сложная, то мозгу всё равно требуется сначала прочитать чей-то блог пост, потом написать свой блог пост, и только потом приходит понимание смысла, заложенного в 9 строчек кода. Как следствие у языка микроскопическая аудитория и ограниченная область реального применения.Это называется высокий порог вхождения. Неосиляторы идут мимо.
Я вот например ниасилил хаскель, но я смотрю с уважением и некоторой завистью на тех, ктоего хорошо понимает.
Нужно сначала покраснеть, потом позеленеть и рискнуть посинеть, чтобы упаковать простейший алгоритм в конструкцию, на тему которой потом можно написать диссертацию. Не знаю, как это называется у тебя, а я называю это каторгой.Если преодолеть порог вхождения, то дальше все пойдет намного легче.
Наговнокодить можно и на си. Написать один метод в 1000 строчек, которые никто понять не сможет, включая автора. Суть в том, что для си есть некоторый стайлинг гид, приспособленный для конкретно этого языка, который указывает какие конструкции и где писать, как их отмечать переносом строк и т.д. Так вот, в хаскеле он тоже есть. Просто другой. Один хаскелист лего поймёт другого, если оба придерживаются стандартов кодинга на хаскеле. А си программер хаскеловский код будет читать с трудом, слишком разные парадигмы. Будет читать посты в блогпосте, пытаясь разобраться.
Ну или скажет, что это слишком сложно, избыточное напряжение для мозга и забьёт.
Если ты ещё не догадался, они возникли от желания сохранить обратную совместимость на уровне байткода.Этот аргумент много раз слышал. Но вот, например, в .NET дженерики ввели почти одновременно с Java. Что в .NET нет обратной совместимости? Тогда почему я этого не заметил? Кто бы ее заметил в Java?
Зачем мне внутренняя логика, когда меня интересует только внешняя, которую я в данный момент описываю.Затем, что это позволяет тебе легко видеть алгоритм за строчками. Это как с распознаванием лиц. Наш мозг уже привык разлагать видео изображения на характерные черты и мы легко распознаём лица, узнавая даже в гриме и через много лет старения. А вот такой же практики распознавания азиатских лиц, например, у нас нет. И все китайцы кажутся на одно лицо. Потому что мы не видим никакой структуры в нём, только мозаику не взаимосвязанных визуальных черт.
Понимание общепринятой структуры записи алгоритмов для языка важно так же, как и понимание синтаксиса самого языка. Он позволяет понимать чужой код. Как раз то, чего ты хочешь.
Что в .NET нет обратной совместимости?Уточни, между какими версиями .NET появились генерики. Скорее всего, там потерялась бинарная совместимость.
Тогда почему я этого не заметил?Тебе не нужна была бинарная совместимость, все существующие библиотеки были пересобраны под новую версию. Или нет, судя по тому, что в системе обычно устанавливается одновременно несколько разных версий .NET.
Кто бы ее заметил в Java?Вопрос к менеджменту Явы. Может быть не хотели терять совместимость с большим количеством библиотек и расслоения.
Понимание общепринятой структуры записи алгоритмов для языка важно так же, как и понимание синтаксиса самого языка. Он позволяет понимать чужой код. Как раз то, чего ты хочешь.Все твои аргументы можно применять как к Haskell, так и к C++, они ничего не говорят о связи сложности чтения и сжатости записи.
Ещё раз повторю: чем код плотнее, тем его тяжелее читать, анализировать и поддерживать. Да, можно ко всему привыкнуть, и это скажется на скорости чтения, но она всё равно остаётся неприемлемо низкой. Есть и золотая середина, но C++ к ней явно ближе, чем Haskell.
Такова реальность, подтверждаемая несколькими темами, которые мы в последний раз обсуждали. Например, когда обсуждали quick sort, только смог что-то объяснить по сложности. То есть по характеристике кода, которая всегда должна быть на виду. Если ты думаешь, что Haskell действительно легко читается, тогда ты без проблем сможешь дать мне точные и простые ответы на вопросы об алгоритмической сложности и сложности по памяти того самого трёхстрочного quick sort. Не так ли?
Ещё раз повторю: чем код плотнее, тем его тяжелее читать, анализировать и поддерживать.Бред. Напиши любой код на си, я напишу более разлапистый код на том же си, делающий то же самое. Ну или проведи мысленный эксперимент и придумай такой язык, у которого строения как у хаскеля, но все конструкции должны записывать длиннее или по нескольку раз. Получишь язык более пространный чем си, и явно менее понятный.
Бред. Напиши любой код на си, я напишу более разлапистый код на том же си, делающий то же самое. Ну или проведи мысленный эксперимент и придумай такой язык, у которого строения как у хаскеля, но все конструкции должны записывать длиннее или по нескольку раз. Получишь язык более пространный чем си, и явно менее понятный.Как ты из процитированной фразы сделал вывод, что код на наиболее разреженном языке будет наиболее читаемым? Читай посты полностью и не бросайся сразу же отвечать.
Ещё раз повторю вопрос, если Haskell так хорошо читается, ты готов обсудить со мной сложность трёхстрочного quick sort по памяти?
Ещё раз повторю вопрос, если Haskell так хорошо читается, ты готов обсудить со мной сложность трёхстрочного quick sort по памяти?Что ты к хаскелю привязался? Вот есть язык питон, с очень емким, лаконичным и простым синтаксисом
Что ты к хаскелю привязался? Вот есть язык питон, с очень емким, лаконичным и простым синтаксисомТам совсем другие проблемы, поэтому я не привязываюсь к питону. Он действительно лаконичный, и на нём можно решать большое количество реальных задач. Поэтому он достаточно популярный. Назвать же питон языком, в котором высокая плотность, у меня язык не поворачивается.
Там совсем другие проблемы, поэтому я не привязываюсь к питону. Он действительно лаконичный, и на нём можно решать большое количество реальных задач. Поэтому он достаточно популярный. Назвать же питон языком, в котором высокая плотность, у меня язык не поворачивается.То, что называешь плотностью языка, разве это не то же, что и емкость/лаконичность?
Вот питон - емкий и лаконичный, но весьма понятный
Ещё раз повторю вопрос, если Haskell так хорошо читается, ты готов обсудить со мной сложность трёхстрочного quick sort по памяти?Готов обсудить.
Во-первых, хаскель - это язык, а не реализация. И язык математически строгий, а значит произвол для оптимизации огромный. И всё это зависит от конкретного компилятора. Ты фактически предлагаешь мне поупражняться не в знании языка, а в умении быть его компилятором.
Во-вторых, я не пользуюсь хаскелом для работы, и соответственно не изучал его практического применения. Меня интересовал язык и концепция, а не компилятор. Я никогда не утверждал, что являюсь специалистом хаскеля. Но эффект увеличения понимания в процессе получения опыта я на себе ощущал, причём не только на хаскеле.
И да, пописав на хаскеле, я заметил, что он плохо подходит для больших проектов, но вовсе не потому что слишком лаконичный или слишком сложный для чтения, или слишком медленный. А потому что в нём плохо поставлена декомпозиция больших задач на подзадачи.
Во-первых, хаскель - это язык, а не реализация. И язык математически строгий, а значит произвол для оптимизации огромный. И всё это зависит от конкретного компилятора. Ты фактически предлагаешь мне поупражняться не в знании языка, а в умении быть его компилятором.Я слышал, что многие сторонники Haskell всё время рассказывают сказки про компиляторы. Что кохтпа, что ты. Фактически ты пишешь, что в математически строгом языке нельзя определить математически строгую сложность.
Во-вторых, я не пользуюсь хаскелом для работы, и соответственно не изучал его практического применения. Меня интересовал язык и концепция, а не компилятор. Я никогда не утверждал, что являюсь специалистом хаскеля. Но эффект увеличения понимания в процессе получения опыта я на себе ощущал, причём не только на хаскеле.Да, я не спорю что ты ощутил эффект увеличения понимания. И другие программисты его тоже могли бы ощутить. Но скорость чтения всё равно осталась бы неприемлемо низкой.
То, что называешь плотностью языка, разве это не то же, что и емкость/лаконичность?Я уже несколько раз упоминал о том, что есть и золотая середина. К чему ты написал свой пост мне не понятно.
Вот питон - емкий и лаконичный, но весьма понятный
P.S. Java программисты как-то мирятся с тем, что не могут предсказать поведение garbage collector. Потому что абстрагированы от него.
К чему ты написал свой пост мне не понятно.К твоему утверждению, что лучше 100 строк на плюсах, чем 10 строк, в которые уместится то же самое
почему нельзя? Можно, причём десятком разных способов. Не факт, что компилятор будет иметь то же самое представление. Особенно если определять сложность через минимум сложности, достижимой на любых реализациях языка.То есть в математически строгом языке такое математически строгое понятие, как сложность алгоритма, не определено? Вот это на мой взгляд и есть самый настоящий бред.
Хорошо. Если для обсуждения требуется выбрать конкретную реализацию, то давай обсудим сложность quick sort в той, которой ты больше всего пользовался. Если язык читаемый и реализация хорошая, то ты без проблем сможешь объяснить всё, что происходит. Не так ли?
Уточни, между какими версиями .NET появились генерики. Скорее всего, там потерялась бинарная совместимость.Дженерики появились при переходе с .NET1.1 на .NET2.0. Вроде, скомпилированные сборки под .NET1.1 можно запускать под .NET2.0. Просто там List<T> поместили в другой неймспейс и всё. А в Java почему-то захотели чтобы старый нетипизирвоанный List был новым List. Зачем такое, не понятно.
К твоему утверждению, что лучше 100 строк на плюсах, чем 10 строк, в которые уместится то же самоеЭто утверждение относилось к тому коду на Haskell, для понимания которого нужно было прочитать 2-3 блог поста на 100 строк каждый.
Я не изучал свой компилятор. Мне было всё равно как он генерирует код.
Я не изучал свой компилятор. Мне было всё равно как он генерирует код.Остаётся только сказать, что слив засчитан.
Хорошо. А ты умеешь программировать на машине тьюринга? А нормальные алгоритмы Маркова тебе знакомы?
Хорошо. А ты умеешь программировать на машине тьюринга? А нормальные алгоритмы Маркова тебе знакомы?Ну, справедливости ради, понимание принципов компиляции и устройства компилятора своего языка - это must have хорошего программиста.
Ну мне интересно, как ты будешь оценивать потребление памяти алгоритмами маркова или машиной тьюринга.
Ну мне интересно, как ты будешь оценивать потребление памяти алгоритмами маркова или машиной тьюринга.Я не программирую на машине тьюринга
Если нет возможности оценить сложность и потребление исходя из априорных соображений, welcome to профилировщик
welcome to профилировщикЭто тоже не панацея. Например, 99.9% программистов на C# используют динамический массив для реализации алгоритма Дейкстры. Я более чем уверен, что ещё 99.9% из них оставит всё как есть даже после профилировки.
А ты умеешь программировать на машине тьюринга? А нормальные алгоритмы Маркова тебе знакомы?А с какой целью ты интересуешься?
Это тоже не панацея. Например, 99.9% программистов на C# используют динамический массив для реализации алгоритма Дейкстры. Я более чем уверен, что ещё 99.9% из них оставит всё как есть даже после профилировки.1. портрет_программиста_C#_на_известной_картинке.jpg
2. профилировщик + мозги - лучше чем только профилировщик
3. в реальности профилировка нужна на 99.9% только для выявления бутылочных горлышек
но ведь это не влияет на читаемость алгоритмов?
Если признаешься, что умеешь их читать и писать, попрошу сделать оценку по памяти для местного квиксорта
но ведь это не влияет на читаемость алгоритмов?Как можно прочитать алгоритм, не поняв его сложности? Что за бред.
Если признаешься, что умеешь их читать и писать, попрошу сделать оценку по памяти для местного квиксортаА если не признаюсь или не знаю? Какой из этого вывод можно будет сделать в отношении дискуссии о читаемости кода? Тогда уж лучше было говорить о шаблонах в C++, но я всё равно являюсь противником чрезмерного их использования.
поищу другой пример. На мой взгляд, понятие сложности не является неотъемлемым свойством программ. И вполне можно рассматривать программы в отрыве от сложности.
"Thus, programs must be written for people to read, and only incidentally for machines to execute"
Почему я никак не могу отделаться от ощущения, что любой мой тред в программинге (даже нубско-пустяковенький) рождает охренительный холивар?
Ты избранный. Несёшь в мир холивары.
Это называется высокий порог вхождения. Неосиляторы идут мимо.Осилить можно конечное количество вещей. Кому-то интересно осиливать новые способы записи одного и того же. Кому-то интересно осиливать имплементацию новых вещей.
хаскел - это прежде всего концепция, а не форма записи. И она полезна даже там, где эти концепции не реализованы на уровне языка.
Какие-то более продвинутые вещи, ммм, не вызывают отклика в их душах.
Какие-то более продвинутые вещи, ммм, не вызывают отклика в их душах.Давай обсудим что-нибудь продвинутое?
Есть предложения?
Есть предложения?Бля...
почему List<Integer> не является подтипом List<Number>Дж-ва не умеет в ковариантность?
Мысль, что мне нужно будет читать код этих людей на скале, меня ужасает.Но ведь им придется понять ковариантность при изучении Скалы!
Или для нее уже изобрели Learn Scala in 28 days in 10 simple steps?
На С++ ты такой код скорее всего вообще не сможешь написать.Ладно врать-то.
Ладно врать-то.openFile("image/*")
.then(checkImageSize(200, 200
.then(checkContentSize)
.then(upload("userAvatar"
.then(showNotification("Image successfully uploaded";
Что-то я сомневаюсь, что в рамках C++ это все выразимо.Use the Force, Luke.
А разве возможна ковариантность в изменяемых контейнерах? Вот обёртка Collecions.unmodifiable... вполне себе ковариантна
Дж-ва не умеет в ковариантность?Я бы скорее предположил, что коллекция мутабельна.
Ладно врать-то.Ладно троллить-то, код тривиальный.
ps
кстати, для js это как решается?
Как обеспечивается, что достаточно писать .then(upload(args вместо .then(function{return upload(args);})? (за исключением банального способа, что функции upload и т.д., заранее пишутся, как функции возвращающие функции)
А List — это mutable? а то я не в теме.
Как обеспечивается, что достаточно писать .then(upload(args вместо .then(function{return upload(args);})?Функции типа upload почти всегда вызываются внутри такого асинхронной цепочки, поэтому удобно сразу реализовать их так:
function upload({tag}){
return function(file){
...
}
}
Если это кажется уродливым, то можно пользоваться тем частичным применением, которое есть в js:
function upload({tag},file){
...
}
..
openFile.then(upload.bind(null, {tag: 'userAvatar'})
Правильно я понимаю, что "Дж-ва не умеет в ковариантность?" cледует читать как " не умеет в дж-ва?"
Я тоже. Но есть подозрения, что мутабелен, поскольку это самое простое объяснение почему коллекция (любая абстрактная) может не быть ковариантной.
В контексте того, что это было про List<Number>, следует читать как "А в чем вопрос-то ваще? "
Кстати, правильнее так: настолько не хочет уметь в дж-ва, что постоянно читает про всякие скалы и прочие кложы.
Ведь " настолько не хочет уметь в дж-ва, что постоянно читает про всякие скалы и прочие кложы" => " не умеет в дж-ва?"
а смысловую нагрузку несёт именно следствие, потому что позволяет не обращать внимание на твои заявления по жабе.
Незнание языка само по себе ни хорошо, ни плохо. Зачем тебе дать понять, что ты "мог бы, но не хочешь"?
Но ведь им придется понять ковариантность при изучении Скалы!Хотел сначала написать, что знание Скалы, наверное, неплохой критерий для найма новых сотрудников (мотивировать старых, как показывает практика, контрпродуктивно).
Но потом, листая этот тред с аватарками, мне внезапно пришло в голову, что таким ничто не мешает не знать, собсно, джаву, и как-то весь смысл потерялся...
Как будет вызов функции превращаться в отложенный вызов этой же функции? через макрос?ну типа несколько путей: через макросы самый топорный
можно сделать функции, которые будут возвращать std::function (или boost::function) с нужным действием
http://lmgtfy.com/?q=javadoc+listПусто. Говорит ему кроме парсера html ещё какой-то скриптовый язык нужно.
Но ты не беспокойся, у меня доступ к javadoc в иде встроен, посмотреть не сложно. Ты только скажи полный fully qualified name для соответствующего класса.
P.S. Что ява в принципе поддерживает ковариантность я прекрасно знаю, потому что использую её под скалой и знаю как она транслируется в ява выражения.
Но ты не беспокойся, у меня доступ к javadoc в иде встроен, посмотреть не сложно. Ты только скажи полный fully qualified name для соответствующего класса.Ctrl-N или Ctrl-Shift-T или Ctrl-O должны были тебе помочь.
Что ява в принципе поддерживает ковариантность я прекрасно знаю, потому что использую её под скалой и знаю как она транслируется в ява выражения.Я догадываюсь. Скорее проще назвать языки с type parameter'ами, где параметры всегда инвариантны.
Я вообще не об этом. Я скорее о показной сибаритской лени в этом разделе, которая используется как элемент дискуссии. И это ладно, когда надо пойти и прочитать статью, но когда достаточно просто в гугле набрать два слова и перестать гадать...
Даже с моей ссылкой. Если у тебя отключены какие-то скриптовые языки в браузере, то я оставлю тебе как домашнее задание извлечение строки поиска из урла. Подозреваю, ты должен быть привычен к таким штукам. Сделал бы ты это сразу - мы бы сейчас не тратили на это время.
Pair <X, Y> [] pairs =
new PairArrayBuilder <X, Y> .
add (x1, y1).
add (x2, y2).
add (x3, y3).
build;
Ctrl-N или Ctrl-Shift-T или Ctrl-O должны были тебе помочь.Это в огнелиса вбивать или в emacs?
P.S. Это не сибаритская лень, просто интереснее угадать самому, чем подсмотреть ответ.
в emacsДа, я боялся этого.
Нет, это были шорткаты для IntelliJ, Eclipse и Netbeans соответственно, которые нашли бы тебе List без FQDN.
Так же как в случае со скриптовым языком, это был твой осознанный выбор, ты в меньшинстве, поэтому я предлагаю страдать тебе, а не пытаться заставить страдать всех вокруг.
Ты учитываешь, что скаловская IDE тебе скорее найдёт скаловский лист, чем явовый?
Должен найти оба варианта, из которых ты должен будешь выбрать.
Как будет вызов функции превращаться в отложенный вызов этой же функции? через макрос?Нет, в 11-ых плюсах, на которых я никогда не писал, всё оказывается весьма просто:
async_op<image> check_image_size(int w, int h)
{
return [w, h] (const image& img)
{
std::cout << "check image size " << w << ", " << h << std::endl;
if (img.m_w > w || img.m_h > h)
throw std::runtime_error("bad image size");
};
}
.then(function{
showNotification('Image successfully uploaded');
}
тогда превратится в
.then([]{showNotification('Image successfully uploaded');})
?
.then(function{Это же вызов оформленной функции? Или ты про то, что её тело не оформлено? Тогда да, можно сделать так: .then([] { show_notification; });
showNotification('Image successfully uploaded');
}
На самом деле, если бы я сейчас взялся за асинхронное программирование на C++, я бы наверняка прикрутил эмуляцию coroutines через переключение контекста или фиберы. Писать код через обратные вызовы слишком сложно.
Ок.
Нет, в 11-ых плюсах, на которых я никогда не писалзабавно видеть левый код на плюсах в треде про жаву
зачем вводишь людей в заблуждение? =\
в плюсах нет async_op, зато есть
std::promise
std::future
std::packaged_task,
std::async
где планировали добавить then
почитать можно в гугле:
proposal:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n355...
.then реализовали вроде только в бусте:
http://stackoverflow.com/questions/22597948/using-boostfutur...
корутины можно взять в том же бусте:
http://www.boost.org/doc/libs/1_57_0/libs/coroutine/doc/html...
забавно видеть левый код на плюсах в треде про жавуПочему левый? Это вполне рабочий код. Класс async_op я написал для демонстрации типа возвращаемого значения; понятное дело, что его нет в stl.
зачем вводишь людей в заблуждение? =\
в плюсах нет async_op, зато есть
Это вполне рабочий код. Класс async_op я написал для демонстрации=> это нерабочий код
если бы ты написал std::function вместо async_op, то тебя бы поняли (те кто вообще плюсы видел да еще и рабочий код был бы, да еще и из STL
=> это нерабочий кодРабочий, я его компилировал и запускал прямо в том виде, который был в ответе на пост DDD. И вообще не понимаю, с чего ты решил вдруг придраться к этому коду.
то тебя бы поняли (те кто вообще плюсы видел)Уверен, что они и так меня прекрасно поняли.
не понимаю, с чего ты решил вдруг придраться к этому кодуда делать нечего, вот и придираюсь
вместо жавовских туплов тред скатился в плюсовые асинки
Просто там List<T> поместили в другой неймспейс и всё. А в Java почему-то захотели чтобы старый нетипизирвоанный List был новым List. Зачем такое, не понятно.1. чтобы не копировать реализацию одной и той же коллекции в разные неймспейсы.
2. чтобы новый List<T> можно было использовать вместе с кодом, который написан в те времена, когда нового List<T> ещё не существовало.
1. чтобы не копировать реализацию одной и той же коллекции в разные неймспейсы.ну не знаю, кодегенерацию на худой конец прикрутили бы. Вопрос на две копейки.
Но вообще я не понимаю к чему относится твое предложение.
2. чтобы новый List<T> можно было использовать вместе с кодом, который написан в те времена, когда нового List<T> ещё не существовало.
А зачем?
ну не знаю, кодегенерацию на худой конец прикрутили бы. Вопрос на две копейки.к тому что код любой библиотеки, работающий с коллекциями должен будет уметь работать как с тем, так и с другим видом коллекций, и по-хорошему любая новая коллекция из библиотеки должна быть и там и там - всем кодогенерацию прикручивать? а поддерживать и баги в ней потом кто будет?
Но вообще я не понимаю к чему относится твое предложение.
А зачем?а зачем вообще совместимость поддерживать?
В джаве, надо признать, из двух вариантов "усложнить жизнь пользователям" и "усложнить жизнь разработчикам jvm" всегда выбирается первый. В этом есть как и плюсы - относительно простая runtime machine, о которой легко рассуждать (ну, то есть как, рассуждать нифига не просто, но могло бы быть хуже, видимо); так и минусы - эпизодический трах с генериками (но надо признать, именно type erasure редко мешается, и в большинстве случаев обходится).
Хуже то, что, например, массивы не поддерживают ковариатность никак, и даже кастом это не поправить. Вот это вот реальный косяк, который порой очень мешается.
Хуже то, что, например, массивы не поддерживают ковариатность никак, и даже кастом это не поправить. Вот это вот реальный косяк, который порой очень мешается.м? даже википедия с тобой не согласна, не то что IDE и JVM.
Конечно, в джаве с массивами все равно есть раздражающая фигня, когда массив примитивов не кастуется в массив обернутых объектов и обратно, но если бы они смогли запилить это, то тогда резона для оберток вообще не оставалось бы...
Давайте считать, что я имел в виду это
Оставить комментарий
yolki
чё, по-простому нельзя? это ж ппц как неудобно.ну вот скажем я хочу иметь массив key-value, как в шарпе:
как это сделать в джаве не очень монструозно?
решил вот расширить кругозор и начать кодить под андроид.