Немножко о "допустимых изменениях" языка

Mar 01, 2008 16:57


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

Пример (это Ruby):
Автору идеи не нравится часто используемая конструкция (проверить существование объекта и вызвать его метод)
@person ? @person.name : nilПричины, почему не ( Read more... )

мелочи, программистское

Leave a comment

Comments 21

slobin March 1 2008, 20:43:56 UTC
Вы знаете, я Руби не знаю вообще. Ни разу в жизни на ней не имел с ней дела, с идиомами не знаком. Но, если Вас смущает то, что вызов @person.try(:name) не выглядит как вызов, то почему нельзя сделать как-то так?:

class Ornil
def initialize(object)
@content = object
end
def method_missing(method, *args)
begin
@content.send(method, *args)
rescue NoMethodError
nil
end
end
end

class Object
def try
Ornil.new(self)
end
end

puts "str".try.length
puts "str".try.whatif
puts "str".try.split(//)
puts "str".try.bogus(42)

По-моему, имя после точки читается как вызов однозначно. Или у вас, рубистов, не так? Я не издеваюсь, я правда не знаю, я на этом вашем языке ни разу в жизни не писал!

... Некоммерческая террористическая организация ...

Reply

zverok_kha March 1 2008, 20:57:38 UTC
В большой степени вопрос вкуса. Этот вариант читается как "получить результат метода try, и вызвать у него метод length". Он подразумевает: а) мы (читая только этот кусок кода) не знаем, что за объект вернет метод try (т.е. неочевидно, что это будет примитивный прокси) и б) метод length будет вызван в любом случае (а не попробует быть вызванным, и промолчит если шо).

Это, кстати, хороший пример "неправильного выбора идеомы" (именно в рамках привычного рубисту).

(Кроме того, кстати, если брать с т.з. эффективности, то предложенный вариант получится наименее эффективным из-за method_missing и игнорирование ошибок через перехват исключения; и еще кроме того, трюки с method_missing считаются довольно "грязными", для них должно быть серьезное обоснование. Именно потому, что от obj.blah как правило ожидаешь вызова метода blah, а не самодеятельности с решением то ли вызывать, то ли не вызывать, то ли вызвать но не его...)

Reply

slobin March 1 2008, 21:42:02 UTC

Хрен его знает. Мне нравится самый первый вариант. Чем-то это напоминает священные войны между Коммон-Лисповцами, как правильно писать: (make-hash-table :test 'equal) или (make-hash-table :test #'equal), а также (mapcar (lambda (x) (+ x 1) '(1 2 3)) и (mapcar #'(lambda (x) (+ x 1)) '(1 2 3)). Лично я всегда пишу первые варианты, потому что считаю, что, если по смыслу видно, что "это" предназначено обозначать функцию, то вряд ли с ней будут делать что-то другое.

Насколько я смог понять, конструкция &:name в Ваших примерах должна напоминать читающему, что это блок, а стало быть, он будет вызываться. Ну хорошо, а сколь велики шансы встретить в программе символы, которые не являются именами методов и, стало быть, вызываться не будут? Если близкие к нулевым, то и так ясно, что раз символ, значит, метод, а раз метод, значит, будет вызываться. Или нет?

... Защита от дурака на дур не рассчитана ...

Reply

zverok_kha March 1 2008, 21:58:00 UTC
> а сколь велики шансы встретить в программе символы, которые не являются именами методов

огромны. символы в Руби используются везде, например, для задания опций чего-нибудь:
Net.connect(:host => 'blah', :port => 8080, :proxy => 'proxy.proxy.ua')
- идеома "именованных параметров".

Или, какой-нибудь там, не знаю:
cool_document.format_as(:html)
cool_document.format_as(:text)

Или даже так:

div(:style => 'width:100%;'){
span "Test", :id => 'main-span'
}

Именно поэтому, когда я вижу something.try(:name) - что означает этот символ - совершенно неочевидно. В том-то и суть претензий к первому варианту :)

Reply


Leave a comment

Up