Нет, они одинаковые. Трансформации, компиляция и все прочее не может менять логику.
Вы о какой логике говорите? Логика бывает разного уровня.
Если о логике и поведении описанном в коде высокого уровня — то оно сохраняется.
Но то как это поведение будет отражено в машинные инструкции — и по какой логике они будут работать — это может как сильно отличатьcя как от ваши представлений, так и сильно разниться от компилятора к компилятору.
Более того, логика работы исходного кода и логика работы машинного кода — они обязаны быть разными. Но обязаны реализовывать одинаковое поведение.
Например, на уровне кодов процессора нет никакого ООП и наследования.
О какой одинаковости логики вы вообще можете говорить, если логика работы вашего исходного кода построена на ООП-понятиях?
Сохраняется поведение, но даже не всегда детали логики исходного кода.
Посмотрите мой ответ https://habrahabr.ru/post/334964/#comment_10352244
и скажите — оптимизирущие компиляторы — они какую логику меняют? и что они вообще меняют?
ну на другой вопрос про разную реализацию await- тоже хотелось бы услышать ответ. спасибо )
Вообще-то компиляция это процесс отображения одного представления кода в другой. Логику выполнения компилятор не трогает, более того, если вдруг такое случайно происходит, то это баг и его очень быстро чинят.
Не совсем так))
Если быть более точными — компилятор реализует поведение, описанное на языке высокого уровня, с использованием языка более низкого уровня.
А вот какая логика будет использована на этом низком уровне — на уровне машинного кода или байткода — это уже его личное дело, покуда он остается в границах ожидаемого поведения, описанного языком высокого уровня.
Вот возьмем оптимизирующий компилятор — если поведение не изменится, он может вообще выкинуть всю логику расчета внутри вашей функции, и сразу выдавать на выход константу. Если, конечно, он обнаружит, что вне зависимости от входных параметров всегда получается одно и то же число.
Он легко может начать не умножать или суммировать, а дергать сдвиги, или, скажем, развернет циклы, если посчитает что так будет лучше. У вас в исходном коде — «визуально-однопоточный» циклический код, а на уровне машинного кода — 4 линейных параллельно исполняющихся цепочки.
Или, что скорее всего происходит и смущает вас — превратит синхронный код с await, в лапшу последовательно вызываемых асинхронных функций, связанных callback-ами.
А другой компилятор, может легко сделать не коллбеки, а 3 потомка и семафоры. Ведь согласитесь, await можно легко «сделать на семаформах».
Поведение программы, в обоих будет одинаковое, а логика и структура работы машинного кода (или байт кода) — разная.
И вот в такой ситуации — когда у нас реализация одного поведения, может быть построена на разных принципах, разной логике — скажите — как классифицировать сам исходный код? — по структуре его поведения, или по структуре того, что получается на выходе компилятора?
Вы, зачем-то, уцепились за выход компилятора. Вы уверены что это правильно?
Но именно так работает async/await в Scala/C# и JS — вешает весь код дальше в колбек. На Future, Task и Promise соответственно.
Не находите, что все ваши рассуждения в этой ветке теряют смысл?
Вы зачем-то смешиваете логику работы откомпилированного байт-кода (после оптимизации, преобразований и трансформации) и логику исходного кода. Они могут быть разные.
Исходно, как я помню, мы говорили именно о логике исходного кода, и о том, что именно «синхронный» код позволяет описывать многие вещи проще и быстрее, чем событийно-ориентированный, асинхронный подход, потроенный на обработчиках и call-back.
и так:
Исходный код с использвоанием await — синхронный.
Байт-код/машинный код может быть каким угодно. И это не отменяет синхронности исходного кода.
Или вот для аналогии ещё пример: если я написал синхронные обертки над асинхронными функциями с call-back — то та часть исходного кода, которая использует обертки — синхронная. Вне зависимости от того, что внутри обертки — асинхронные функции.
или вот ещё загадка:
У меня есть абстрактный класс с одной функцией waitForBytes() которая не должна отдавать управлениедо момента своего окончания. Далее, я реализовал интерфейс в 2-х потомках — в одном я использвал синхронной функции, а в другом — на синхронных функциях и на асинхронных callback.
Скажите — код который использует интерфейс — он синхронный или асинхронный? если думать о том, что лежит под функцией, а не над тем, как оно должно себя вести, то у вас возникает ситуация, что классификация участка исходного кода будет динамически меняться. Что есть бред.
Вообще асинхронность подразумевает, что что-то происходит независимо от основного потока выполнения. Использование await соответствует этому определению, потому что фактически обозначает:
определение не полное, именно поэтому вы путаете многопоточность и асинхронность.
Асинхронность (в случае локального, выполняющегося на одной машине кода) как правило говорит о том, что вы умеете реагировать на события/сообщения/уведомления от «того, что происходит независимо от вас» — когда что-то стороннее начинает вас уведомлять — и у вас как правило есть «обработчики»/«подписки»/«хуки»/«коллбеки»… — которые будут вызваны когда событие произойдет).
А если вы останавливаетесь на текущей инструкции, до тех пор пока не выполнится что то независимое от вас — это синхронный код.
Вы сами синхронищируетесь с чем-то — вне зависимости от того, на что вы смотрите или за чем вы следите.
То, что после await, выполнится тогда, когда задача, на которой сделан await, завершится (что является асинхронным событием). А сейчас возвращаем управление тому, кто нас вызвал.
завершение процесса — не стоит называть асинхронным событием.
Вот если бы ваш таск присылал вам в случайные моменты времени сообщения, и вы на них реагировали — это было бы асинхронным событием.
А так — это поведение, сходное с обычным «семафором».
Сравните вашу фразу с фразой "то, что после «вызова mуSemaphore.release(), выполнится только тогда, когда сосдений поток освободит семафор».
Но семафоры — это обычная синхронизация потоков, а ни какая ни «асинхронность».
И по-вашему, если я начал долгую асинхронную операцию IO, потом долго что-то считал, и потом «жду» результата начатой ранее операции через await — это типа все синхронно?
это запуск потока с последующей синхронизацией потоков.
И да, это, по логике/стилю работы работы — синхронный код.
Приведите пример «асинхронного кода» в вашем понимании.
а-синхронный код, в классическом, верном, понимании — это суть, событийно ориентированный код, который построен на колл-беках и/или обработчиках событий
примеры асинхронного апи: WinApi функции работы с последовательными портами, в которые вы передаете ссылку на функцию, которую надо вызывать, когда на вход поступят байтики. Qt-шные сигнал-слоты. Промисес в js (потому что вы передаете им функцию/ссылку на функцию)
int main()
{ ...
serial->setOnByteIncomeCallBack(&onByteInome);
serial->writeBytes(....);
}
int onByteInome(byte bytes[])
{ ...
}
сначала, про поток в определении: вы цепляетесь за реализацию, причем даже конкретный частный случай сишарпа.
Раз это деталь реализации, значит бывают реализации, где и такое происходит.
не совсем верный вывод… могут, и есть, реализации, к которым само понятие «блокировка вызывающего потока» не применимо, а понятие «асинхронный вызов» — применимо.
я пытаюсь вывести вас на определение асинхронного вызова, которое не зависит от деталей реализации. тогда вы будете понимать почему ваш код, который вы написали — «построен по логике синхронных вызовов».
вот скажем, о каких потоках и блокировках, мы можем говорить, если мы попытаемся определить, скажем что такое синхроные и асинхронные вебсервисы?
или вот: поток может быть вообще прекращен (как тут кто то говорил про то, как работает await), или под каждую инструкцию или группу инструкций будет свой поток создаваться (почему бы и не создать такую машину для байткода? проанализировать зависимости и распараллелить для оптимизации на многоядерном проце?) — вариантов масса, и понятие «блокировка потока» вообще будет неприемлемо — все зависит от реализации. особено, если мы говорим не про машинный код, а про машины исполняюшие байткод.
вы просили "пример асинхронного вызова, который блокирует вызывающий поток" — это конечно бред, но вот вам пример «асинхронного», для которого понятие вызывающий поток вообще не применимо: асинхронный вебсервис.
или вот еще «немного путарицы» пример: вызов синхронного вебсервиса может быть реализован на вызывающей стороне по синхронной локиге построения кода, так и по асинхронной.
теперь про определение асинхронности: вот немного скорректированное определние асинхронного вызова, которое я давал выше:
при асинхронном вызове запускается выполнение инструкций в параллели, а и не дожидаясь его кончания, управление возвращают в точку вызова (или сигнализирует о том, что выполнение инструкций запущено); в точке вызова, после этого, как правило, продолжается исполнение инструкций с места вызова.
при синхронном вызове, возврат управления в точку вызова не осуществляется (или сигнал об окончании исполнения не передается), пока не закончено выполнение инструкций в вызванной функции.
и совершенно не важно что у вас тут: сишарп, джава, или взаимодействие между двумя хостами при RPC или вызов вебсервиса описанного в wsdl.
отодвиньтесь от деталей. вы зарылись в частные учебные определения, и забыли изначальную суть. более того, вы используете смешанные механизмы, которые используют или допускают и асинхронный вызов, и последующую синхронизацию, но заявляете чтт это «полностью асинхронный код». жто не верно.
в вашем примере ( в конце которогоо гордо заявляете «вот полностью а-синхронный код») — вы строите именно синхронный код, вызываете функции синхронно,… а потом заявляете что код «полностью асинхронный»… извините, но это… очень мягко говоря… не верно.
вы не переходите на следующие инструкции пока не выполните операции чтения из компорта. иначе вся логика работы кода разрушится.
при вызове функции через await, вы не перейдете на следующую строчку кода, пока функция не будет завершена — и именно поэтому ваш вызов синхронный, и потому код ваш — синхронный: он построен по логике синхронных вызовов. вне зависимости от того что происхолит внизу с потоками, асинхронными и не очень функциями — ваш вариант псевдо-исходника и логика его работы — синхронные, или повторяют мой код, полностью построенный на синхронной логике.
если бы вы объявляли для своих асинхроных функций callback-и, и каждое обращение ловили именно в них, то ваш код был бы асинхронным. суть — событийно ориентированным. аки как его любят js-ники, ратующие за однопоточность и событийно-ориентированность.
я предлагаю прекратить говорить сугубо частными терминами сишарпа (таски, async/await ) когда рассуждаете об асинхронности. вы топик видели?))) вы понимате что такое опредение — это как минимум слишком узкое понимание? тем более, вы используете механизмы которые не столько относятся к асинхронному/синхронному вызову, сколько к потокам и синхронизации потоков.
Асинхронная функция отличается от синхронной тем, что она возвращает управление почти сразу же.
верно! если быть точнее асинхронный вызов запускает выполнение потока инструкций в параллели, а сам, не дожидаясь его кончания, отдает управлепие в точку вызова, где после этого продолжается исполнение инструкций с места вызова.
«асинхронный» именно вызов, а не сама функция. и оператор await — занимается именно тем, что позволяет изменить синхронность вызова у функции, у которой стоит директива асинхронного вызова по умолчанию.
т.е. он позволяет приостановить выполнение потока инструкций в текущей функции, пока не закончится выполнение вызываемой функции.
сужу по официальным докам майкрософта.
И async/await — это именно что способ написания асинхронных функций
я бы рассматривал это как способ определения того, как вызывать функцию по умолчанию, и как изменить синхронность вызова.
идея таких директивы/оператора действительно интересная; выглядит удобно, позволяют не писать обертки. в джаве это желается несколько более громоздко.
но согласитесь, определение у функции директивы (?) «async», а потом вызов её с оператором await — это полностью соответсвует определению синхронного вызова: «выполнение инструкций в точке вызова, не продолжается пока не закончено выполнение инструкций в вызванной функции».
а если это соответвует синхронному вызову, то как же мы можем говорить про код, использующий await, что он асинхронный? он построен по логике синхронных вызовов. а то что где то там внутри есть асинхронные процедуры — это уже третье дело. исходник с await — синхронный.
Я, конечно, подозревал, что полное, безоглядочное погружение в идеологию и технологии мягкотелых вызывает… определенного рода… профессиональную деградацию…
Но то, что вы тут уже 5й пост устраиваете параолимпиаду по синхронным методам запуска асинхронных функции… и при этом заявляете что это «полностью асинхронный код»…
Я потрясен. «Такое» я вижу впервые.
Вы… в некотором роде, теперь, мой личный рекордсмен.
В отдельной, особой номинации. Для «тяжеловесов».
То, что вы тут язощеряетесь и демонстрируете «удобные и красивые методы» работы с асинхронными функциями, как раз доказывает, что далеко не везде асинхронность и событийно ориентированность — к месту. Потому что все что вы показываете — это как раз вариации на тему, как бы нам асинхронный вызов превратить в синхронный, и приостановть выполнение текущего потока инструкций (и поверьте всем глубоко плевать, блокируется при этом поток или освобождается, или начинается другой поток — это детали реализации. не важные по большому счету)
Да, эти методы позволяет не писать особых оберток, но это не делает ваш код «асинхронным».
То, что вы вызубрили костыли сишарпа — это конечно похвально, но даже то что вы показали, не поможет вам красиво и удобно, без лишних оберток работать с WinApi в котором вы должны «передать вниз» ссылку на callback функцию, которую надо вызвать, когда данные поступают.
Скажите, а вы точно понимаете что такое асинхронный и синхронный вызов?
Вы использовали выражение await, для того, что бы явно сделать синхронный вызов функции, которая заявлена как «асинронная», и говорите что взаимодействие стало асинхронным? вы уверены что не запутались?
Синхронный вызов — это когда исполнение приостанавливается в точке вызова.
Именно это вы и делаете, когда предлагаете использовать await.
А блокируется или приостанавливается при этом поток, какие потоки при этом вызываются, что используется внутри или не вызываются, что происходит внутри — это уже технические детали рализации.
Например похожие технические эффекты, (похожие на await) можно добиться в Java 'без всяких await' с использвоанием yeld() — он отдает ресурсы потока на другие задачи, не не разрушая контекст исполнения.
А «асинхронный» вызов, не приостанавливает выполнение кода в точке вызова в ожидании ответа, а сразу преходит к следующей инструкции.
Правильнее было тогда бы наверное скорее обернуть через TaskCompletionSource в нормальный асинхронный интерфейс и работать не теряя производительности и не блокируясь, и при этом пользуясь хорошим инструментом.
нет))) не правильнее))
не будет а-синхронный интерфейс давать вам видеть нормально логику работы кода и отслеждивать диалог с принтером.
Мыслите не уровнем «stateless» механизма принял-отдел, а уровнем всей задачи, когда вам надо хранить состояние и (очень желательно) контекст исполнения.
Вот давайте по порядку на примере
Инициализация принтера — это порядка 20 команд, каждая и которых имеет свой ответ. и в зависимости от ответа вы ещё должны иногда задавать дополнительные команды в зависимости от того, о чем вам рассказал принтер. Например для этой прошивки надо ещё кодировку поменять, а тут — установить плотность другую.
Рассмотрим на примере псевдо c++ кода гипотетической функции инициализации принтеров определенной серии с использованием синхронных функций:
Функция waitForBytes() — синхронная. не отдает управление пока не получен минимум 2 байта, или не истек таймаут. Если получено больше чем ожидается — отдает весь полученный объем данных.
int initPrinter()
{
serial->send( {0x??, 0x??, 0x??}); //запросим модель принтера
byte[] resp=serial->waitForBytes( 18, 5000); //ждем ответ принтера - минимум 8 байт, 5 секунд.
if (resp==NULL) return -100; // timeout
if (sizeof resp <8 ) return -101; // ответ не распознан
String model = new String(resp);
if ( ! model->startsFrom("Posiflex") ) return -102; // не поддерживаемая модель принтера
if ( ! model->equals("Posiflex PP5200") )
{
serial->send( {0x??, 0x??, 0x??}); //запросим прошивку принтера
resp=serial->waitForBytes( 2, 5000); //ждем ответ принтера - 2 байта, 5 секунд.
if (resp==NULL) return -100; // timeout
...
if (resp[0]==0x23 and resp[0]==0x24) // упс... у нас тут модель с прошивкой с известным багом
{
serial->send( {0x??, 0x??, 0x??}); //уст. кодировку 866 - в этой прошивке исходно 1251
resp=serial->waitForBytes( 2, 5000); //ждем ответ принтера - 2 байта, 5 секунд.
if (resp==NULL) return -100; // timeout
....
}
};
serial->send( {0x??, 0x??, 0x??}); //переведем принтер в страничный режим с абс. позиционированием
resp=serial->waitForBytes( 2, 5000); //ждем ответ принтера - 2 байта, 5 секунд.
if (resp==NULL) return -100; // timeout
....
return 0;
}
Вот теперь, перепишите этот маленький и простой кусочек кода «в асинхронной, неблокирующей логике». Вы сможете сделать его столько же простым, прозрачным и понятным, что бы он не вызывал проблем при отладке, и не приводил к желанию материться?
Поймите, тут как раз тот случай, когда асинхронная логика «ну не в вперласть» никаким боком.
От слова совсем.
Удобно и просто прозрачно когда один поток, который ведет диалог с принтером, и ждет ответ от него, с сохранением контекста исполнения и состояния. Потому что это позволяет просто и легко описывать сложную логику диалога с устройством.
Если вам сложно мыслить принтером и последовательным компортом, то представьте, что у вас сокет на удаленный хост — у вас кастомный протокол, и в процессе «рукопожатия» — вам надо запросить у него кучу подробнотей, и в зависимости от того, что он вам ответит — что то ему рассказать дополнительно, или не рассказать.
так, народ)))
во первых… не в шарпах я работал. дело было в году 2006-м 2007 и сишарп тогда был… далеко не самым интересным, чем можно было заниматься. от слова совсем.
во вторых — я делал на с++ кроссплатформенную обертку над работой с компортами, и в виндовой части проекта я работал с WinAPI и использовал неблокирующее чтение с коллбеком. Потому что реализовать блокирующее чтение с таймаутом — … ну вот как-то не вышло. В линуховой части все вышло на ура, а вот c WinAPI — матов было много. А таймаут надо было иметь.
а потом туда же (через этот интерфейс) был пристыкован доступ к «виртуальному компорту» ( serial профиль USB-устройства — некоторые принтеры делают именно так)… и матов было примерно столько же.
Да и не про это разговор. разговор о том, что не все задачи можно и удобно решать в событийно-ориентированной логике. А работа с ком-портом — это только пример такого противоречия, когда низкоуровневый интерфейс — событийно-ориентированный, а вам надо делать синхронное взаимодействие, потому что иначе логика инициализации ии проверки состояния принтера усложняется во много крат — когда ты прежде чем послать задачу, проверяешь у него с десяток флагов и состояний, и при необходимости — ещё и настраиваешь режимы и подрежимы.
Объясните, разве это плохо — ездить на конференции по своему языку программирования? Плохо, что в какой то технологии можно за 20 секунд сделать что-то?
Нет, ездить на конфернцию не плохо.
Плохо терять критическое мышление в результате этой конференции)))
именно об этом пишет автор.
в который раз раз повторюсь: я был свидетелем безумия рубистов и пхпшников, которые запихивали свои «супертехнологии» в промышленные проекты ( со сложной бизнес-логикой, высокими требованиями к надежности, и большим объемом обратываемых в одном запросе данных, с высоким темпом изменений, в условиях большого объема кода и сложной логики) — не понимая где лежит граница применимости их технологий.
и я видел, что происходило с этими проектами через полгода, через год, через 2. ничего хорошего.
ведь, имхо, именно о потере критического мышления пишет автор во фразе «вирус откусывает ту часть мозга, которая помнит о многопоточности — она умирает не успев задать свои вопросы».
событийно ориентированный стиль разработки прекрасен.
но строго до тех пор, пока им не пытаются замень что то сугубо многопоточное или требующее синхронности.
скажите, вы когда либо писали код взаимодействия с промышленым принтером через rs-232? а я писал.
и в гробу я видел, извините за выражение, тех, кто написал «событийно ориентированные» классы, которыми я был вынужден пользоваться. потому что когда ты работаешь с принтером — тебе надо поддерживать его состояние и контекст, а проверять это всё каждый раз когда ты просыпаешься в «onByteRecieved()» — настолько усложныет код, что мне пришлось отдельно сидеть и писать «синхронные обертки» над асинхронным интерфейсом работы с ком-портом. потому что только синхронный интерфейс позволял мне сохранить простоту структуры кода и прозрачность логики. а обертка работала, только благодаря многопоточности.
вот такая сказка об идеализации однопоточности и событийности в реалиях жизни.
к чему я? к тому что сейчас очень много школоты, потеряв критичность мышления пихают js куда можно и куда нельзя. и этт плохо. об этом весь холивар.
«Здоровый» человек не будет обсирать другую технологию, которую он не понимает, которая стала вдруг популярной. «Здоровый» человек напишет про свою любимую технологию.
Не хочешь JavaScript на backend, не применяй (если ты решаешь чему быть), убеди тех. директора чем C# лучше JavaScript, не работай в компании с «больными» людьми, и все остальное в этом духе.
несколько не правы, имхо. действительно здоровый человек знает ограничения и границы прменимости технологии. и использует js там где он пригоден, а java там, где java работает лучше всего, с# — там где ему место, а не убеждает тех директора что c#/java лучше или хуже js.
у каждой технологии — свои границы применимости. и, напрмер, имхо, пихать js-на сервер, это прмерно так же, как java-апплеты встраивать на страницы публичного сайта. в принципе, работает, но «здоровые» люди так как правило не делают, потому что слишком много минусов, и ограничений у получившегося решения.
Не стал бы делать таких громких заявлений, можно подождать и посмотреть пока язык еще более стабилизируется и обрастет необходимыми фреймворками. Глядишь, окажется что и биллинг вполне можно написать.
не обрастет. и не во фреймворках дело.
дело в прогнозируемости результата, в динамической типизации, и как следствие этого всего — низкая скорость рефакторинга.
все это — заложено by dezign.
кроме того, что бы js оброс такими фичами как аннотации в java и системой метаданных, что бы с объекты в базу данных запихивать с теми же фичами и удобством как это делается в jpa, или можно было тот же xml ваять, так же удобно и просто (с валидацией, кстати) как это делается с jaxb или simple xml framework… для этого js должен перестать быть джава скриптом.
оставьте эту роль догоняющего сишарпу ;) у него много чего появилось, но пока и он не тянет и половины только что перечисленного.
но согласитесь, до руби ещё далеко. тот ещё прекраснее.
и дело даже не в наличии у джаваскрипта хоть какой-то ecma-спеки.
как мне показывали, руби восхитителен вплоть до превращения класса в переменную типа стринг, с естественным «обломом» при попытке создать объект этого класса после такого финта ушами.
особенно это прекрасно, если этот финт ушами проделал падаван в левом подключенном модуле, при попытке дополнить класс «очень нужными мегафичами».
Напишите свой продукт один раз на JS и больше не понадобится переписывать его на очередной хайповый фреймворк по прихоти 23-летнего сеньера, который увлекся функциональщиной и теперь лоббирует очередной HaskellScript в продакшн.
напишите, ага) только есть пара-тройка особенностой иусловий для вашего проекта, что бы он стал успешным на какое то время на js:
1. он не должен иметь долгий жизненный цикл. потому что есть over 100500 причин, что он перестанет работать с заменой ядра движка в следующем поколении браузеров. никто не обещает обратной совместимости.
2. он должен быть маленьким. вы не сможете написать свой продукт, потому что верхний порог логики и сложности, который вы сможете контролировать в условиях динамической типизации не даст вам развернуться. я не говорю о таких «сложных» системах как курсовая, проект jQuery, или пошаговая ммо-игрушечка. я говорю о действительно вещах типа СЭД, учетные системы с историяеской отчетностью, хранилище данных, олап, и тд и т.п.
3. вам не стоит к нему возвращаться что бы рефакторить и добавлять в него фичи. потому что если вы создадите большого монстра, со ложной бизнес-логикой, то как только вы начнете рефакторить и модифицировать свой продукт (под влиянием времени, и изменния требований окружения) — вы поймете что «не успеваете». ни оттестировать, ни предсказать влияние ваших изменний. потому что прогнозировать влияние изменний в языке с динамической типизацией сложно. и typescript не панацея. потому что… где стандартна тайпскрипт и гарантия обратной совместимости? (см проблему 1).
а так, да, js, вполне прикольный, для маленьких здесь и сейчас задач. как прослойка скриптовапия компонентами, для задач, где где бизнес-логика примитивна, задачи прозрачные, а ответственность минмальна — самое то.
(не в конце концов, никто же не умрет, аэс не взорвется, поезда с рельс не сойдут, если ваш мега сайтик с оvер 8миллионов конекшенов просто подохнет, после обновлепия или какого иного чиха.
просто не надо думать что js может заменить, или тем более вытеснить джаву, c++ или ассемблер.
это глупо.
а так… хайп кончится, будет новая мода. visualbasic, delphi, php, python, ruby, javascript… что из этого продержалось на волне популярности долго?..
осмелюсь быть усыпанным минусами, но если под «контролировать» понимать «прогнозирование поведения программы», то имхо, к этому ближе всего java.
и это стоило очень больших больших усилий sun, а теперь стоит очень больших усилий ораклу.
и 100% обратная совместимость, и максимально возможная спека языка с требованиями к джава-машине с эталонным поведением.
именно. то что вы не сталкивалсь с этим, говорит только о том, что вы мелко плаваете. или о том, что любимый вами язык никто в здравом уме не применяет для серьезных задач.
вопрос с интерпрайзом не в мегатоннах байт и простых запросов, а в сложных и часто постоянно плавающих бизнес правилах.
всем плева-ть на миллион запросов в секунду. совершенно.
важно, что бы хотя бы один отработал за преемлемое время, сопоставимое хотя бы с часом.
потому что когда воодушевленные хайлоад-конференциями школьники приходят и делают систему на этих модных «производительных» технологиях, а потом вдруг оказывается, что их творение не способно построить справку об исполнении поручений первого лица города за неделю, и уже 6 часов это «хайлоад творение» пытается собрать «просто отчет» (просто потому, что правила по которым вы понимаете исполнено поручение или нет — уже это сложно рассчитываемый признак) а потом ещё надо посчитать на сколько дней оно было просрочено поручение (рабочие дни! не календарные! ) и планируемый срок окончания — вот тут начинается совершенно иная песня.
особенно после того, как совещанме мэра начинается _без_ основной бумажки об исполнительской дисциплине. потому что язык, способный перелапачивать мегатонны байт в секунду, и миллины рест запросов — не смог за 6 часов построить один-единственный отчет, на горизонте событий 1 неделя, попоручениямодного человека
У руби тоже типа с кроссплатформенностью все хорошо.
На бумаге. На словах.
Но различные реализации интерпретаторов руби, под разные платформы, в разных средах, на практике оказываются малосовместимы друг с другом, или ведут себя по разному (код ведет себя по разному) (тут я сошлюсь на мнение знакомого рубиста. бывшего рубиста.).
И у с/с++ тоже с кроссплатформенностью все хорошо. Ну как хорошо — только анси-си в примитивном виде можно переести между платформами. Но это не точно. Не факт, что после сборки взлетит (банально, int у всех разной длины.).
Самый яркий пример красот кросскомпиляции C++ кода — необходимость фазы метакомпиляции в Qt, когда универсальный кроссплатформенный Qt/C++ превращается в код код конкретный компилятор. мол в линуксе — gcc, но код, который gcc проглотит, не проглотит майкросовтовская вижуал студия (ну не понмает она шаблонные классы — generic, и это в 21м веке, году 2010 от Рождества Христова....) и тд. и тп.
Потому и спрашиваю — как в гоу с кроссплатформенностью на самом деле. Хочу ответ услышать с деталями.
* Как обеспечивается кроссплатформенность. Как решены проблемы присущие С/С++ коду при сборке на разных системах?
* Eсть ли (как у джавы, снова) процедура сертификации компилятора/интерпретатора на соответствие стандарту? (ибо как вы собираетесь кроссплатформенность соблюдать без наличия четкого стандарта).
* Сам стандарт на язык вообще есть и в каком виде? или «оно как в питоне» — это некая малоформального вида бумага, поддерживаемая автором и сообществом?(поправьте если ошибаюсь).
А если уж отсылаете в фак, то надо отсылать с выдачей ссылки, а не посылать в пустоту. Где ссылка? Вы предлагаете мне продираться сквозь тонны рекламной мишуры? Дайте ссылку на самый правильный фак, какой вы сами считаете есть. Вы эксперт по языку, а не я. Я потенциальный потребитель, который пока задает вопросы, и не будет тратить время на ваш язык, если вы не в состоянии ответить на эти вопросы.
Ибо кроме вас есть еще руби, питон, раст, хаскель, свифт, сишарп, ди, 1с,… и каждый кричит — все просто, все на поверхности, вот почитай фак/идеологию/роадмап/вижен/идею… да вы что, все, смеетесь?)))
Вы эксперт — вы и ответьте, пожалуйста на вопросы. Со ссылками. Заранее спасибо.
Да не вопрос, нет пула потоков — опишите как управляются горутины, как они исчерпывают ресурсы системы (и какие есть ресурсы вообще? память, процессорное время, потоки, ещё что то?) и как их лимитировать на сервере гоу, как не дать гоу серверу банально подохнуть с серфолтом (или аакой тип ошибок у вас там в гоу?) под потоком запросов?
Давайте по сути обсуждать, а не по форме?) я знаю что вам кажется все это чужеродным в отношении гоу ) да, я не понмаю «этом вашем гоу» — и я задаю вопросы в терминах, которые сейчас применяются в промышленных технологиях. В общепринятых тезнологиях. а Термин горутины — это специфиака. «Ваша специфика». Проведите параллели с промышленными терминами и объясните на пал цах как не дать гоу серверу вывалиться в нерабочее состояние при попытке перерасхода выделенных ресурсов? и как вообще ему выделять ресурсы?)
Вы о какой логике говорите? Логика бывает разного уровня.
Если о логике и поведении описанном в коде высокого уровня — то оно сохраняется.
Но то как это поведение будет отражено в машинные инструкции — и по какой логике они будут работать — это может как сильно отличатьcя как от ваши представлений, так и сильно разниться от компилятора к компилятору.
Более того, логика работы исходного кода и логика работы машинного кода — они обязаны быть разными. Но обязаны реализовывать одинаковое поведение.
Например, на уровне кодов процессора нет никакого ООП и наследования.
О какой одинаковости логики вы вообще можете говорить, если логика работы вашего исходного кода построена на ООП-понятиях?
Сохраняется поведение, но даже не всегда детали логики исходного кода.
Посмотрите мой ответ https://habrahabr.ru/post/334964/#comment_10352244
и скажите — оптимизирущие компиляторы — они какую логику меняют? и что они вообще меняют?
ну на другой вопрос про разную реализацию await- тоже хотелось бы услышать ответ. спасибо )
Если быть более точными — компилятор реализует поведение, описанное на языке высокого уровня, с использованием языка более низкого уровня.
А вот какая логика будет использована на этом низком уровне — на уровне машинного кода или байткода — это уже его личное дело, покуда он остается в границах ожидаемого поведения, описанного языком высокого уровня.
Вот возьмем оптимизирующий компилятор — если поведение не изменится, он может вообще выкинуть всю логику расчета внутри вашей функции, и сразу выдавать на выход константу. Если, конечно, он обнаружит, что вне зависимости от входных параметров всегда получается одно и то же число.
Он легко может начать не умножать или суммировать, а дергать сдвиги, или, скажем, развернет циклы, если посчитает что так будет лучше. У вас в исходном коде — «визуально-однопоточный» циклический код, а на уровне машинного кода — 4 линейных параллельно исполняющихся цепочки.
Или, что скорее всего происходит и смущает вас — превратит синхронный код с await, в лапшу последовательно вызываемых асинхронных функций, связанных callback-ами.
А другой компилятор, может легко сделать не коллбеки, а 3 потомка и семафоры. Ведь согласитесь, await можно легко «сделать на семаформах».
Поведение программы, в обоих будет одинаковое, а логика и структура работы машинного кода (или байт кода) — разная.
И вот в такой ситуации — когда у нас реализация одного поведения, может быть построена на разных принципах, разной логике — скажите — как классифицировать сам исходный код? — по структуре его поведения, или по структуре того, что получается на выходе компилятора?
Вы, зачем-то, уцепились за выход компилятора. Вы уверены что это правильно?
Исходно, как я помню, мы говорили именно о логике исходного кода, и о том, что именно «синхронный» код позволяет описывать многие вещи проще и быстрее, чем событийно-ориентированный, асинхронный подход, потроенный на обработчиках и call-back.
и так:
Исходный код с использвоанием await — синхронный.
Байт-код/машинный код может быть каким угодно. И это не отменяет синхронности исходного кода.
Или вот для аналогии ещё пример: если я написал синхронные обертки над асинхронными функциями с call-back — то та часть исходного кода, которая использует обертки — синхронная. Вне зависимости от того, что внутри обертки — асинхронные функции.
или вот ещё загадка:
У меня есть абстрактный класс с одной функцией waitForBytes() которая не должна отдавать управлениедо момента своего окончания. Далее, я реализовал интерфейс в 2-х потомках — в одном я использвал синхронной функции, а в другом — на синхронных функциях и на асинхронных callback.
Скажите — код который использует интерфейс — он синхронный или асинхронный? если думать о том, что лежит под функцией, а не над тем, как оно должно себя вести, то у вас возникает ситуация, что классификация участка исходного кода будет динамически меняться. Что есть бред.
Асинхронность (в случае локального, выполняющегося на одной машине кода) как правило говорит о том, что вы умеете реагировать на события/сообщения/уведомления от «того, что происходит независимо от вас» — когда что-то стороннее начинает вас уведомлять — и у вас как правило есть «обработчики»/«подписки»/«хуки»/«коллбеки»… — которые будут вызваны когда событие произойдет).
А если вы останавливаетесь на текущей инструкции, до тех пор пока не выполнится что то независимое от вас — это синхронный код.
Вы сами синхронищируетесь с чем-то — вне зависимости от того, на что вы смотрите или за чем вы следите.
завершение процесса — не стоит называть асинхронным событием.
Вот если бы ваш таск присылал вам в случайные моменты времени сообщения, и вы на них реагировали — это было бы асинхронным событием.
А так — это поведение, сходное с обычным «семафором».
Сравните вашу фразу с фразой "то, что после «вызова mуSemaphore.release(), выполнится только тогда, когда сосдений поток освободит семафор».
Но семафоры — это обычная синхронизация потоков, а ни какая ни «асинхронность».
И да, это, по логике/стилю работы работы — синхронный код.
а-синхронный код, в классическом, верном, понимании — это суть, событийно ориентированный код, который построен на колл-беках и/или обработчиках событий
примеры асинхронного апи: WinApi функции работы с последовательными портами, в которые вы передаете ссылку на функцию, которую надо вызывать, когда на вход поступят байтики. Qt-шные сигнал-слоты. Промисес в js (потому что вы передаете им функцию/ссылку на функцию)
не совсем верный вывод… могут, и есть, реализации, к которым само понятие «блокировка вызывающего потока» не применимо, а понятие «асинхронный вызов» — применимо.
я пытаюсь вывести вас на определение асинхронного вызова, которое не зависит от деталей реализации. тогда вы будете понимать почему ваш код, который вы написали — «построен по логике синхронных вызовов».
вот скажем, о каких потоках и блокировках, мы можем говорить, если мы попытаемся определить, скажем что такое синхроные и асинхронные вебсервисы?
или вот: поток может быть вообще прекращен (как тут кто то говорил про то, как работает await), или под каждую инструкцию или группу инструкций будет свой поток создаваться (почему бы и не создать такую машину для байткода? проанализировать зависимости и распараллелить для оптимизации на многоядерном проце?) — вариантов масса, и понятие «блокировка потока» вообще будет неприемлемо — все зависит от реализации. особено, если мы говорим не про машинный код, а про машины исполняюшие байткод.
вы просили "пример асинхронного вызова, который блокирует вызывающий поток" — это конечно бред, но вот вам пример «асинхронного», для которого понятие вызывающий поток вообще не применимо: асинхронный вебсервис.
или вот еще «немного путарицы» пример: вызов синхронного вебсервиса может быть реализован на вызывающей стороне по синхронной локиге построения кода, так и по асинхронной.
Блокировка потока (который thread) «как признак асинхронности» — это частный случай.
теперь про определение асинхронности: вот немного скорректированное определние асинхронного вызова, которое я давал выше:
и совершенно не важно что у вас тут: сишарп, джава, или взаимодействие между двумя хостами при RPC или вызов вебсервиса описанного в wsdl.
отодвиньтесь от деталей. вы зарылись в частные учебные определения, и забыли изначальную суть. более того, вы используете смешанные механизмы, которые используют или допускают и асинхронный вызов, и последующую синхронизацию, но заявляете чтт это «полностью асинхронный код». жто не верно.
в вашем примере ( в конце которогоо гордо заявляете «вот полностью а-синхронный код») — вы строите именно синхронный код, вызываете функции синхронно,… а потом заявляете что код «полностью асинхронный»… извините, но это… очень мягко говоря… не верно.
вы не переходите на следующие инструкции пока не выполните операции чтения из компорта. иначе вся логика работы кода разрушится.
при вызове функции через await, вы не перейдете на следующую строчку кода, пока функция не будет завершена — и именно поэтому ваш вызов синхронный, и потому код ваш — синхронный: он построен по логике синхронных вызовов. вне зависимости от того что происхолит внизу с потоками, асинхронными и не очень функциями — ваш вариант псевдо-исходника и логика его работы — синхронные, или повторяют мой код, полностью построенный на синхронной логике.
если бы вы объявляли для своих асинхроных функций callback-и, и каждое обращение ловили именно в них, то ваш код был бы асинхронным. суть — событийно ориентированным. аки как его любят js-ники, ратующие за однопоточность и событийно-ориентированность.
я предлагаю прекратить говорить сугубо частными терминами сишарпа (таски, async/await ) когда рассуждаете об асинхронности. вы топик видели?))) вы понимате что такое опредение — это как минимум слишком узкое понимание? тем более, вы используете механизмы которые не столько относятся к асинхронному/синхронному вызову, сколько к потокам и синхронизации потоков.
верно! если быть точнее асинхронный вызов запускает выполнение потока инструкций в параллели, а сам, не дожидаясь его кончания, отдает управлепие в точку вызова, где после этого продолжается исполнение инструкций с места вызова.
«асинхронный» именно вызов, а не сама функция. и оператор await — занимается именно тем, что позволяет изменить синхронность вызова у функции, у которой стоит директива асинхронного вызова по умолчанию.
т.е. он позволяет приостановить выполнение потока инструкций в текущей функции, пока не закончится выполнение вызываемой функции.
сужу по официальным докам майкрософта.
я бы рассматривал это как способ определения того, как вызывать функцию по умолчанию, и как изменить синхронность вызова.
идея таких директивы/оператора действительно интересная; выглядит удобно, позволяют не писать обертки. в джаве это желается несколько более громоздко.
но согласитесь, определение у функции директивы (?) «async», а потом вызов её с оператором await — это полностью соответсвует определению синхронного вызова: «выполнение инструкций в точке вызова, не продолжается пока не закончено выполнение инструкций в вызванной функции».
а если это соответвует синхронному вызову, то как же мы можем говорить про код, использующий await, что он асинхронный? он построен по логике синхронных вызовов. а то что где то там внутри есть асинхронные процедуры — это уже третье дело. исходник с await — синхронный.
Я, конечно, подозревал, что полное, безоглядочное погружение в идеологию и технологии мягкотелых вызывает… определенного рода… профессиональную деградацию…
Но то, что вы тут уже 5й пост устраиваете параолимпиаду по синхронным методам запуска асинхронных функции… и при этом заявляете что это «полностью асинхронный код»…
Я потрясен. «Такое» я вижу впервые.
Вы… в некотором роде, теперь, мой личный рекордсмен.
В отдельной, особой номинации. Для «тяжеловесов».
То, что вы тут язощеряетесь и демонстрируете «удобные и красивые методы» работы с асинхронными функциями, как раз доказывает, что далеко не везде асинхронность и событийно ориентированность — к месту. Потому что все что вы показываете — это как раз вариации на тему, как бы нам асинхронный вызов превратить в синхронный, и приостановть выполнение текущего потока инструкций (и поверьте всем глубоко плевать, блокируется при этом поток или освобождается, или начинается другой поток — это детали реализации. не важные по большому счету)
Да, эти методы позволяет не писать особых оберток, но это не делает ваш код «асинхронным».
То, что вы вызубрили костыли сишарпа — это конечно похвально, но даже то что вы показали, не поможет вам красиво и удобно, без лишних оберток работать с WinApi в котором вы должны «передать вниз» ссылку на callback функцию, которую надо вызвать, когда данные поступают.
Вы использовали выражение await, для того, что бы явно сделать синхронный вызов функции, которая заявлена как «асинронная», и говорите что взаимодействие стало асинхронным? вы уверены что не запутались?
Синхронный вызов — это когда исполнение приостанавливается в точке вызова.
Именно это вы и делаете, когда предлагаете использовать await.
А блокируется или приостанавливается при этом поток, какие потоки при этом вызываются, что используется внутри или не вызываются, что происходит внутри — это уже технические детали рализации.
Например похожие технические эффекты, (похожие на await) можно добиться в Java 'без всяких await' с использвоанием yeld() — он отдает ресурсы потока на другие задачи, не не разрушая контекст исполнения.
А «асинхронный» вызов, не приостанавливает выполнение кода в точке вызова в ожидании ответа, а сразу преходит к следующей инструкции.
нет))) не правильнее))
не будет а-синхронный интерфейс давать вам видеть нормально логику работы кода и отслеждивать диалог с принтером.
Мыслите не уровнем «stateless» механизма принял-отдел, а уровнем всей задачи, когда вам надо хранить состояние и (очень желательно) контекст исполнения.
Вот давайте по порядку на примере
Инициализация принтера — это порядка 20 команд, каждая и которых имеет свой ответ. и в зависимости от ответа вы ещё должны иногда задавать дополнительные команды в зависимости от того, о чем вам рассказал принтер. Например для этой прошивки надо ещё кодировку поменять, а тут — установить плотность другую.
Рассмотрим на примере псевдо c++ кода гипотетической функции инициализации принтеров определенной серии с использованием синхронных функций:
Функция waitForBytes() — синхронная. не отдает управление пока не получен минимум 2 байта, или не истек таймаут. Если получено больше чем ожидается — отдает весь полученный объем данных.
Вот теперь, перепишите этот маленький и простой кусочек кода «в асинхронной, неблокирующей логике». Вы сможете сделать его столько же простым, прозрачным и понятным, что бы он не вызывал проблем при отладке, и не приводил к желанию материться?
Поймите, тут как раз тот случай, когда асинхронная логика «ну не в вперласть» никаким боком.
От слова совсем.
Удобно и просто прозрачно когда один поток, который ведет диалог с принтером, и ждет ответ от него, с сохранением контекста исполнения и состояния. Потому что это позволяет просто и легко описывать сложную логику диалога с устройством.
Если вам сложно мыслить принтером и последовательным компортом, то представьте, что у вас сокет на удаленный хост — у вас кастомный протокол, и в процессе «рукопожатия» — вам надо запросить у него кучу подробнотей, и в зависимости от того, что он вам ответит — что то ему рассказать дополнительно, или не рассказать.
во первых… не в шарпах я работал. дело было в году 2006-м 2007 и сишарп тогда был… далеко не самым интересным, чем можно было заниматься. от слова совсем.
во вторых — я делал на с++ кроссплатформенную обертку над работой с компортами, и в виндовой части проекта я работал с WinAPI и использовал неблокирующее чтение с коллбеком. Потому что реализовать блокирующее чтение с таймаутом — … ну вот как-то не вышло. В линуховой части все вышло на ура, а вот c WinAPI — матов было много. А таймаут надо было иметь.
а потом туда же (через этот интерфейс) был пристыкован доступ к «виртуальному компорту» ( serial профиль USB-устройства — некоторые принтеры делают именно так)… и матов было примерно столько же.
Да и не про это разговор. разговор о том, что не все задачи можно и удобно решать в событийно-ориентированной логике. А работа с ком-портом — это только пример такого противоречия, когда низкоуровневый интерфейс — событийно-ориентированный, а вам надо делать синхронное взаимодействие, потому что иначе логика инициализации ии проверки состояния принтера усложняется во много крат — когда ты прежде чем послать задачу, проверяешь у него с десяток флагов и состояний, и при необходимости — ещё и настраиваешь режимы и подрежимы.
Нет, ездить на конфернцию не плохо.
Плохо терять критическое мышление в результате этой конференции)))
именно об этом пишет автор.
в который раз раз повторюсь: я был свидетелем безумия рубистов и пхпшников, которые запихивали свои «супертехнологии» в промышленные проекты ( со сложной бизнес-логикой, высокими требованиями к надежности, и большим объемом обратываемых в одном запросе данных, с высоким темпом изменений, в условиях большого объема кода и сложной логики) — не понимая где лежит граница применимости их технологий.
и я видел, что происходило с этими проектами через полгода, через год, через 2. ничего хорошего.
ведь, имхо, именно о потере критического мышления пишет автор во фразе «вирус откусывает ту часть мозга, которая помнит о многопоточности — она умирает не успев задать свои вопросы».
событийно ориентированный стиль разработки прекрасен.
но строго до тех пор, пока им не пытаются замень что то сугубо многопоточное или требующее синхронности.
скажите, вы когда либо писали код взаимодействия с промышленым принтером через rs-232? а я писал.
и в гробу я видел, извините за выражение, тех, кто написал «событийно ориентированные» классы, которыми я был вынужден пользоваться. потому что когда ты работаешь с принтером — тебе надо поддерживать его состояние и контекст, а проверять это всё каждый раз когда ты просыпаешься в «onByteRecieved()» — настолько усложныет код, что мне пришлось отдельно сидеть и писать «синхронные обертки» над асинхронным интерфейсом работы с ком-портом. потому что только синхронный интерфейс позволял мне сохранить простоту структуры кода и прозрачность логики. а обертка работала, только благодаря многопоточности.
вот такая сказка об идеализации однопоточности и событийности в реалиях жизни.
к чему я? к тому что сейчас очень много школоты, потеряв критичность мышления пихают js куда можно и куда нельзя. и этт плохо. об этом весь холивар.
несколько не правы, имхо. действительно здоровый человек знает ограничения и границы прменимости технологии. и использует js там где он пригоден, а java там, где java работает лучше всего, с# — там где ему место, а не убеждает тех директора что c#/java лучше или хуже js.
у каждой технологии — свои границы применимости. и, напрмер, имхо, пихать js-на сервер, это прмерно так же, как java-апплеты встраивать на страницы публичного сайта. в принципе, работает, но «здоровые» люди так как правило не делают, потому что слишком много минусов, и ограничений у получившегося решения.
не обрастет. и не во фреймворках дело.
дело в прогнозируемости результата, в динамической типизации, и как следствие этого всего — низкая скорость рефакторинга.
все это — заложено by dezign.
кроме того, что бы js оброс такими фичами как аннотации в java и системой метаданных, что бы с объекты в базу данных запихивать с теми же фичами и удобством как это делается в jpa, или можно было тот же xml ваять, так же удобно и просто (с валидацией, кстати) как это делается с jaxb или simple xml framework… для этого js должен перестать быть джава скриптом.
оставьте эту роль догоняющего сишарпу ;) у него много чего появилось, но пока и он не тянет и половины только что перечисленного.
и дело даже не в наличии у джаваскрипта хоть какой-то ecma-спеки.
как мне показывали, руби восхитителен вплоть до превращения класса в переменную типа стринг, с естественным «обломом» при попытке создать объект этого класса после такого финта ушами.
особенно это прекрасно, если этот финт ушами проделал падаван в левом подключенном модуле, при попытке дополнить класс «очень нужными мегафичами».
напишите, ага) только есть пара-тройка особенностой иусловий для вашего проекта, что бы он стал успешным на какое то время на js:
1. он не должен иметь долгий жизненный цикл. потому что есть over 100500 причин, что он перестанет работать с заменой ядра движка в следующем поколении браузеров. никто не обещает обратной совместимости.
2. он должен быть маленьким. вы не сможете написать свой продукт, потому что верхний порог логики и сложности, который вы сможете контролировать в условиях динамической типизации не даст вам развернуться. я не говорю о таких «сложных» системах как курсовая, проект jQuery, или пошаговая ммо-игрушечка. я говорю о действительно вещах типа СЭД, учетные системы с историяеской отчетностью, хранилище данных, олап, и тд и т.п.
3. вам не стоит к нему возвращаться что бы рефакторить и добавлять в него фичи. потому что если вы создадите большого монстра, со ложной бизнес-логикой, то как только вы начнете рефакторить и модифицировать свой продукт (под влиянием времени, и изменния требований окружения) — вы поймете что «не успеваете». ни оттестировать, ни предсказать влияние ваших изменний. потому что прогнозировать влияние изменний в языке с динамической типизацией сложно. и typescript не панацея. потому что… где стандартна тайпскрипт и гарантия обратной совместимости? (см проблему 1).
а так, да, js, вполне прикольный, для маленьких здесь и сейчас задач. как прослойка скриптовапия компонентами, для задач, где где бизнес-логика примитивна, задачи прозрачные, а ответственность минмальна — самое то.
(не в конце концов, никто же не умрет, аэс не взорвется, поезда с рельс не сойдут, если ваш мега сайтик с оvер 8миллионов конекшенов просто подохнет, после обновлепия или какого иного чиха.
просто не надо думать что js может заменить, или тем более вытеснить джаву, c++ или ассемблер.
это глупо.
а так… хайп кончится, будет новая мода. visualbasic, delphi, php, python, ruby, javascript… что из этого продержалось на волне популярности долго?..
и это стоило очень больших больших усилий sun, а теперь стоит очень больших усилий ораклу.
и 100% обратная совместимость, и максимально возможная спека языка с требованиями к джава-машине с эталонным поведением.
именно. то что вы не сталкивалсь с этим, говорит только о том, что вы мелко плаваете. или о том, что любимый вами язык никто в здравом уме не применяет для серьезных задач.
вопрос с интерпрайзом не в мегатоннах байт и простых запросов, а в сложных и часто постоянно плавающих бизнес правилах.
всем плева-ть на миллион запросов в секунду. совершенно.
важно, что бы хотя бы один отработал за преемлемое время, сопоставимое хотя бы с часом.
потому что когда воодушевленные хайлоад-конференциями школьники приходят и делают систему на этих модных «производительных» технологиях, а потом вдруг оказывается, что их творение не способно построить справку об исполнении поручений первого лица города за неделю, и уже 6 часов это «хайлоад творение» пытается собрать «просто отчет» (просто потому, что правила по которым вы понимаете исполнено поручение или нет — уже это сложно рассчитываемый признак) а потом ещё надо посчитать на сколько дней оно было просрочено поручение (рабочие дни! не календарные! ) и планируемый срок окончания — вот тут начинается совершенно иная песня.
особенно после того, как совещанме мэра начинается _без_ основной бумажки об исполнительской дисциплине. потому что язык, способный перелапачивать мегатонны байт в секунду, и миллины рест запросов — не смог за 6 часов построить один-единственный отчет, на горизонте событий 1 неделя, попоручениямодного человека
На бумаге. На словах.
Но различные реализации интерпретаторов руби, под разные платформы, в разных средах, на практике оказываются малосовместимы друг с другом, или ведут себя по разному (код ведет себя по разному) (тут я сошлюсь на мнение знакомого рубиста. бывшего рубиста.).
И у с/с++ тоже с кроссплатформенностью все хорошо. Ну как хорошо — только анси-си в примитивном виде можно переести между платформами. Но это не точно. Не факт, что после сборки взлетит (банально, int у всех разной длины.).
Самый яркий пример красот кросскомпиляции C++ кода — необходимость фазы метакомпиляции в Qt, когда универсальный кроссплатформенный Qt/C++ превращается в код код конкретный компилятор. мол в линуксе — gcc, но код, который gcc проглотит, не проглотит майкросовтовская вижуал студия (ну не понмает она шаблонные классы — generic, и это в 21м веке, году 2010 от Рождества Христова....) и тд. и тп.
Потому и спрашиваю — как в гоу с кроссплатформенностью на самом деле. Хочу ответ услышать с деталями.
* Как обеспечивается кроссплатформенность. Как решены проблемы присущие С/С++ коду при сборке на разных системах?
* Eсть ли (как у джавы, снова) процедура сертификации компилятора/интерпретатора на соответствие стандарту? (ибо как вы собираетесь кроссплатформенность соблюдать без наличия четкого стандарта).
* Сам стандарт на язык вообще есть и в каком виде? или «оно как в питоне» — это некая малоформального вида бумага, поддерживаемая автором и сообществом?(поправьте если ошибаюсь).
А если уж отсылаете в фак, то надо отсылать с выдачей ссылки, а не посылать в пустоту. Где ссылка? Вы предлагаете мне продираться сквозь тонны рекламной мишуры? Дайте ссылку на самый правильный фак, какой вы сами считаете есть. Вы эксперт по языку, а не я. Я потенциальный потребитель, который пока задает вопросы, и не будет тратить время на ваш язык, если вы не в состоянии ответить на эти вопросы.
Ибо кроме вас есть еще руби, питон, раст, хаскель, свифт, сишарп, ди, 1с,… и каждый кричит — все просто, все на поверхности, вот почитай фак/идеологию/роадмап/вижен/идею… да вы что, все, смеетесь?)))
Вы эксперт — вы и ответьте, пожалуйста на вопросы. Со ссылками. Заранее спасибо.
Давайте по сути обсуждать, а не по форме?) я знаю что вам кажется все это чужеродным в отношении гоу ) да, я не понмаю «этом вашем гоу» — и я задаю вопросы в терминах, которые сейчас применяются в промышленных технологиях. В общепринятых тезнологиях. а Термин горутины — это специфиака. «Ваша специфика». Проведите параллели с промышленными терминами и объясните на пал цах как не дать гоу серверу вывалиться в нерабочее состояние при попытке перерасхода выделенных ресурсов? и как вообще ему выделять ресурсы?)