LINUX.ORG.RU

node.js-like vs continuations


1

2

Погружаюсь в node.js, и внезапно понимаю, что все эти коллбеки и неестественный нелинейный стиль написания программы можно заменить на обычный простой код с поддержкой continuations. Грубо говоря - набрели на блокирующий вызов, свернули стек со всеми переменными, пошли выполнять следующее событие. Вернулся ответ на блокирующий вызов, вытащили из очереди соответствующее событие, раскрыли стек, пошли дальше выполнять. Стиль написания программы абсолютно линейный (понятно, что при желании можно и через коллбеки что-то делать, если надо); плюшки (не нужно плодить треды на каждый запрос) сохраняем.

Собственно, полагаю, что это всё в каком-нибудь racket-е уже есть, но как-то немодно. Про нод жс в каждом туалете говорят.

В чем причина? continuations непригодны для реального мира? Нет языка с джавоподобным синтаксисом с нормальной поддержкой продолжений?

Может через 5 лет в V8 запилят поддержку продолжений и весь прогрессивный мир будет в шоке от того, насколько проще можно писать всю эту асинхронную муть?

★★★★★
Ответ на: комментарий от nerdogeek

nginx - вещь в себе (и тоже не с пустой багзиллой), а вот mencoder или libav - штуки вполне себе посторонние, и в них тоже бывают баги. fault-tolerance проекта должен быть. Кроме того, еще раз - 10к - что-то нереальное, 100 - уже ближе, а на таком кол-ве оверхед практически незаметен.

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

Ничего не понял из обсуждения. Мы сейчас обсуждаем перекодировку видео внутри веб-сервера? WUT!?! Или я что-то не понял?

vertexua ★★★★★
()

Кто-то только что изобрел промисы и фиберы. А мужики-то и не знали...

yield появится с 0.12, его в v8 недавно добавили.

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

Ну а повсеместно не используют - потому что проект молодой, нет единых стандартов. Будут лишние сложности со стыковкой внешних модулей. Исторически сложилось, короче. Может когда и изменится волевым решением.

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

суть - «node.js говно, т.к. не умеет многопоточность, и нельзя перекодировать видео (к примеру) в потоках серверного процесса, а параллелизм процессами имеет очень большой оверхед»

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

OSHI, пусть будет проклят тот, кто делает длительные вычисления а) в потоке event driven веб-сервера б) да и вообще синхронно с ожиданием пользователя.

Зачем вообще декодировать что-то в ответ на HTTP запрос?

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

нет, об этом речь не идет, не фантазируй.

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

Это да, но по полному списку сложнее искать готовые пакеты.

В принципе, для любого человека, начинающего осваивать ноду, свойственно первые 2 месяца сочинять гениальные прорывные решения. Надо переболеть :) . Я тоже первое время с горящим взором всякую хрень творил.

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

Ох уж эти эксперты. Во-первых, это тупо, использовать одновременно и колбеки и эксепшены. Во-вторых, для любителей эксепшенов в ноде есть домены, еще с 0.8 версии.

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

В Python есть delimited continuations, но в существующих версиях нет удобной возможности их комбинировать между собой

А в чем неудобство и что именно yield from сделает удобнее?

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

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

На самом деле, ему предложили полный список того, что переизобрели предлагавшие, а сам ТС без всяких претензий на изобретение упомянул continuations в заголовке.

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

Ну пытался перенести опыт с других языков 1:1, не учитывая местной специфики, и думал что самый умный :)

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

Корявая организация кода, из-за того, что мозгу сложно сразу переключиться на колбечный стиль. Плюс собственные лисапеды, вместо использования готовых библиотек. В частности, попытка писать на промисах там, где это совершенно не нужно. Еще вот sprockets c рубей притащили (mincer) - до сих пор не знаю, стоил ли он тех усилий.

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

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

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

А в чем неудобство и что именно yield from сделает удобнее?

В текущей версии нельзя сделать yield из уже существующего генератора, его надо «раскручивать» циклом вручную. А yield from может из одного генератора включить в pipeline другой без извращений

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

yield from может из одного генератора включить в pipeline другой без извращений

Насколько я понимаю, конвейер из генераторов пишется в десяток строк.

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

Насколько я понимаю, конвейер из генераторов пишется в десяток строк.

Да. Только потом эти 10 строк придется везде копипастить, т.к функцией его сделать нельзя, а макросов нету.

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

Насколько я понимаю, конвейер из генераторов пишется в десяток строк.

Да. Только потом эти 10 строк придется везде копипастить, т.к функцией его сделать нельзя

Хм. Чем не подходит такая функция?

def pipeline(glst):
  def prime(x):
    if isinstance(x, FunctionType):
      pass
    elif isinstance(x, GeneratorType):
      g.next()
  def run(x, v):
    if isinstance(x, FunctionType):
      if x.func_code.co_argcount > 1 and isinstance(v, tuple):
        return x(*v)
      else:
        return x(v)
    elif isinstance(x, GeneratorType):
      v = g.send(v)
      g.next()
      return v
    else:
      assert False
  hd, tl = glst[0], glst[1:]
  assert isinstance(hd, GeneratorType)
  for g in tl:
    prime(g)
  while True:
    v = hd.next()
    for g in tl:
      v = run(g, v)
    yield v

Умеет сшивать функции и генераторы; если надо сшивать только генераторы, будет короче.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от Vit

Каким образом домены спасают от утечки ресурсов?! Мне действительно интересно, я сколько в них не смотрел, всё фигу вижу. Второе - использовать эксепшены может и плохо использовать, но из стандарта их уже не выпилить, так что так или иначе с ними приходится жить, или есть какой-то образ запускать v8 чтобы он не кидал эксепшены?

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

А ну это решение не со стороны генератора (как yield from), а со стороны того кто им пользуется. Нормально новерное, хотя будут определенные проблемы если окажется что не все внутренние генераторы надо разматывать.

Почитай http://www.python.org/dev/peps/pep-0380/, так все хорошо описано

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

Почитай http://www.python.org/dev/peps/pep-0380/, так все хорошо описано

Я читал. По-моему, там не об объединении генераторов в конвейеры:

«The rationale behind most of the semantics presented above stems from the desire to be able to refactor generator code. It should be possible to take an section of code containing one or more yield expressions, move it into a separate function (using the usual techniques to deal with references to variables in the surrounding scope, etc.)».

Впрочем, я далек от веб-специфики.

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

Грубо говоря, домены - это обертка, которая обеспечивает правильное протаскивание эксепшенов и стектрейса через колбеки. И освобождение вложенных замыканий. Как это делается - без понятия, код не смотрел.

Насчет того, что эксепшены случаются - в грамотно написаных асинхронных функциях их просто не кидают. Или код локально в try/catch оборачивают, выливая результат в callback.

В очень грубом приближении, эксепшены для синхронного кода, потому что он может вернуть только 1 параметр (результат). А при колбеках стандартная сигнатура это function(err, data). То есть эксепшены использовать можно, но в большинстве случаев это выглядит более чем странно.

Vit ★★★★★
()
Последнее исправление: Vit (всего исправлений: 2)
Ответ на: комментарий от maxcom

What’s New In Python 3.3

...

New syntax features:

New yield from expression for generator delegation.

Вероятно, оно уже есть?

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

Где написано про правильное освобождение вложенных замыканий? Я вот в упор не вижу. Насколько я знаю, в js, на данный момент, такое сделать в принципе невозможно. Насчет грамотно написанных асинхронных функций не знаю, но в том же модуле fs там полно «неправильно написанных» асинхронных функций(уверен и в остальных модулях дела обстоят не лучше, просто мне именно этот попался)

Так что, быть может и удастся написать свои «правильные» обёртки над нативными функциями, чтобы не использовать то что уже есть, но не уверен что оно того стоит.

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

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

Это какая-то фигня. Если бросать исключение в слотах, то Qt вполне пишет в чём проблема и как решить.

И никакого противоречивого состояния не будет (при нормальных условиях). Ну а если постараться, то и просто в своём коде можно такого противоречивого состояния добиться. И даже без исключений...

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

Ну я практик, а не теоретик. У меня нода на продакшене месяцами работает, без утечек. Если вам нужна помощь, как можно/нужно делать на ноде, чтобы работало - всегда пожалуйста. А в теориях не силён, тут вам от меня будет мало толку.

Доменами не пользуюсь, мне и без них хорошо.

Насчет fs, который вы смотрели - там эксепшены кидают только синхронные функции. В асинхронных эксепшенов нет.

Vit ★★★★★
()
Последнее исправление: Vit (всего исправлений: 1)
Ответ на: комментарий от Vit

Да нет, я на данный момент пользуюсь другими технологиями, просто стараюсь следить за тем что происходит, малоли)

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

Про то что асинхронные функции в fs никогда не кидают эксепшнов это тоже не совсем верно. Не хочу спорить на эту тему, просто приведу пример. Вот есть у нас прекрасная асинхронная функция fs.write которая использует assertEncoding, которая в свою очередь в определённых случаях кидает эксепшены.

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

Исключения там естественно кидаются. Если в программе явный баг и продолжать выполнение нет смысла. Например опечатка в названии кодировки. Если опечататься в названии функции, тоже вылетит исключение. В треде речь идет об ошибках, которые возникают из-за внешних факторов и на которые программист повлиять не может. Например баба Маша, выдернувшая сервер БД из сети.

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

Почему это из-за опечатки в названии кодировки продолжение работы не возможно? Почему не возможен вариант что это пользовательский ввод, и если он не корректен, то поймать исключение и пойти другим путём?

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

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

[code]
var functionName = readUserInput();
myObject[functionName]();
[/code]

Видимо в этом случае разработчики посчитали, что обычно в качестве кодировки будет указываться ASCII или UTF-8 как константная строка и проще и быстрее отлавливать ошибки как можно раньше, а кодировка, как ввод пользователя - более редкий случай и на такой случай разработчик может сам, перед вызовом нужной функции, проверить эту кодировку. Или не продумали этот момент, такое тоже может быть.

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

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

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

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

Для выявления случаев, когда кидается эксепшен, есть стандартная методика - вешается логер на глобальный эвент 'uncaughtException'. Потом по логу быстро ищем косячный код и чиним. После этого память не течет, проверено.

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

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

Это всё понятно. И про то что недороботки/ошибки в ПО тоже могут(будут) встречаться это тоже естесственно. Но речь шла о том что нельзя смешивать стиль написания построеный на колбеках с использованием эксепшнов, но сделать это в данном случае не удаётся. В итоге получается что всё же оно там понамешано, и вот они утечки, и вот они выстрелы в ногу. По крайней мере именно так это видится мне.

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

В примере, который вы привели, assert сидит на legacy коде. Для новых сигнатур его убрали. Угадайте сами почему.

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

Утечка памяти меня интересует не меньше чем утечка файловых дескриторов, или каких-то внутренних ресурсов, которые может быть не так просто отследить. Да и 'uncaughtException' может не отловиться, если «плохое» исключение кто-то да ловит, но при этом утекают ресурсы.

Возможно всё так и есть, и мне это только кажется, что всё в ноде плохо, но я еще ни для одной другой платформы не видел столько всяких дополнительных утилит и «мониторов», которые бы следили за инстансами нод и перезапускали их, если что-то «пойдёт не так». Быть может, даже и это выход, серъёзно, почему нет. Пускай ресурсы и утекают, если это можно ненакладно починить своевременным перезапуском нод, тогда они освободятся системой, и всё будет здорово. Но почему-то меня такой подход отталкивает.

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

Больше интересует, почему он там появился. И я еще раз говорю, не хочу рассматривать какой-то один конкретный пример, я его привёл только чтобы показать что не всё так здорово в тех кто говорит «просто не используй исключения»...

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

Думаю, он там появился, потому что это было давно, и на 0.4 ноде в голове у разработчиков не было порядка.

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

Ну в таком случае останусь при своём мнении еще хотяб на какое-то время, пока не вычистят то, что наделали раньше. А там посмотрю снова. Спасибо за пояснения.

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

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

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

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

Ну нода среди прочего, позиционируется как способ быстро начать разрабатывать сервер-сайд приложения со знанием одного лишь javascript. А тут оказывается, что надо еще много всяких нюансов освоить и понять чтобы научиться делать что-то стоящее. В итоге опять же вопрос - стоит ли оно того? В чем тогда профитность?

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

А вы меньше слушайте всяких балаболов, которые вещают про волшебные решения.

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

У меня нода была выбрана в основном из любопытства. Ну еще потому что хотелось рендерить шаблоны и на сервере и на клиенте. Стоило мне это любопытство немало - пришлось тратить время/деньги на портирование библиотек, которых 2 года назад не было, или были фиговыми (парсер ямла, парсер командной строки, генератор документации, менеджер ассетов). Если сейчас начинать - будет попроще.

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

Он есть, но не тот, что рекламируется всякими фанбоями. И не факт, что он нужен именно в вашем случае. Просто незачем лелеять завышенные ожидания, что любая кухарка с джикваери станет на ноде джидаем.

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

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

Ну я так понял код для ноды выходит местами специфичным и использовать один код и на сервере и на клиенте можно, но тогда ограничения ноды автоматически накладываются на код, который будет использоваться на клиенте. Выходит опять таки сомнительный профит)

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

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

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