2014-10-28 3 views
1

Как часть моего обучения ruby, я хотел бы назвать метод size в пределах rjust, передавая его в качестве первого параметра. Не знаете, как это сделать.Как использовать вызовы методов в пределах rjust?

См., Например,

2.to_s(2) #=> returns "10" 

Теперь я хотел бы использовать rjust на 10 проходящей :size + 5 в качестве первого аргумента, чтобы получить *****10

2.to_s(2).rjust(how_to_get_size_of_10_and_add_5, "*") #=> dont know how to. 

Безуспешно пытался ниже:

2.to_s(2).tap{|s| rjust(s.size+5,"*")} #=> ...undefined method `rjust' for main:Object 
2.to_s(2).rjust(send(:size)+5,"*") #=> ... undefined method `size' for main:Object 

Я пытаюсь понять, как ссылаться и осуществлять метод на части цепочки вызовов методов. В моем примере я пытаюсь позвонить rjust по телефону 2.to_s(2) и в пределах rjust обратиться к size от 2.to_s(2). Извините, если мое письмо неуклюж

+0

Непонятно, что вы пытаетесь сделать. Что такое «размер предыдущего результата»? – sawa

+0

Мне кажется, что вы просто хотите добавить 5 звездочек к строке? 'rjust' - неправильный инструмент для этого. –

+1

То, что вы пытаетесь сделать, - это правильное выравнивание строки до длины 'size + 5'. Это эквивалентно простому добавлению пяти '*', поэтому вы можете просто сделать '' ***** # {2.to_s (2)} "' возможно даже '('*' * 5) + 2.to_s (2) ' –

ответ

4

Я не понимаю, почему вы делаете это косвенно, но, возможно, что вы пытались сделать, это:

2.to_s(2).tap{|s| break s.rjust(s.size + 5, "*")} 

новый метод, предложенный в ядре Ruby, для ситуаций, как это, но это не так но доступный. В то же время вы должны использовать комбинацию tap и break.

+0

Какова цель 'tap' здесь, когда вы« ломаете »в любом случае? Он просто добавляет шум, я бы использовал переменную. –

+0

@ p11y Чтобы избежать назначения переменных снаружи. Я пытаюсь показать минимальную поправку к коду OP. Более простым способом является просто добавить '* * * * 5'. Но OP, похоже, хочет узнать, как использовать «tap» в подобных ситуациях. – sawa

+0

@ p11y: потому что нет «карты» для одного объекта. –

0

Самое простое решение будет:

'*' * 5 + 2.to_s(2) 

Это всегда будет предварять 5 звездочками в строку.

2

Давайте отложим причины почему вы хотите сделать что. Я отвечу на прямой вопрос: «как».

Если ваша строка была коллекцией, это было бы просто map. Поэтому мы можем обернуть строку в массиве (одного элемента), карте и затем развернуть.

Array(2.to_s(2)).map{|str| str.rjust(str.size + 5, '*') }.first # => "*****10" 

К сожалению, нет map для одного объекта. Но мы можем обойти это, используя tap + break взломать.

2.to_s(2).tap{|str| break str.rjust(str.size + 5, '*')} # => "*****10" 
2

Я думаю, что печать пять звезд и ряд может быть выражено много Симпер ("*****%b" % 2, как @stefan предложил в комментариях), но вы можете сделать это ваш путь тоже:

2.to_s(2).instance_eval do 
    rjust(size + 5, '*') 
end 

Однако, tap + break -hack (предложенный @sawa и @sergio) превосходит это решение. Это в 2-3 раза быстрее, чем при использовании instance_eval, а instance_eval обходит инкапсуляцию, заменяя self.

Таким образом, не используйте instance_eval в вашем случае для академических интересов, за исключением или коду игры в гольф :)


Тестовые результаты:

tap+break  2.020000 0.000000 2.020000 ( 2.017987) 
instance_eval 5.380000 0.000000 5.380000 ( 5.383094) 

Эталонный сценарий:

require 'benchmark' 

n = 5000000 
Benchmark.benchmark do |x| 
    x.report("tap+break") do 
    n.times do 
     '10'.tap { |str| break str.rjust(str.length + 5, '*') } 
    end 
    end 

    x.report("instance_eval") do 
    n.times do 
     '10'.instance_eval { rjust(length + 5, '*') } 
    end 
    end 
end 
+0

Обратите внимание, что это также изменяет 'self' и работает медленно. – sawa

+0

При использовании 'instance_eval' аргумент блока является избыточным, просто используйте' 2.to_s (2) .instance_eval {rjust (size + 5, '*')} '. Будьте осторожны, однако, вы находитесь внутри приемника, минуя инкапсуляцию. – Stefan

+0

Спасибо за ваши комментарии - вы совершенно правы. Меня интересовала * как * slow 'instance_eval' на самом деле и сделал грязный бенчмарк. – tessi

Смежные вопросы