Pull to refresh

Comments 46

Тяжело дочитать топик до конца…
Все равно, спасибо за детальное и качественное сравнение!
Спасибо Yehuda Katz за сравнение ;)
А мне — в лучшем случае за перевод :)
Советую дочитать, там просто все. Будешь знать чем руби лучше других ;)
В чем то лучше, а в чем то и хуже…
Но, так как я использую руби уже более 3-х лет, то для меня плюсов все же больше чем минусов :)
да, в чем руби хуже надо читать в других блогах :)
статье ооооочень нехватает подсветки синтаксиса.

По переводу:

Метод File.open принимает блок. Он открывает новый файл (в режиме «append») и выдает открытый файл в блок. Когда блок заканчивает работу, Ruby закрывает файл. Кроме этого, Ruby не просто закрывает файл, когда блок<.strong> завершается, он гарантирует, что File будет закрыт, даже если выполнение блока завершается исключением

и вот из-за таких мелочей как повторяемые слова, статью сложно дочитать до конца =(
т.е.:

Метод File.open принимает блок. Он открывает новый файл (в режиме «append») и выдает открытый файл в блок. Когда блок заканчивает работу, Ruby закрывает файл. Кроме этого, Ruby не просто закрывает файл, когда блок завершается, он гарантирует, что File будет закрыт, даже если выполнение блока завершается исключением
Подправил это место, а заодно и несколько других. Надеюсь, теперь читать будет легче, но все равно могли остаться «нерусские» места, пишите еще.
на счет подсветки — соооогласен :) хорошо хоть <pre></pre> работает. Видимо, не предназначен хабр для таких статей
разобрался зачем ХабраРедактор, следующая будет в нем с подсветкой синтаксиса
еще вариант — вставить картинки с кодом из оригинальной статьи, он там подсвеченный
Блоки/коллбеки/замыкания — очень интересная вещь — но статья абсолбтно нечитаема, и примеры какие-то непонятные :(
что именно непонятно?
> Начнем с того, что мы обычно указываем на Rake, RSpec или Sinatra в качестве примеров удивительного использования блочного синтаксиса:

Что такое Rake, Rspec и тем более Sinatra (певец вроде такой был)? Непонятно. Что делают идущие далее 3 строчки кода? Тем более непонятно, то есть ясно, что выводят Hello world при каких-то условиях, но не очень ясно, при каких.

Сама структура предложений выдает перевод, и этот дословный перевод звучит как-то неуклюже в русском варианте.

Дальше идет штук 10 кусков кода, которые явно что-то делают с файлами, но не очень понятно, что имеенно, и чем они друг от друга отличаются (делать diff в уме не все моугт)

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

Потому я и сделал вывод, что статья (или ее перевод) плохая и запутанная. С точки зрения читателя.
рейк, рспек и синатра — это инструменты руби. о каждом из них написана книга. непосвященному с первого взгляда действительно непонятно, что это и зачем, но это к автору. могу сказать от себя, что он не ставил перед собой цель дать обзор для непосвященных, а именно для тех, кто понимает язык, но не понимает в чем его основная фишка, преимущество. О том, что блоки в руби — это сила, написано в каждом двухстраничном туториале, но почему это так — никто на самом деле не знает (потому что думает, как правило, что основное преимущество в красоте). Примеры показывают суть возможностей, по два примера на каждую — один на «руби» другой — на «обычном» языке, не имеющем этих возможностей. То есть статья действительно не для новичков. А те, кто хорошо разбирается в руби, пусть за себя скажут сами. Мне было очень полезно прочитать и разобраться в ней, хотя я программирую на руби и рельсах уже три года. Автор статьи является одним из разработчиков ядра рельс 3й версии и (может быть я ошибаюсь) руби 1.9.

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

Ну так бы и писали, кто не прочел эти 3 книги, к статье может даже не подходить :)

> К сожалению, он использует пресловутый «мощный синтаксис блоков», обобщая целый набор возможностей, непонятных для питониста или джависта из-за отсутствия соответствующего механизма в их языках.

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

> Описывая блоки «внешним», владеющим Javascript'ом, мы стремимся привести его функции в качестве примера. К сожалению, это только усиливает непонимание.

Я неплохо знаю Яваскрипт, но этого предложения не понял абсолютно. Чем «внешним»?

> When describing blocks to “outsiders” who share a common knowledge of Javascript, we tend to point at Javascript functions as a close analogue. Unfortunately, this only furthers the confusion.

Вот теперь стало понятно. Оказывается, «внешним» — это кому, а не чем.

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

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

чаще всего такие польза от таких штук обнаруживается при проектировании фреймворков, когда нужно как можно компактнее и удобнее решать сложные задачи. Разработчики, использующие впоследствии эти фреймворки, чаще всего даже не подозревают о таких концептуальных возможностях языка. То есть оно может даже и попасться в их коде (как
format.html { redirect_to(person_path(@people.first)) and return }
), скопированное из какого-то блога, но как оно устроено внутри мало кто сможет объяснить — работает себе, что еще надо?
Спасибо за перевод. На баркемпе 20го будете?
постараюсь прийти :)
Я понимаю что Django популярен и по этому с ним сравнивают, но куда было бы интереснее сравнение с Pylons. Мне он намного больше нравится. Касательно Ruby, в нем очень много всякого вкусного, но он так же страдает как и perl. Все эти сокращения конечно красивы, пока не начнешь их комбинировать и тогда понятность кода куда-то уплывает… А «подмешивания» просто убивают, особенно когда проект большой. Это все на любителя. Кстати библиотек там мало по сравнению с питоном, взять туже раскраску синтаксиса или wiki-разметку. Дочитал только до первого примера который ввел меня в ступор. Впрочем как и интерпретаторы. Видимо нужно подключить какие-то либы. Очень надеюсь, что кто-то это прояснит, так как самому интересны эти возможности.
Про Pylons не слышал. к оригинальной статье есть комментарий, хвалящий Rebol.

Самый первый пример — это использование фреймворка Sinatra. Его удобство проявляется тогда, когда нужен сайт из 5-10 страниц. В рельсах это выливается в сложный файл роутинга и один контроллер с несклькими вьюшками, или в несколько контроллеров и соответственно несколько папок вьюшек для них, в то время как они выполняют простейшие действия. Неудобно. Синатра позволяет сделать один файл, который сразу же и роутит, и контроллит, например:

# myapp.rb
  require 'rubygems'
  require 'sinatra'
  get '/' do
    'Hello world!'
  end


это уже заменяет все контроллеры и вьюшки рельс, рисуя хелло ворлд на стартовой странице сайта (она же единственная).

пример посложнее:
get '/hello/:name' do
    # matches "GET /hello/foo" and "GET /hello/bar"
    # params[:name] is 'foo' or 'bar'
    "Hello #{params[:name]}!"
  end

по адресу localhost:4567/hello/NElias будет надпись «Hello NElias»

Дальше можно почитать тут: www.sinatrarb.com/intro.html

Автор пишет по мотивам дискуссии на одном из ресурсов (http://news.ycombinator.com/item?id=1097901), поэтому подразумевает, что Синатра известна читателю. Кстати, я сам узнал о ней несколько месяцев назад, к собственному стыду :))) Что ж, предлагаю в первую очередь рубистам (а также синатровцам, рельсовикам и т.д. не отставать от прогрессивного человечества, а там и свой фреймворк забодяжить :)
Спасибо, понятно. На целую строчку аж короче… хотя не короче, одинаково :) Вот пример из Werkzeug(аналог Sinatra):
@expose('/display/<uid>')
def display(request, uid):
    url = URL.query.get(uid)
    if not url:
        raise NotFound()
    return render_template('display.html', url=url)

Зря вы про Pylons не слышали, потому что он аналог Rails. В чем-то лучше, в чем-то хуже. Например ORM в Pylons мощнее. А Rails сравнивать с Django не корректно, у них разная философия.
С with дело не имел, но подозреваю, что можно сделать похожий синтаксис. Из примера Ruby:
get '/hello/:name' do
    "Hello #{params[:name]}!"
end

на Python это будет примерно так:
with get('/hello/:name'):
    "Hello %s!" % params[:name]

но едва ли это нужно :)
Насамом деле на синатре мног очего интересного можно написать, мне на нем приятнее, что-то делать чем на рельсах.
По поводу понятности могу разуверить. Руби очень понятный. И миксины с блоками не так страшны как черт малюет. Сужу по своей конторе где многих кто приходил переучивали на Ruby.
Ой, ну тоже можно сказать про то, что генераторы и декораторы портят код. Классовые проперти в питоне работают не как во всех привычных языках (не шарятся между наследниками, то есть не являются для всех классов указателем в одно место; и нет, я считаю, что так и должно быть, но везде же это не так как в питоне).

И куда там дели private/public :)) Что за дурацкая конвенция с _meth __meth__ и тд и тп. Кароче религия все это :)

Да, и возможность написать:

class A(object):
pass

class B(object):
pass

a = A()
a.__class__ = B

Это что вообще такое???

Ну, а метакласса это вообще ужас-ужас :))))

То есть это религия :))) и ничто больше.
> И куда там дели private/public :))

В руби private/public тоже ничего не значат. Есть несоклько возможностей вызвать снаружи приватный метод. Более того, это не является хаком, а заложено в язык.
> а заложено в язык

Точнее — в идеологию. И эта идеология присуща многим языкам. Просто большинство кроме статично-классового ООП и не видали ничего больше. Естественно, легче назвать это «религией» и «откреститься» от этого.
даже в плюсах есть возможность вызвать приватный метод (насколько я помню) с помощью friend. Может я ошибаюсь по поводу самой возможности, но то, что это идет в разрез с инкапсуляцией — это точно.
Причём здесь Ваше отношение к альтернативной идеологии ООП и «религия»? Python использует делегирующую модель наследования с объектами первого класса. Абсолютно та же картина в Javascript.

По поводу «private» и «protected» — у Вас, опять же, неверное восприятие. Инкапсуляция — это усиление абстракции, а не параноидальное сокрытие от «злых хакеров». Использовать сокрытие ради сокрытия — это большая и самая распространённая ошибка, связанная с неверным восприятием инкапсуляции. Тогда как, в первую очередь — это помощь программисту, более абстрактно описывать систему.

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

Найдите время, прочитайте полностью: dmitrysoshnikov.com/ecmascript/ru-chapter-7-1-oop-general-theory/
Ой, ну говорил же я про другое. Я говорил, что обсуждение подходов к ООП это вещи исключительно религиозные. Потому что на парктике нет возможности убедиться какой из них лучше. Я покрайней мере не знаю, как определить какой подход лучше.

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

Я программирую на рельсах, в некоторые периоды я писал на питоне (типа не Django, а просто на питоне). Так что я че-то да понимаю, и даже помню те темные времена, когда ребятя наконец решили использовать C3 для лениризации дерева наследования и вообще родили из себя таки new-style classes.
Религиозная вера заканчивается, когда появляется понимание (или переходит на другой уровень). Я бы сказал что лучше тот язык, который правильнее реализует изначальные ООП концепции, но они тоже не стоят на месте.
Но из-за таких мелочей (как описанные в посте) язык приобретает возможности реализовывать более специфические тонкости, заметные на более низком уровне, но облегчающие создание фреймворков и работу с ними (хотя в других вещах может быть и усложняющие), как опять-таки тот же респонд_ту.
В питоне будут свои тонкости, способные упрощать работу в чем-то, но для характеристики «лучше-хуже» оснований нет (если удобство кодирования, рефакторинга, подключения расширений, документации, настройки сервера, скорость интерпретатора, масштабируемость не отличается в десятки раз), есть только заложенные в сам язык возможности и обусловленные этим более удобно решаемые задачи. Для одной задачи удобнее этот язык, для другой — этот. Т.е., например, руби благодаря своим возможностям, имеет такие преимущества, а питом — такие. Это объективно. «Лучше-хуже» — субъективизм. Если в дискуссию включить программиста микропроцессоров, он скажет, что хуже руби и питона вообще нет, а для веба — наоборот. Есть набор характеристик языка, который отражает эти возможности. Фреймворки (мне кажется) их часто нивелируют, потому что тоже предназначены для решения специфических задач, и особенности языка чаще видны внутри, чем снаружи, а наружу уже вылазят особенности фреймворков, о которых тоже можно бесконечно спорить «лучше-хуже», но по сути если нет выигрыша по критическим параметрам в разы объективно лучшего найти не получится.
). Я бы сказал что лучше тот язык, который правильнее реализует изначальные ООП концепции, но они тоже не стоят на месте.

Вот Erlang очень хороший язык массы задач определенного сорта и он совсем не реализует изначальные концепции ООП :)

Если язык реализует примерно одинаковые концепции ООП, а так же не сильно отличается в скорости и маштабируемости, тот тут уже принимается решение исходя из того, а какого качества и сколько сторонних библиотек есть для языка, а также лично впечатление от его «фишек» и красоты синтаксиса. Оба этих параметра субъективны. Любые субъективные параметры можно тут же записывать в потенциальные причины для религиозных споров.
вот и я о том же :)
но есть объективные особенности — например ретурн изнутри лямбда-функции. Это дает конкретные возможности программисту. Если они нужны — пусть берет руби, если нужны другие — пусть берет другой язык.
Ну, значит мы с самого начала говорим об одном и том же. Я лишь сторонник того, чтобы добавить в питоне блоки и многострочные лямбы, ибо я считаю, что это удобно. И многострочных лямбд мне в питоне в задачах, которые я решал, нехаватало.

Но это гнилася тема для обсуждения, ибо обсуждалась она много раз. И совсем недавно в очередной раз поднималась в comp.lang.python
Я эту статью не осили дважды. Сначала в блоге Каца, а теперь здесь. Тогда я подумал, что может это из-за того, что это английский, вот Улисс Джойса я же тоже по-английски не осилил. Однако тут получилось как с Улисс. По-русски тоже не осилил.

Просто мне кажется, что написана скучно, да и примеры… ну кому из нас в руби нужны мютексы? Кому вообще в руби нужны мютексы, если 90% его использования это Rails (тут Matz может меня минусовать, то есть мог бы, если бы у него был аккаунт на хабре и он научился бы читать по-русски).

Дело просто в том, что статья написана для тех, кто на руби не пишет, вот по этому осилить рубисту ее и сложно.

Вдобавок, стоит отметить, что ублоков есть самое клевое применение: написание DSL-ей. Да, это все сахар и рюшечки, но красиво и удобно. И второе (это уже камень в огород питона): попробуйте в питоне написать лямбду в несколько строк. А это многострочная лямбда была бы крайне полезна во всяких методах над итераторами, типа map, find и т.п.
по сути статья сводится к следующему: блоки в руби умеют
  • возвращать значение вызвавшей их функции;
  • вызывать super вызвавшей их функции;
  • передать управление в другой блок.

Если еще короче —
  • делать return
  • делать super
  • делать yield.

Но только внутри {} или do...end. Proc.new и lambda такое не позволят.
А еще они сохраняют контекст в котором были созданы. Это _очень_ важно.
Чем отличаются {} или do...end от Proc.new и lambda в вашем понимании? Мне кажется вы не поняли сути.
Поэтому они и умеют все это делать, поскольку сохраняют контекст, это я понимаю. Я писал комментарий «сверху», а не «снизу». Что именно я не понимаю?
фраза «Но только внутри {} или do...end. Proc.new и lambda такое не позволят» странна.
скорее всего, «трудности перевода» ))
Я имел ввиду комментарии после статьи:
Colin Curtin:
Кое-что, о чем нужно помнить про non-local-return: блок должен иметь доступ к контексту, из которого вы хотите вернуться.
и дальше. Т.е. в моем понимании нельзя написать оторванный от контекста Proc или lambda с директивами super, return или yield и надеяться, что он будет работать. Нужен контекст для этих super, return или yield.
с ретурном оказалось еще хитрее (innig.net/software/ruby/closures-in-ruby.rb):

# I'll spare you the rest of the experiments, and give you the behavior of all 7 cases:
#
# «return» returns from caller:
# 1. block (called with yield)
# 2. block (&b => f(&b) => yield)
# 3. block (&b => b.call)
# 4. Proc.new
# 5. proc in 1.9
#
# «return» only returns from closure:
# 5. proc in 1.8
# 6. lambda
# 7. method

т.е. из блока и Proc return вернет из внешней функции, а из lambda — только из нее (как из настоящей лямбда-функции)
Лямбда в несколько строк уже заслуживает отдельного имени, имхо. Лямбда используется там, где надо быстренько описать несложно правило преобразования аргументов в результат. Приведите пример, где нужна именно многострочная лямбда? (естественно, честная лямбда).
Вот я считаю, что не заслуживает она отдельного имени. У меня бывали задачи по обработке всяких там наборов данных. Данные приходили, скажем так, в разных форматах. И перед тем, как начать их обрабатывать иногда приходилось сделать некоторые простенькие процедуры привода их к общему виду. Причем иногда к разному. Не суть. На практике это было так: вот тут чуть подколбасить, вот чуть и отправлять считать. Подколбасить это по-сути map или несколько map-ов c простыми преобразованиями. Преобразования столь не сложные, что выносить их в именованную ф-ию нет смысла (более того, они переодически менялись, так что осмысленно набор преобразований выносить в метод), но иногда одной строчки для преобразования не хватало, так что приходилось создавать идиотскую именнованную ф-ию.
в дополнению к habrahabr.ru/blogs/ruby/86882/#comment_2619504
в частности, это упрощает рефакторинг кода, рендеры и ретурны внутри respond_to, простую реализацию синхронизации мютексов
def a
  yield
end
a{ return  0 } # => LocalJumpError: unexpected return

Это относится к ключевому слову return. Оно, ведь, не просто опционально (как пишут некоторые статьи); в определённых местах эта опциональность имеет смысл:

def a
  yield 10
end
a {|n| n + 10 } # 20
спасибо, тонкая деталь
Sign up to leave a comment.

Articles

Change theme settings