Как стать автором
Обновить

Комментарии 349

> Лучшая поддержка работы со временем и датой.
> Стандартная библиотека Python даже с UTC не позволяет работать.
Вам больше нечего добавить по этому поводу? :) Pytz — стандарт де-факто, который по разумным соображениям не входит в дистрибутив самого питона, но в легкую ставится отдельно.
Как уже говорилось, я не рассматриваю сторонние библиотеки. В общем случае на компьютере, где мы используем скрипты, может не стоять ничего кроме стандартной поставки, а установка сторонних библиотек может быть затруднительна — конфликты, sudo и прочее.
Не очень удачная постановка задачи, скажем прямо не для оптимального выбора языка. Лучше так — а насколько удобно в {язык} поставить все то, чего вы тут понаписали недостающего.
для этого есть virtualenv
#!/usr/bin/env python
import datetime
datetime.datetime.utcnow()

Вы просто UTC не умеете готовить :)
А где все. Где холивары.
Все опасливо смотрят на карму и не рискуют.
Нет. Просто холивары на некоторые темы изжили себя. Вот и всё.
Это так кажется, всегда есть свежая кровь, готовая бурлить и извергать.
НЛО прилетело и опубликовало эту надпись здесь
Зато когда в erlang пишут — наши процессы это не те процессы которые ОС, а полностью контролируются виртуальной машиной erlang — это ого-го :)
Наши процессы — самые процессные процессы в мире!
ОС работает в режиме ядра, а пользовательскому приложению туда хода нет, поэтому программная эмуляция параллелизма без использования потоков ОС всегда будет сложнее и медленнее.
НЛО прилетело и опубликовало эту надпись здесь
Нет никакой магии, просто такова архитектура современной связки компьютер-ОС.

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

Собственно поэтому и Ruby так же пошли по этому пути в новой версии.
Вопрос не в качестве реализации, а в том что будет, когда из такого «переключаемого языком потока» вызов пойдет наружу, в функции операционной системы и сторонних библиотек. Если потоки зеленые (переключаемые самим языком) — то пока такой вызов не отработает, остальные потоки будут стоять и ничего не делать. В этом проблема, а не в том какой там слайс и как хорошо они переключаются :).
НЛО прилетело и опубликовало эту надпись здесь
Нет, я хочу сказать что это архитектурные отличия green threads от native threads. Велосипед не едет в гору, если не срктить педали, не потому что он криво реализован — а из-за арихтектурных отличий от мотоцикла.
НЛО прилетело и опубликовало эту надпись здесь
велосипед не предназначен для полётов, у него нет крыльев, а вы хотите, что бы он летал


По-моему вы меня с кем-то путаете ^_^".
НЛО прилетело и опубликовало эту надпись здесь
Вот вам и холивар :)
Всё же кто сильнее — Сабзиро или Скорпион?
Саб-зира! Но на картинке ни одного из них нет.
Ermac и Reptile.
Только наоборот. Рептилия и Ермак.
НЛО прилетело и опубликовало эту надпись здесь
А кто бадминтонист
Смоук, однозначно.
А МНЕ ПХП НРАВИТСЯ! ТОЛЬКО ПХП! ТОЛЬКО ХАРДКОР!
раби-раби-раби-раби!
Мой змий проглотит твой раби.
Мой верблюд растопчет твой змий.
рАби ?! руби! Да с какого ***, простите раби? Го то гоогле транслате
… флейм? Добро пожаловать в комменты.

А еще вам пора на курсы по повышению троллеустойчивости.
Проверочное слово — study.
Вам бы тоже на вышеуказанные курсы сходить не помешало, мне кажется.
Возможно, из-за того, что study != studdy
ойойой!
а можно, пожалуйста, ссылочку на полный список правил орфографии английского языка?
а то я «worcester» прочитать не могу.
ой-ой-ой!
не, я пас. На сегодня хватит.
Вустер читается оно.
Мне было интересно, какое «проверочное слово» придумает stolen
Проверочное слово:
— или рубин, если мы русифицируем название
— или google -> define:ruby, которое читается, как, сюрприз, /ruːbi/ (руби)

ЗЫ. Прежде, чем посылать людей на «проверочные» слова, советую ознакомится с этой ссылкой, если у вас существует уверенность, что в английском слова, которые пишутся похоже, читаются похоже
Ну неужели вы думаете, что я не знаю, как на самом деле читается слово ruby?
В холиварном топике очень уместно злить рубистов проверенными годами методами, вы не находите?
> Ну неужели вы думаете, что я не знаю, как на самом деле читается слово ruby?

Я на Хабре уже и не знаю, что думать :)
Здравствуйте. А можно глупый вопрос, при чём тут английский язык в принципе? Руби вроде японцем изобретён, а то, что название интерпретатора латинскими буквами записывается, вроде ни к чему никого не обязывает.
Название-то на английском.
Из чего это следует? Название это просто сочетание латинских букв. Латинские буквы следует читать по правилам русского прочтения латиницы, то есть «u» как «у».
en.wikipedia.org/wiki/Ruby_(programming_language)#Choice_of_the_name_.22Ruby.22

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

А уж чтение таких связочек в инглише и подавно. просто го то транслате
Реквестирую транскрипцию этого слова.
Только не «раби», а "ребе". :D
ТВОЙ ПЭХЕПЭ АЦТОЙ! ТОЛЬКО ЖДЖАВЫ!
Flawless Victory!
У меня еще больше заболела голова…
в OSX начиная с 10.6 он не работает для поставляемого с системой Ruby и нужно его перекомпилировать, что в целом не очень просто

rvm install 1.9.3

У Ruby сейчас активно идет переход с несовместимых веток 1.8 на 1.9 — довольно болезненный, мучительный и порождающий косяки.

Ничего подобного. Боль вызывает переход с rails 2.3.* на 3.*, и то по причине изменившегося API, а не изменений в corelib Ruby.
Как уже говорилось, разработка веб проектов не является для меня профильной, поэтому я рассматриваю больше со стороны автоматизации, server side, утилит. От рельсов далек. А вот переход с 1.8 на 1.9 лично меня задел довольно сильно — начиная от cassandra и заканчивая SOAP.
В середине первого абзаца и написано
> сравнение web фреймворков, сред разработки и доступных библиотек не включены
но это пролетает мимо глаз. Буду очень благодарен, если отметите отрывок полужирным или иным способом.
Выделил жирным.
Почему-то тишина про то, какую боль вызывает переход на 3-ю версию питона.
А никто не переходит, вот и боли нет. Ну не считая несчастных авторов библиотек которые выплескивают яд по этому поводу в твиттер.
Джанго скоро перейдёт и сразу попрёт тема.
Неплохая статья описывающая некоторые плюсы и минусы языков. Только ребят, не надо устраивать холивар на эту тему, в каждом языке есть свои плюсы и минусы, автор четко описал различия.
А его, кажется, не будет. По моему, все устали от них уже.
Мне нравятся оба, но ни одним из них я не пользуюсь :)
Автор лажанулся на самом главном — ограничиваться корелиб неудачная идея.
Если я не буду ограничиваться corelib — то статья лопнет, как та корова. Да и не думаю, что у меня хватит компетенции сравнить основные библиотеки по актуальным направлениям. Слишком большой объем работ, слишком много направлений. Для веба есть хорошие сравнения, ИМХО этого в первом приближении достаточно.
А ограничиваясь corelib вы не достигаете главного — корректного сравнения и определения удачных ниш.

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

И потому, у меня редкий опыт — я в течении нескольких лет довольно активно пишу и на питоне, и на руби. Исследовательский отдел и все такое. Могу рассказать о косяках из первых рук :).
Так рассказывайте. :)
Основное рассказал в статье. Дополнительно рассказываю в комментариях по мере задавания вопросов. Вы спрашивайте, спрашивайте. Вот уже absolute imports в питоне обсудил, groups() в питоне. Сплошной профит и повышение квалификации :).
Было бы интересно еще почитать такое же сравнение с Node.js (Node.coffee)
Одни минусы бы были, стандартная библиотека же скудная :)
какая стандартная библиотека?
Что лучше модем или интернет? А как вы предлагаете сравнивать язык с приложением? 0_о
Подождите-ка, здесь не только язык сравнивают, а платформу. Вот и интересно такое же сравнение с javascritp (и coffeescript) в контексте наличия документации, встроенных модулей и синтаксических конструкций, их удобства и прочего.
Оба хорошы. Но я их не использую.
Странно, мне всегда казалось, что у руби должно быть меньше строк кода чем в python, а в этой инфографике это не так. Надо пойти первоисточник попинать.
Лично меня удивило то, что предложений о работе для знающих питон нет даже в первой десятке. Наверное, Ruby более популярен в вебе из-за Ruby on Rails, а они смотрели в основном вакансии, связанные с вебом…
Мейнстрим, как никак.
Вы приезжайте к нам на Украину и в открытую заявите — я Senior Python Developer, удивитесь.
В инфографике присутствует functional php.
Скажите кто-нибудь — что это?
Видимо, вы имеете в виду место, где сравнивается быстродействие при использовании ОО и функционального подхода. Я не знаю, что авторы инфографики подразумевают под функциональным подходом, но на PHP >= 5.3 можно относительно удобно писать в функциональном стиле. Если интересно, можно начать читать отсюда.
Вот это новость!
php становится взрослым.

хотя, с другой стороны, там и пространства имён есть, и кассы, и исключения.
а толку-то…
Вот спасибо, давно думал попробовать руби раз на нем столько именитого крутится… теперь видно что смысла 0. но фреймворк вокруг него видимо накручен удобный, раз он еще не умер
но все равно, лучше всех — lua! :)
Странные выводы. Если заниматься, например, сайтостроением, то Ruby (on Rails) — конфетка. Для десктопа не пробовал, не скажу.
Для десктопа… Кому-то нравится, кому-то нет… Те же Standalone приложения пишутся легко. Куча гуев на выбор. В стандартную поставку, например, Tk входит. Я писал уже как-то о создании приложения с использованием Тк. Можете в профиле посмотреть.
А как с Qt? Когда я пробовал покрутить qt биндинги их скорее не было, чем были. :(
gem install qtbindings
Для сайтостроения и Django — конфетка :) Так что тут, как уже говорилось, вопрос слишком холиварный :)
Не спорю. Но это не преуменьшает полезности Ruby и уж точно не сводит толк от его изучения к 0.
десктоп не нужен
НЛО прилетело и опубликовало эту надпись здесь
На руби не найти ни одной нормальной библиотеки для научной работы, чтобы делать какие-то вычисления и выводить графики, а в Python есть SciPy.
Напиши)
Была такая мысль, но руки не доходят :) По сути надо прикрутить NumPy, который написан на Фортране и сделать хороший интерфейс для вывода графиков.
Для вывода графиков в руби, можно использовать всё тот же gnuplot, который запилен в качестве гема. Очень удобно ;)
SciRuby есть. Альфа, но все же.
Это хорошо, что такие работы идут. К сожалению мэйнтейнеры не очень стабильные и последние коммиты 4 месяца назад.
Это еще ладно. FoxRuby после двухлетнего молчания ожил, а вы говорите.
Я вот никогда не понимал желания использовать Python или Ruby для научных расчётов. Есть же Mapple, Matlab и другие специализированные инструменты для этих целей.
В конце концов язык программирования — это лишь средство… и знание Python/Ruby — вовсе не повод пытаться заниматься научными расчётами с их помощью
Maple и Matlab, вообще говоря, другого типа инструменты. Например я видел программы написанные на Python для таких серьёзных расчётов как квантовая химия, однако их нельзя написать на Maple и Matlab. То есть возможно и получится написать, но работать это будет медленно и только на небольших примерах. Я уж не говорю о том, что они стоят денег и очень даже приличных.
Подтверждаю. Коллега с нейросетями долго специализированным инструментом мучился — тот матрицы от миллиона элементров грузил по десять минут и «специализированный» язык был очень сильно урезан — даже корректно распарсить входные файлы не получалось. Перешел на pybrain — все работает мгновенно и бесплатная интеграция со всем что движется, начиная от произвольного формата входных данных и заканчивая построением графиков и таблиц в пару строк кода.
Если вас не пугают доллары, собаки и проценты в именах переменных — пишите на перле :-)
Наверняка, на CPAN уже лежит модуль для нужных вычислений.
Для научной работы есть биндинги к GSL, или вы не об этом?
Про кодировку файлов в питоне: docs.python.org/library/stdtypes.html#file.encoding

Переход на 3.x не выглядит столь уж отдалённой перспективой. Примерно половина, если не больше, распространённых библиотек сейчас уже поддерживают 3.x.
еще codecs.open есть с незапамятных времен в стандартной библиотеке:

import codecs

with codecs.open('my_file.txt', encoding='utf8') as f:
    for line in f:
        print line


а в 3ке можно просто

with open('my_file.txt', encoding='utf8') as f:
    for line in f:
        print(line)

НЛО прилетело и опубликовало эту надпись здесь
Незачем.

За деньги.
Мне одному кажется, что большинство описанных автором преимуществ и недостатков не являются преимуществами и недостатками?
Ну а как тогда сравнивать? Как сейчас модно — «В питоне декораторы и list comprehensions, в Ruby — блоки и DSL»? Это неинформативно. Я постарался собрать те вещи, которые лично мне при каждодневном использовании показались удобными / неудобными. А так как в общей сложности я занимаюсь разработкой уже более пятнадцати лет, то взгляд хотя и субъективный — но профессиональный :).
На мой взгляд принципиальных отличий между руби и питоном нет. Языки примерно одного плана, каждый со своими преимуществами и недостатками. И эти преимущества и недостатки, как мне кажется, не могут быть определяющими при выборе того, или иного языка.

Языки не важны, важны задачи, точнее говоря важен контекст в котором приходится эти задачи решать. Если нужно сделать десктопное приложение, то более выгоден питон, например за счет наличия указанных выше биндингов с Qt. Если веб-приложение, то возможно руби т.к. там есть рельсы, которые гораздо удобнее всего, что есть в мире питона (мое оценочное мнение:)). В контексте других задач будут, наверное, другие определяющие факторы.
>Возможность включать модули по относительному пути. Python технически это может, но большим
>количеством кода и с рядом неприятных спецэффектов.

from ..models import Page

>Лучшая поддержка работы со временем и датой. Стандартная библиотека Python даже с UTC не
>позволяет работать.

Стандратные либы (time и datetime) позволяют работать с UTC, и мне кажутся очень удобными. В чем по вашему заключется неудобство?
Неудобство заключается в том, что автор не шарит)
Ну вот, считаем что время на написание статьи себя окупило — я не знал про «from __future__ import absolute_import». Но тут надо посмотреть не убьет ли это чужие модули при активном использовании.

По поводу стандартной библиотеки и UTC. В Ruby я могу создать объект типа «время» вида «13:00 +4 UTC». И этот объект будет корректно работать с любыми другими объектами типа «время». В Python два типа объектов — «время с timezone» и «время без timezone» — их нельзя сравнивать. Более подробно все проблемы описаны вот тут: asvetlov.blogspot.com/2011/02/date-and-time.html
> Но тут надо посмотреть не убьет ли это чужие модули при активном использовании.
Это не убъет чужие модули, потому что «from __future__ import absolute_import» вы будете делать в своем модуле.
Да не надо это. Вы можете использовать относительные пути и без ``from __future__ import absolute_import``. А вот после этого импорта импортнуть файл в локальной директории без ``.`` уже не сможете, что иногда полезно.

Таймзоны, хм, ну там и написано все четко — те же темы, что и с юникодом.
Пункт два — а чего pytz не в стандартной библиотеке? А вы посмотрите когда очередная административная задница начинает выдумывать как чем-нибудь отметиться в истории, так все версии python обновлять что-ли сразу?
А вы посмотрите когда очередная административная задница начинает выдумывать как чем-нибудь отметиться в истории, так все версии python обновлять что-ли сразу?

Это не ваша — програмистская забота, а наша — сисадминская.
Нам всё равно на всех серверах обновлять tzinfo в системе, в php, в java, итп.
И pytz в этом плане — гораздо проще.
На самом деле все что тут сказано — это дело привычки. Ничего такого особенного при выборе языка не увидел. И да — я питонист… :)
На самом деле обидно становится, когда и тот и другой изучишь — постоянно тянет в одном использовать лучшие фишки из другого и расстраивает, что их нет. Я сам на питоне больше пишу, но руби изучил из интереса. Теперь мне в питоне очень не хватает блоков, довольно часто с их помощью можно очень красиво и просто написать. А еще очень в руби нравится, что там нет такой чехарды с именованием как в питоне, очень раздражает, когда даже в базовой поставке языка в библиотеках CamelCase используется вместо официального underscore_case, ну и так далее в мелочах.
> На самом деле обидно становится, когда и тот и другой изучишь — постоянно тянет в одном использовать лучшие фишки из другого и расстраивает, что их нет.

Я пишу на питоне и пхп… представляете мой уровень расстройства когда пишу на пхп? :)
Как я вас понимаю =(
Сочувствую. )
Есть похожее.
У меня это выявляется когда пишу много Coffescript кода. Потом сложно переключиться на чистый яваскрипт и как-то противненько педалить на C# — всё кажется что этих скобочек слишком много.
> Примеры утрированы и сравнивают одинаковые возможности языков, без учета лучших практик их применения.

Ну так важны же практики применения. На руби надо писать как на руби, на питоне надо писать как пишут на питоне. Какой смысл вообще в таком сравнении?
Хотя, вброс, наверное годны:)
Смысл в том, что любой язык программирования заточен под какие-то специфические задачи, которые на нем решаются лучше. На мой взгляд, знание сильных и слабых сторон позволяет лучше выбрать язык под задачу. Сложный shell скрипт лучше писать на Ruby. Сложное GUI приложение — на Python. На то есть причины — и я постарался их частично отразить.
Да, я понял. Выше уже отписался, но еще раз повторюсь — мне кажется, что ни руби ни питон не заточены под какие-то специфичные задачи, нет чего-то, что лучше решается на руби, и чего-то, что лучше решается на питоне. Я бы под задачу выбирал не язык, а фреймворк.
Благодаря наличию удобных фреймворков и различных библиотек тот или иной язык может быть удобен для разработки определённых вещей.
И в области математических задач или написания гуевых приложений руби как раз блистать не будет.
Но если вы возьмёте область веба, то всё будет ровно наоборот.
На правах вброса: в общем, я уже понял, что Tcl лучше и того, и другого, и причём уже давно :)
Да, жаль про него мало статей на Хабре. Не торт :(
А как у него с производительностью?
Да он вообще на cisco маршрутизаторах встроен :)
У Вас 4 ошибки в слове LISP.
>Интерполяция строк позволяет включать в строки код на Ruby, автоматически подставляя в строку результат его выполнения.
Не очень понял что автор хотел здесь показать. Например, в питоне можно писать:
«test: %(result)d» % {'result': 1+23}

>Возможность создания временных папок с автоматическим удалением. В Python такая возможность появилась только в версии 3.2 — а это совсем отдаленное будущее.
tempfile вроде вполне себе в двойке есть.

>Есть языковая конструкция switch. А в python — нету.
Всегда казалось, что elif отлично покрывает юзкейс switch.

>В Python файл по умолчанию открывается в «текстовом режиме»
Странно видеть в списке «недостатков» логичное поведение по умолчанию какой-то функции. Если программист откроет бинарный файл без 'b', то он что называется сам виноват.

А вообще такой вопрос, имеет ли смысл для общего развития питонисту изучить Руби или лучше посомтреть на какой-то другой язык?
Не очень понял что автор хотел здесь показать

Там специально есть картинка с разницей синтаксиса. На Ruby это делается внутри строки, на Python — вызовом для строки метода format.

tempfile вроде вполне себе в двойке есть.

tempfile есть, но для ряда задач — например, когда мы делаем в скрипте svn checkout или запускаем сборку, нам нужен не временный файл, а именно временная папка.

Если программист откроет бинарный файл без 'b', то он что называется сам виноват.

Это специфичное для Windows поведение. Для всех остальных операционных систем нет такого понятия как «текстовый файл». Учитывая, что Python и Ruby оба позиционируются как кроссплатформенные языки, я ожидаю более-менее одинакового поведения моего кода. И в Ruby файл всегда открывается как «бинарный», без спецэффектов.

А вообще такой вопрос, имеет ли смысл для общего развития питонисту изучить Руби или лучше посомтреть на какой-то другой язык?

Для общего развития, на мой взгляд, полезно. Вообщем, чем больше языков — тем лучше :).
>Там специально есть картинка с разницей синтаксиса. На Ruby это делается внутри строки, на Python — вызовом для строки метода format.
Т.е. в руби вы в строку впихиваете ещё и исполняемый код? Как-то мне это смешение не очень нравится.

>tempfile есть, но для ряда задач — например, когда мы делаем в скрипте svn checkout или запускаем сборку, нам нужен не временный файл, а именно временная папка.
tempfile — Generate temporary files and directories

>Это специфичное для Windows поведение
Хм, не замечал, т.к. работаю только под линуксом. Хотя в любом случае «специфичность» выглядит странно. Вы именно что проверяли в Линукс и в Виндовс данное поведение и наблюдали разницу?
tempfile — Generate temporary files and directories

Python возвращает имя какой-то временной папки. Например, $TEMP. И ничего не удаляет. Ruby — создает временную папку и удаляет ее после выполнения скрипта.

Хотя в любом случае «специфичность» выглядит странно. Вы именно что проверяли в Линукс и в Виндовс данное поведение и наблюдали разницу?


Конечно. Это все описано в документации.
> Т.е. в руби вы в строку впихиваете ещё и исполняемый код? Как-то мне это смешение не очень нравится.
Есть два вида синтаксиса.
Можно вставлять выражения напрямую в строки: «some text #{some_ruby_expression}»
Можно использовать аналог format: «some text %s» % string_expression или «some text %s %f» % [string_expression, float_expression]

На практике если надо вставить всего одну переменную или какое-то простое выражение, то часто используют первый вариант, в более же сложных ситуациях — второй.
>на Python — вызовом для строки метода format.
И кстати, заметьте, что в примере который я привёл обошлось без явного вызова метода format.
(холивар?)
Для общего развития стóит изучить перл. В конце концов, перл повлиял и на руби, и на питон и на пхп.
(холивар!)
Для общего развития — хаскель! Всё остаьное — суета сует.
В конце концов — это принципиально иная концепция, расширяющая не только кругозор но и способы мышления.
Ну и scheme ещё. Потому что есть SICP.
Про переход ruby на 1.9. Он всё-таки можно сказать уже завершен.
Старые проекты могут ещё крутиться на 1.8.7, но все новые гемы пишут под работу с 1.9, некоторые даже начинают дропать совместимость с 1.8, те же рельсы 4е, да и другие гемы тоже, плюс ree выпуск новых релизов сворачивают в пользу mri 1.9.
Соответственно всё, что вы записываете в минус из-за поддержки только в 1.9 для начинающих новые проекты таковым уже не будет.

Плюс если вы уж сравниваете переходы на новые версии, сравните заодно уже близкую миграцию python на 3.0 Тут всё на порядок или два печальнее.
Тут скорее проблема в том, что в большинстве официальных линуксовых репозиториях, до сих пор лежит Ruby 1.8. Хотя конечно, для тех кто в теме, RVM решает все проблемы, но поверьте есть и те, кто не в теме.
Это проблема тормознутости майнтейнеров пакетов ruby в конкретных дистрах. В Archlinux'е свежий ruby в основном репозитории появляется максимум через неделю после официального анонса.
Лежать может и 1.9 рядом с 1.8 (Убунту), но вот у других пакетов в зависимостях может быть прописан именно 1.8.
В ряде случаев наши программы используются на компьютерах конечных пользователей. В случае Python там с высоко степенью вероятности будет версии 2.6 или 2.7. А вот в случае ruby там практически с равной веростностью будет 1.8 или 1.9. Так что процесс, конечно, близится к завершению, но пока не завершен :). BTW, я ничего особенного в недостатки из-за версии не записал. Наоборот, всячески подчеркнул, что в случае Ruby нужно использовать 1.9

BTW, сильное влияние оказывает версия интепретатора, идущая в комплекте с OS. Для OSX это до сих пор Ruby 1.8.x, RVM пользуются не все.
Для OSX это до сих пор Ruby 1.8.x, RVM пользуются не все.

На мой взгляд это вообще не проблема, и не касается конечных пользователей.
Распространяйте ваш софт вместе с виртуальным окружением, очевидно же.
Не весь софт можно распространить вместе с виртуальным окружением :).
НЛО прилетело и опубликовало эту надпись здесь
Юмор понятен, но чисто для галочки :)
main = do
  putStrLn ""

Хм. А ЧТО при этом становится монадным?
Холиварная статья, конечно.

По поводу бонусов руби могу сказать что форматирование в питоне можно использовать следующим образом:

print ('Name: %(name)s' % locals())

И что останов потока в любой момент — почти гарантированный способ выстрелить себе в ногу, если используется общая память.
Пример с разницей в синтаксисе для фрматирования — картинка под соответствующим пунктом сравнения.
Про выстрел в ногу и общую память — можно поподробнее?
Да, я видел картинки. Просто мне кажется что предложенный мною вариант лучше того, что указан там, и более близок к ruby-аналогу (лучше, если мы вообще считаем прямую подстановку переменных хорошей идеей, в чем я не уверен).

Общая память. Если поток, который мы собираемся убить, работает с объектом (для простоты), которым пользуются в других потоках, то он в частности может быть остановлен в середине любого метода этого объекта, потенциально оставляя его и любые его данные в inconsistent state. Это может приводить к феерическим багам и весьма неожиданному поведению. Не знаю как именно реализованы list и dict в python, но в яве, например, можно оставить в inconsistent state какой-нибудь совершенно базовый ArrayList, что приведет к абсолютной невозможности работать с ним далее.
% — синтаксис в документации Python помечен как deprecated, рекомендуется использовать format.
Не знаю как именно реализованы list и dict в python, но в яве, например, можно оставить в inconsistent state какой-нибудь совершенно базовый ArrayList, что приведет к абсолютной невозможности работать с ним далее.

И python, и ruby используют GIL, что нивелирует проблему для встроенных типов. Там есть нюансы, но они в плоскости race conditions, а не прямого нарушения потоками целостности общих данных.
Не знал про %. Очень жаль, что они убирают такие удобные конструкции из языка, основным плюсом которого является удобство (да, изменение синтаксиса print мне тоже очень не нравится).

В любом случае, проблема с состоянием пользовательских данных остается.
Подразумевается, что тот единственный поток, который работает с состоянием пользовательских данных, я убью по флагу. Но делать флаги для остальных потоков, которые куда-то коннектятся tcp, читают файла, ждут пайпов… Вообщем наличие языковой конструкции для их остановки помогает.
Я неверно выразился. Я имел в виду все данные не встроенных типов. Программист не может дать никакой гарантии на состояние данных таких типов. Конечно, можно попробовать писать классы таким образом, чтобы они работали с любыми внутренними состояниями, но я не уверен, что овчинка стоит выделки.
По поводу % — никто его не уберет, там теперь пишут «the % operator is supplemented by a more powerful string formatting method, format()» — в версии 3.0 думали, что в 3.1 объявят устаревшим, но вроде передумали.

По поводу print. Минусы понятны — в простом случае писать на 2 скобки больше. Но в консоли с ipython его можно по-старому вызывать (т.к. ipython поддерживает вызов функций без скобок). Ну и в print теперь можно аргументы передавать и разыменовывать их print(*args), или саму print как коллбэк передавать куда-то в аргументы, так что и плюсы есть)
> Очень жаль, что они убирают такие удобные конструкции из языка,
Я тоже думал что это конструкция языка. Но на самом деле это просто реализация basestring, в которой есть магический метод __mod__().
Магические методы, кстати, рулят! И весьма часто.
Хотя некоторые считаютпереопределение синтаксиса — злом, а другие, наоборот, считают макросы в лиспе — верхом метапрограммирования.

Интересно, как с этим в руби?
НЛО прилетело и опубликовало эту надпись здесь
С дает возможность легко выстрелить себе в ногу. С C++ это сложнее, но если вы стреляете, то вам отрывает всю ногу.

— Бьёрн Страуструп

А еще вот это.
Да, я просто решил дать сылку на оригинал, дабы не подозревали в сочинении сказок :-)
Вы упустили самое главное — как со скоростью?
А я не любитель предварительной оптимизации, мне все равно как у них со скоростью. Будет что тормозит — я могу тормозяющую часть оформить как расширение на C и будет мне счастье.
Не все знают с, а некоторые так знают с, что скорость может быть меньше (утечки, ошибки итд). Поэтому и интересна скорость самих языков.
Это и без меня десятки раз сравнивали :)
Вы еще там пункт забыли что у питона аргументы в функции/методе создаются на стадии интерпретации а не на стадии вызова, и это может повлечь за собой ошибки у невнимательных =)
def q(a=[]):
    a.append(1)
    print(a)
q(); // [1]
q(); // [1, 1]

Я не знаю для питонцев это преимущество или недостаток, но для остальных это явно неожиданное поведение.
любопытно! неожиданное, согласен
Тут момент вообще тонкий для начинающих, надо понимать разницу между mutable и immutable

def q(a=""):
    a += "a"
    print(a)
q(); // "a"
q(); // "a"
В любых языках есть ссылочные типы, другое дело в порядке инициализации аргументов в функции, в других языках они инициализируются каждый раз при вызове функции, в отличии от питона
В том-то и дело, что в питоне всё передается по ссылке, поэтому меняется сам объект, в данном случае массив.
Во многих языках есть ссылочные значения, но только в питоне агрументы относятся не в внутренним переменным функции а к внешним. Считайте их просто глобальными переменными к которым у Вас нет доступа.
С помощью такой фишки можно пилить синглтоны без явного объявления синглтона
Примеры кривые, вот краткий python:

class Singleton(object):
    def __new__(cls):
        if not hasattr(cls, 'instance'):
             cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance
Так запилите его в википедию.
Запилил.
И мир стал на несколько строчек лучше!
Между прочим, предыдущий вариант на метаклассе был лучше: в данной реализации __init__ будет вызываться при каждом инстанцировании класса, вне зависимости от того новый экземпляр возвращается или ранее созданный! Т.о. придётся инициализацию переносить в метод типа __init2__ и вызывать вручную в __new__ при создании нового объекта, а __init__ оставлять пустым. Ну и потомки этого класса не будут иметь возможности иметь аргументы инициализации.
Да, правы, __init__ вызывается, косяк.

Аргументы. Давайте рассудим — вот я вызываю a = Singleton(234), а в другом месте вызову b = Singleton(8903890). Вот тут я как-то в замешательстве, а что с этим делать? То есть как бы я уже создал один синглетон, который 234, а что делать с новым, у которого 8903890?
Тем не менее аргументы могут понадобиться, как параметры создания первого экземпляра, поэтому всё же лучше предоставить возможность, а не наложить ограничение (ИМХО).

А повторный вызов с другими аргументами можно перенаправить в явный метод типа _update(...). Скажем у нас есть сквозной singleton-журнал, и повторное «инстанцирование» со строкой-параметром дополняет уже существующий журнал.

Опять же через параметры конструктора можно реализовать не singleton, но cache, ключами которого будут хэши параметров
Ну предыдущий вариант явно разрешает принять аргументы, потом пихает их в первый вызов __init__, а последующие тупо игнорит.
Сказать `хрен вам` и то в сто раз прекраснее чем подложить такую свинью :)
В общем надо подумать и запилить абсолютно правильную реализацию синглтона на все случаи жизни, пусть и, эх эх, не столь краткую.
Ну правильнее лучше чем короче )) Да и метакласс не сильно длиннее вашего класса будет. Зато метакласс можно подмешать (например через декоратор) к любому (ну почти) существующему классу, не навязывая наследование. Это несомненно плюс!
НЛО прилетело и опубликовало эту надпись здесь
Видел код, где с помощью этого поведения сделано кэширование «навсегда» =)
Ой, это же скользкая тема :) Во первых сам cpython быстрее, но не критично. А во вторых, если не выходим за рамки stdlib, легким движением запускаем через pypy и взлетаем в космос. Сейчас прогнал свой древний raytracing пример на pypy, скорость меня приятно удивила.
По примеру с регулярным выражением, если сильно хочется — на python можно записать ничуть не хуже:
x, y = re.search(r'(\d+)x(\d+)', '30x20').groups()
Не-named capture groups приводят к проблемам, если возможно частичное совпадение (например, в regexp есть «или»). Также в вашем случае будет exception, если совпадения нет (search вернет None) :).
Тогда можно использовать элегантный и нечитаемый говнокод:
x, y = (lambda x, y: (x, y))(**getattr(re.search(r'(?P\d+)x(?P\d+)', '30x20'), 'groupdict', lambda: [None] * 2)())

что-то меня понесло)
Трюки и фокусы я тоже знаю. Интерполяция в словарь locals() и прочее. Но такой куд труднее читать и поддерживать. Я рассматриваю базовый синтаксис языка, который можно встретить в реальных приложениях и который в целом используется большинством программистов. Эзотерические техники существуют, но они за рамками этой статьи. Может быть напишу следующую про эмуляцию рубиновой интерполяции в питоне — есть ряд интересных наработок. Но это скорее курьез для развлечения, нежели техника, которую стоит применять в production коде.
Или так:
x, y = (
    lambda s: s.groups() if s else (None, None)
)(
    re.search(r'(\d+)x(\d+)', '30x20')
)
Описанными языками не владею, но прочитал сравнение с удовольствием.
Судя по эмоциям, вы хаскелевец или лисповец.
К сожалению PHPшник. Почему к сожалению? Не потому что PHP плохой язык, а потому что знаю только его на хорошем уровне. Тем не менее, усиленно пытаюсь заставить себя изучить python.
А в пхп что-нибудь из сравниваемого вообще есть?
Я бы отметил тот факт, что полно документации, соответственно, низкий порог вхождения. Встроенная поддержка огромного количества движков БД. Написано много библиотек (не могу сравнить с питоном и тем более руби, но полагаю, что много больше).

Из минусов — не умеет так низкоуровнево работать с потоками вообще с железом. Хотя, ему это и не сильно нужно — специфика другая.

PS/ Сравнить не могу, для этого нужно знать больше о других языках.
— встроенная поддержка JSON
— встроенная поддержка sqlite
— встроенная поддержка архивов
— в целом более распространен (в вебе уж точно)
— хорошая обратная совместимость между актуальными версиями (я бы сказал слишком хорошая)
— интерполяция строк
— встроенная поддержка SSL
— возможность включать «модули» по относительному пути (плюс автозагрузка)
— встроенный шаблонизатор, вернее PHP является шаблонизатором :)
— хорошая поддержка даты и времени (субъективно)

Итого из 32 плюсов из топика PHP обладает 12, причем как плюсами питона, так и руби. И, возможно, для кого-то именно такая комбинация плюсов перевесит минусы (коих субъективно больше чем в питон и руби вместе взятых)
Согласен, но поддержка UTF-8 достаточно печальная и не всегда работает как надо.
JSON при этом не работает корректно с кириллицей (использование кириллицы — абсурд, но это все же недостаток).
Про движки БД я упомянул — считаю что это огромный плюс.
Про совместимость — это иногда проблема, так как тащит огромный легаси, но поддерживать проект на пыхе, конечно, удобнее в этом плане.
ССЛ — юзал не часто, но поддержка действительно есть.
Дата и время, считаю что слабая сторона пыха. DateTime, конечно, есть, но работа с ним не тривиальна.

Многие обозначенные Вами плюсы являются полуплюсами, ИМХО, но пых бросать пока не собираюсь — люблю его :)
Если кратко, то многое. Точно нет потоков и нормального юникода. остальное лень выискивать — спать охота.
Требуется PHPшник на постоянную работу. И это не шутка.
Задействован на ivi.ru
ruby лучше. rails самый лучший, самый удобный, самый защищенный фреймворк. rubyist это самый добрый и умный гик.
Подожди, не торопись. Пусть они поверят, что мы здоровы.
:-)
Да и джанго как бы не покушать зашел :) Я бы даже сказал, на российском рынке сейчас на джангистов спрос куда выше, чем на рельсовиков.
обоснуй? rubyjobs.ru
И что доказывает эта ссылка? На hh поиск по python — 673 вакансии за месяц, по ruby — 250. Как вариант.
Если возможно, сравните вакансии именно относительно фреймворков — Django и RoR. Тогда и поговорим.
Пожалуйста — по запросу django 91 вакансия, по запросу ruby on rails 79. Да и по личному опыту знаю, что в 90% случаев вакансии по питону именно на джангу, еще процентов пять — администраторы, им для автоматизации. Оставшиеся — редкие вакансии в крупных компаниях на специфические должности, где питон не для веба. Насчет руби говорить не буду, но подозреваю, что и там примерно те же пироги, если уклон в веб не больше.
Ну ты приколист)) еще бы на сайте rubyjobs.ru было меньше вакансий ruby)) а сайтов связанных с вакансиями питон тож полно если что включая специализированные для Django.
Сказал тот, кто недавно «ломанул» репозиторий rails на github.
ждемс opapril1 есть информация что рельсы самый защищенный фреймворк
передавать команду и ее аргументы не строкой, а списком.
Насколько я знаю, причина, по которой аргументы передают не строкой а списком — повышение безопасности (исключение shell — инъекций).
И пробелы. Иначе не работает. Лично проверял :(.
Можете пример кода привести на Ruby и Python. Я просто не до конца понимаю что за проблема.
Примерно вот так (пишу по памяти, конкретные детали могут быть написаны с ошибками):

Ruby:
# Будет работать
`"c:/program files/some app/app.exe" "c:/documents and settings/some file.txt"`


Python:
# Не будет работать.
subprocess.check_output( '"c:/program files/some app/app.exe" "c:/documents and settings/some file.txt"' )
# Будет работать
subprocess.check_output( [ "c:/program files/some app/app.exe", "c:/documents and settings/some file.txt" ] )
shell=True попробуйте добавить
subprocess.check_output( '"c:/program files/some app/app.exe" "c:/documents and settings/some file.txt"' , shell=True)


Видимо ruby по умолчанию вызывает команду через промежуточный shell (bash/sh) а питон запускает напрямую (ресурсы экономит??)
Там все перепробовано. Не работает (с).
$ echo 'dance dance' > 'lets dance.txt'
$ "/bin/cat" "/home/seriy/lets dance.txt"
$ python
>>> import subprocess
>>> subprocess.check_output('"/bin/cat" "/home/seriy/lets dance.txt"')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 537, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
  File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1239, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
>>> subprocess.check_output('"/bin/cat" "/home/seriy/lets dance.txt"', shell=True)
'dance dance\n'
Возможно только на Windows проблема, проверить не на чем…
Да, проблема только на Windows.
Извините меня, но при установке для Windows, Tk для Ruby уже есть «из коробки».
эт скорее потому что вы ставили с rubyinstaller.org/ а не с www.ruby-lang.org ;)

я им сам пользуюсь, там МНОГО чего полезного прям в коробке
особенно радует наличие DevKit (ставим отдельно)
для сборки gem которым «С» нужен…
Совершенно верно. Я просто автора не понял. Что он за инсталлятор использовал, что у него Тк «из коробки» нема.
Оно там есть, но галочка в инсталляторе по умолчанию снята. Так что у олшинства пользователей, поставивших ruby с помошью ruby installer, Tk не будет :). Это и практики развертывания скриптов в корпоративной сети.
Возможно. Но я не первый раз занимаюсь установкой этого чуда и сам галок не ставил никогда. Завтра буду на работе — проверю. :)
Спасибо за сравнение, познавательно

сам пишу на руби, он в общем красив и понятен ;)

но многие на стороне используют питон, как встроенный/дефолтный, по этому Ваш обзор и интересен.

для меня еще аргумент в сторону ruby это синтаксис работы с регекспами — нативынй

print "Hello #{$1} world" if var =~ /regexp(.*)$/

Угу, мне тоже регэкспы в руби импонируют. Я там даже в сравнении особо выделил удобство работы с named capture groups. Очень читаемый код получается.
Собственно, на чём говорить, на русском или на английском?
Буду говорить на английском — в моём городе большинство меня не поймёт, так как у нас национальный язык РУССКИЙ, так же и тут, для решения одной задачи удобноее «говорить на питоне», а для другой — на раби.
И в чём смысл статьи?
имхо — как раз и показать это
это два языка из одной группы, (руби начинался как более объектный питон с примесью перла ?)
combines syntax inspired by Perl with Smalltalk-like features. It was also influenced by Eiffel and Lisp.
it is therefore similar in varying respects to Smalltalk, Python, Perl, Lisp, Dylan, Pike, and CLU.
кстати, да
после RUBY стали понятнее некоторые fuctional штуки
и объектная модель — понятная (мое имхо)

в общем полезен как прокси язык?
Можно использовать как основной рабочий инструмент, попутно изучая и прочие. Ведь чем больше языков — тем лучше подобрать правильный к задаче.
*тем легче
руби
>>>Интерполяция строк позволяет включать в строки код на Ruby, автоматически подставляя в строку результат его выполнения.
>>>print( «Name: {name}».format( name = name ) )
Хотел было предложить print( «text_prefix»+`py_expr`+«text_suffix» ) с намёком на то, что "+` и `+" аналогичны #{ и }. Но понял, что это не совсем то же самое, хоть и похожее.
как я понимаю #{ } активно использует то что в руби ВСЕ возвращает результат
И это правильно :)
Труъ… =)
А давайте дополним может сравнение? Я как бы по руби сам не много могу с уверенностью сказать, так как по верхушкам смотрел, для расширения кругозора.

Но в общем библиотеки это важно, глупо не пользоваться библиотеками. А потому нужны инструменты для работы с ними — rvm, virtualenv etc. Что лучше я вот не могу сказать, так как с rvm не возился.

Альтернативные реализации. То есть jruby, ironruby, ironpython, jython, pypy.
Биндинги, есть для ruby что-то вроде Cython? Есть проекты типа pypy?
Боюсь, у меня компетенции не хватит на такое сравнение. Все-таки я больше по управлению разработкой и C++. Python, Ruby — часто используемые, но не основные инструменты. Тут кому-нибудь другому писать надобно :(.
Есть FFI, — это наиболее удобная библиотека биндинга.

Аналога PyPy нет. Есть Rubinius с виртуальной машиной, основанной на LLVM, но это не то.
На счет болезненности перехода с 1.8 на 1.9 — чушь. Как тут ранее верно заметили, это касается перехода с рельс 2.х на 3.x. Но не рельсами едиными живо ruby, как говорится…

На счет многозадачности… В ruby майнстримом признана другая парадигма. Почитайте про fibers. Это что-то типа реализации кооперативной многозадачности внутри руби и является абсолютно переносимым решением.

Автор совсем ничего не сказал про метапрограммирование, duck-typing, встроенный фреймворк тестирования minitest (это для ruby 1.9) и прочая. А это в ruby «наше всё»… Впрочем, признаюсь, как с этим обстоят дела на питоне я вообще не в курсе. Возможно не хуже…

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

То как это сделано на питоне выглядит для меня как грязный хак.

Но за общий доброжелательный тон обзора — респект. Была бы возможность, плюсанул бы обязательно…
Автор совсем ничего не сказал про метапрограммирование, duck-typing, встроенный фреймворк тестирования minitest (это для ruby 1.9) и прочая. А это в ruby «наше всё»… Впрочем, признаюсь, как с этим обстоят дела на питоне я вообще не в курсе. Возможно не хуже…


Примерно одинакого. Про DSL и декораторы я написал, остальное достаточно минорные различия, которые мало на что влияют в коде и не могут быть признаны слабыми и сильными сторонами :). Встроенный фреймворк тестирования в питоне такой же, но на практике все равно все используют внешние системы тестирования, интегрированные с continous integration

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


Спасибо на добром слове, но я их примерно в равной степени использую. Руби мне импонирует чуть больше — DSL, регэкспы, shell. Но отсутствие потоков и слабая документация убивают. «Присваивать переменной функцию» — это типичное делегирование. Например, активно применяется в Qt. Аналогичный код на Ruby с замыканиями и блоками будет больше по размеру.
Есть потрясающий(для меня точно) доклад от Yehuda Katz «Why ruby isn't python» с конференции RuPy
blip.tv/rupy-strongly-dynamic-conference/yehuda-katz-tradeoffs-and-choices-why-ruby-isn-t-python-5726460
где он рассказывает о некоторых принципах, лежащих в основе ruby, почему оно всё работает именно так как есть, сравнивая с аналогичными вещами в python, и почему некоторые концепции в других языках с точки зрения рубиста 'сломаны'
> То как это сделано на питоне выглядит для меня как грязный хак.

вы про x = func? где здесь грязь и где здесь хак?
Если я правильно понимаю, функция своим именем занимает имя в пространстве имен переменных. То есть код:

def func( a, b) :
     return a + b
func = 1
func( a=1, b=2 )

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

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

Хотя бы потому, что случаи присваивания функции переменной это куда более редкая операция, чем просто присваивание числа переменной даже в python'е. Ради нечастой фичи приходится постоянно контролировать именование переменных.
Это не аргумент против функций как объектов первого рода. Ровно также можно напороться на:

func = "s"
func + 2
Для отлова таких ошибок есть статические анализаторы, например pylint. Это общая проблема динамической типизации, она не ограничивается функциями.
Я не против функций как объектов первого рода. Просто на мой взгляд это создает определенные и очевидные неудобства. Лишнее усложнение жизни программиста, которое можно было и не создавать.

Но возможно, это дает какой-то профит. Если это так, то хотелось бы примеров…
Посмотрите на примеры биндинга Qt на Python (pyside) и Ruby (qtbindings). Очень хорошо все видно.
Это даёт много профитов — почти все они возникают там, где нужна _переменная_ функция, то есть не заранее определённая прибитая гвоздями.
> Впрочем, признаюсь, как с этим обстоят дела на питоне я вообще не в курсе.
А о чем вы тогда хотите нам рассказать?

> То как это сделано на питоне выглядит для меня как грязный хак.
А присваивание обычных переменных тоже грязный хак? В Питоне все объект, вообще все. И объявление функции — это такое же присваивание переменной объекта функции, который является callable. Кстати, не только объекты функции являются callable.
Вам ни о чем. Вы в этом не нуждаетесь, как я понимаю. Я просто комментировал статью. То, что я назвал это довольно важный функционал в ruby, без этого ruby как язык был бы значительно слабее.

В ruby тоже всё объект.

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

Или я не прав? Какие возможности это дает python'у?
Делегаты в Qt удобно писать.
Таки в руби функция — объект первого класса или как?
Нет, к сожалению. Более того, вызов функции можно делать без круглых скобок — так что просто идентификатор функции это уже ее вызов О_О. У меня там в одном из примеров иллюстрация как функция оборачивается в proc через хитрую конструкцию с амперсандом и двоеточием, «symbol#to_proc».
Вот меня это и смутило.
Получается, что для функциональных приёмов программирования руби совсем никак не подходит?
Ни map/reduce, ни колбэков, ни функторов/декораторов?
ar = ['12', 'abc']
ar.map(&:size) # => [2, 3]


совсем нет, и map, и inject, и колбэки — всё есть
Вы будите смеяться, но при де факто отсутствующих декораторах и функциях, которые совсем не first class object — Ruby в рамках стандартной библиотеки предоставляет гораздо больше приемов функционального программирования, нежели питон. Выше уже написали ряд примеров. Хорошая стандартная библиотека, много алгоритмов, динамические сообщение (объекту можно послать size даже если у него нет такого метода, вернется nil) — видно, что этим пользуются, для людей сделано.
Тут ведь как — если функции первоклассные, то количество приёмов ограничено только фантазией программиста.
А что именно есть в стандартной библиотеке руби?
(я не смог адекватно сориентироваться в документации по нему)

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

map, reduce, inject, fold, select, reject, each…
э… таки.
reduce, inject, fold — это же синонимы.
select и reject — почти одно и тоже с точностью до отрицания условия.
each и map — одно и тоже в силу «всё возвращает результат»

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

Но это же всего ТРИ фичи, причом самых элементарных. И никак не «гораздо больше».

А как, например, с функциональными замыканиями, каррингом, continuations?
карринг есть.
continuations есть.
Функциональные замыкания — это что такое?
var outervar = foo;
function func() {
    var self = this;
    var localvar = bar;
    ...
    function myclosure(data) { self.dosomething(data, localvar, outervar); }
    $.ajax({ url: "url.json", success: myclosure });
    localvar = baz;
    ...
}


В качестве колбэка success передана не функция, но замыкание.
В нём замкнуты переменные self, localvar, outervar.
При её выполнении эти переменные будут связаны со значениями установленными в контексте, в котором определена функция.
В частности, localvar == baz, и outervar == foo (если за время выполнения запроса они не изменятся).
При её выполнении эти переменные будут связаны со значениями установленными в контексте, в котором определена функция.


Не понял. При выполнении myclosure после выхода из контекста функции func() — значения «localvar» и «outerval» должны быть какие? Какие они были на момент объявления myclosure, какие они были на момент выхода из контекста func() (там я вижу localvar меняется) или какие они есть на момент вызова?
На момент вызова.

Но если это вызов произойдёт где-то глубоко и темно, где есть свои outervar, localvar и self — будут использоваться те, которые видны из точки объявления.
Вот что я могу соорудить на скорую руку по вашему описанию:

$outervar = 1
$outerclosure = nil
def func()
  localvar = 10
  myclosure = ->( data ) { p data, localvar, $outervar; }
  $outerclosure = myclosure
  localvar = 20
end

func()
$outerclosure.call( "foo" )

Выведет:

"foo"
20
1


Это то или не то?
P.S.
Если после вызова func но до вызова outerclosure поменять значение outerval — то будет выведено новое значение.
А если передать closure куда-нить подальше, где есть свои outervar, localvar — и они свойства другого модуля/объекта/контекста?
А как же Файберы в Ruby 1.9? Очень мощная штука. Например, с её помощью можно писать асинхронный код в синхронном стиле github.com/igrigorik/em-synchrony. Или в Rails 3.1 с её помощью реализовали отдачу верхушки layout до выполнения кода основного шаблона.
Файберы — это другое название для «green threads». Ну да, они есть. В питоне тоже генераторы есть — это примерно равноценные механизмы, никаких явных преимуществ тут нет. А то, что я в питоне могу в отдельном потоке пообщаться с операционной системой без остановки логики программы, а в руби не могу — тут уже разница.
Green threads (потоки на уровне языка) вроде совсем другое. Файберы даёт API по управлению точки выполнения программы. Поэтому можно реализовывать хитрые штуки, как в случае с асинхронным кодом. Есть пример у генераторов в Python, которые дают тоже самое?
Про асинхронность я имею в виду:
req1 = http.request('google.com')
# делается запрос, но программа продолжает выполняться, пока мы ожидаем ответа от ОС
req2 = http.request('yandex.ru')
# снова запрос уходит в фон
puts req1.title + req2.title
# как только нам понадобилось что-то из фоновых запросов, мы прекращаем выполнение программы и ждём ответа, следующие строки программы будут выполняться только когда загрузятся данные от обоих фоновых запросов
Генераторы это генераторы, они explicit. То что вы показываете это скорее greenlet или stackless python.
В общем сейчас дефакто используют greenlet. Так как в самом python есть генераторы. которые типа тоже корутины, то гринлетов в корелиб не будет никогда.
С ходу не смогу ответить, никогда таким типом синхронизации не интересовался.
Нда. Человек сделавший обзор Ruby vs Python не знает разницу между Fibers и Green thread.
Я не кормлю троллей по принципиальным соображениям :).
Спасибо за информацию. А теперь идите и почитайте, что-то о языках о которых вы говорили. Я руку от лица не убирал с первых строчек. Забавно, имено вот такие неучи мне и слили карму.
Я зарабатываю деньги разработкой программ уже более пятнадцати лет. И чуток разбираюсь в программировании вообще, и в этих языках в частности. А что до точности формулировок — я не книгу пишу, могу себе позволить выражать мысли как мне нравится. Вот буду писать статью о зеленых потоках, генераторах, файберах, приемах их использования и разнице в реализациях — будет точность формулировок и википедия.

Забавно, если я — неучь, то кто же тогда, кроме вас конечно, профессионал? Авторы языка? :)
> Я зарабатываю деньги разработкой программ уже более пятнадцати лет.
Начался ageism. Не прав? Старше собеседника? Напомни ему об этому!

> И чуток разбираюсь в программировании вообще, и в этих языках в частности.

В чем суть тогда обзора, если вы разбираетесь «чуток»?

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

Вы вводите людей в заблуждение называя Fibers зелеными тредами.

> Забавно, если я — неучь, то кто же тогда, кроме вас конечно, профессионал? Авторы языка? :)
Вот например он — Ilya Grigorik. А вы или реально ничего не знаете о языках о которых вы написали (выглядит как сравнение 2х статей из википедии) или уебдевелопер. А то, что сравнение сильно притянуто в python выдает всю субъективность.
:)
Слив засчитан.
greenlets?
И ещё нет, что у Ruby есть символы — поиск в хеше по символу идёт гораздо быстрее. Хотя может в Python тоже есть что-то подобное.
Да, символы настолько самоочевидны, что я это как-то не учел. Но, ИМХО, это ближе к предварительной оптимизации по скорости, нежели к реальному преимуществу при написании кода.
Символы очень наглядны и удобны. Гораздо разумнее использовать именно их, нежели строки.
Гвидо отверг идею, заявив, что строковых констант будет достаточно для любого приложеиня.
Вообще обзор больше со стороны GUI разработки под Windows. При веб-разработке под UNIX было бы другие плюсы-минусы.
Я и не скрываю, что обзр достаточно субъективный. Но это, увы, будет для любого обзора — объективные критерии сухи, скупы и не передают того, с чем в реальности столкнется разработчик.
А меня больше всего раздражает невозможность написать в питоне some_list.len(), some_list.each… и обязательные скобки при вызове метода. Но это все конечно мелочи если вы привыкли к такому подходу :)
Насчёт len можно писать так:
some_list.__len__()
по-моему это еще хуже :)
Автор явно яррый питонист.

Основываясь на собственном многолетнем опыте использования обоих языков…

Позвольте мне усомниться.
Это что такое? Неужели никто не заметил?
def foo( ** kargs )
  return kargs[ :first ] + kargs[ :second ]
end

Наверное имелось в виду
def foo args = {}
  args[:first] + args[:second]
end

И ретурн там вопиюще лишний.

Это опечатка, такое бывает. Когда знаешь более двадцати языков программирования, иногда клинит даже на синтаксисе тех, которые используешь часто. А скобочки и return я написал для иллюстративности — чтобы сравнивать тот синтаксис про который я рассказываю, на не ассортимент возможностей по упрощению синтаксиса.
def foo args = {}

Возможность не ставить скобки — как кунгфу, не надо использовать её без необходимости.
согласен
но я просто обратить внимание на опечатку а не на возможность печатания без скобок :)
мдее… одно пропущенное слово превращает суть в муть :)
под «я просто обратить внимание» имелось в виду «я просто хотел обратить внимание»
Был бы ярым питонистом — писал бы по PEP8.
Тру стори.
ну тогда исправьте пожалуйста, глазам больно :)
спасибо
Уже, спасибо :)
и не одного комментария про Perl?
А что тут коментировать — всем известно, что ruby — это помесь perl и smalltalk.
не самая лучшая.
multiproccessing позволяет обойти GIL в python
Так в питоне он как раз поднимается и не мешает. Его там не нужно обходить :).
ну там есть map_async, apply_async весьма полезные в которых случая.
Используются настоящие потоки операционной системы. Несмотря на то, что оба языка используют GIL (global interpreter lock), использование настоящих потоков позволят коду на Python выполнять в отдельных потоках блокирующие операции — например, вызов shell скрипта или функций операционной системы — и при этом не блокировать другие потоки. В Ruby до версии 1.9 использовался один настоящий поток, а переключение между потоками языка эмулировалось. На практике это приводит к тому, что если в отдельном потоке Ruby вызвать shell скрипт (например, копирование файлов) или функцию операционной системы (например, показать окошко с сообщением) — то все остальные потоки в данном скрипте останавливались. Начиная с версии 1.9 Ruby использует настоящие потоки операционной системы, но на данный момент (версия 1.9.3-p125) множество недоработок не позволяют получить от этого преимущество — в частности, Ruby крайне не любит поднимать GIL при вызовах блокирующих операций, так что попытка показать окно операционной системы в отдельном потоке так же остановит остальные — на этот раз потому, что не будет поднят GIL.
wiki.python.org/moin/GlobalInterpreterLock
В питоне тоже не все чисто с ним.
В частности при работе с CPU intensive будет блокироваться GIL, а следовательно ВСЕ треды на процессорном ядре, где запущен питон процесс.
В этом плане, вплоть до 3.2 версии питона лучше, легче и удобнее использовать вместо тредом greenlets, stackless, eventlet и аналоги.
Что есть «CPU intensive»? Два запущенных потока с числодробилками вполне себе псевдопараллельно выполняются, контексты переключаются достаточно резво.
Внимательно прочитал статью. Я большую часть этого знаю. Правильно ли я вас понимаю, что у вас претензия к тому, что если 10 питоновских потоков крутят питоновский код (логику, без ввода/вывода/ожиданий), то в один момент времени выполняться будет только один из этих десяти потоков?
Вот как раз из-за таких сравнений я и написал эту статью. От того, что у Ruby есть автоматический self а у питона нет, или от того что у питона есть генераторы программисту не горяче и не холодно. Проверено на людях :).
Для тех кто пока только присматривается к Ruby или Python есть неплохая таблица сравнения синтаксиса 4х языков — Ruby, Python, Perl, PHP
http://hyperpolyglot.org/scripting
Отличная табличка
А что насчет менеджера пакетов (rubygems)? Есть нечто подобное в Python сейчас? Также неплохо было бы узнать насчет community — у кого больше? По-мойму, здесь оба пункта добавляют плюсов к ruby.
Насчёт менеджера пакетов — pip.
Насчёт «у кого больше» — это как раз здесь в комментариях и выясняется ;)
И так, продолжаем флеймообразующую тему, начатую в статье…
(знал же что не нужно заходить — не сдержусь)

К выборочным пунктам:
Именованные аргументы:
(defun foo (&key first second)
  (+ first second))
(foo :first 2 :second 3)

функции-объекты:
(defun foo ()
  (princ «test»))
(setf a #'foo)
(funcall a)

Интерполяция строк есть в библиотеке cl-interpol. Выглядит как-то так:
(princ #«My name is $name»)
Декораторы тоже на ридер макросах где-то есть. Выглядит как-то так:
#@threadsafe
(defun foo ()
  (princ «I'm decorated»))
Но вообще декораторы почти не нужны, т.к. есть макросы. Как-то так:
(defun foo ()
  (with-lock ()
    (princ «I'm decorated»)))

Было бы интересно посмотреть на примеры реализации на Ruby или Python подобного уровня фич *в библиотеках*.

Всё, простите за выбор наугад пунктов и синтаксис от балды (в cl-interpol, например, наверняка другой), пора бежуть.
И так, продолжаем флеймообразующую тему, начатую в статье…
(знал же что не нужно заходить — не сдержусь)

А я ещё здесь почувствовал, что дальше будет лисп.
Любая работающая программа неявно содержит в себе интерпретатор лиспа.

Любой тьюринг-полный язык является недоделанным лиспом.
ИМХО, в пользу руби играет то, что это очень маленький язык (классы, методы, замыкания, массивы, хэши), и справочник его стандартных классов лаконичен. Python же очень сложно осилить, т.к. он большой и его документация — разбухшая, и в ней трудно найти что-то нужное.
Т. е. большая документация — это плохо? Ок…
Да, плохо. Документация не должна быть большой или маленькой, она должна быть как раз :)
Написал ответ
Автор статьи высказывал претензии к Питону. Иногда он ошибался по незнанию матчасти. Я поправляю по мере сил.
Спасибо. Очень приятно что не зря старался. Ответил там же.
Кстати, пример с rescue для руби неправильный.

File.delete('file.txt') rescue Errno::ENOENT
на самом деле словит ЛЮБОЙ эксепшен и вернет Errno::ENOENT. Другое дело что тут врядли что-то другое может появиться, но все же, возврат объекта эксепшена — не то что подразумевалось.
Вот это уже гораздо интереснее, я этот подход откуда-то скопировал и не удосужился проврить что все работает. А можно в такой нотации отловить только нужное исключение?
как один из вариантов:
def method_a
# ...
File.delete('file.txt')
# ...
rescue Errno::ENOENT
# handle Errno::ENOENT
rescue AnotherYetError
# another yet handling
end
видимо надо было использовать не «code», a «source»
данная нотация используется только в том случае, если необходимо обязательно получить результат
content = File.read('file.txt') rescue "" # получим пустую строку, если файла нет

На счет многопоточности: то есть на многоядерном процессоре потоки, созданные в Ruby, автоматически распараллеливаются только если версия Ruby — 1.9.х? То есть до этого все выполнялись бы на одном ядре поочередно? =/ Как-то даже странно, учитывая что язык используется для high load проектов достаточно активно.
Да, на одном ядре до 1.9

Ничего странного — потоки для параллелизма используются в основном в Windows. Ruby, вместе с highload, традиционно использовалась на остальных операционках, где для параллелизма используются процессы.
Нужно сделать один веб-проект. Питон знал поверхностно, Руби не знал совсем. Но так меня пробесило, что до сих пор Джанго не поддерживает 3й Питон (сколько ему уже лет?!), что решил выучить Руби и писать на рельсах…