Как я могу проверить функцию, переданную методу в Ruby? - PullRequest
1 голос
/ 12 октября 2009

Я пишу библиотеку для гуманизации байтов в Ruby (например, чтобы превратить счетчик байтов 1025 в строку 1.1K), и я застрял на одном элементе дизайна.

План состоит в том, чтобы расширить Numeric методом humanize, который возвращает дружественную человеку строку при вызове по номеру. Посмотрев на источник Number :: Bytes :: Human (модуль Perl, который мне очень нравится за это), я решил добавить к этому методу две опции: одну для использования 1000-байтовых блоков и одну использовать floor вместо ceil для функции округления по умолчанию.

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

def humanize(params = {})
  params = {:block => 1024, :r_func => lambda }.merge params
  # yada yada
end

В идеале, я бы хотел, чтобы пользователь передавал функцию в качестве значения params[:r_func], но я не могу понять, как проверить, что это либо ceil, либо floor. Поскольку я не могу справиться с этим, я закончил тем, что сделал следующее, что кажется довольно неуклюжим:

  def humanize(params = {})
    params = {:block => 1024, :r_func => 'ceil' }.merge params
    if params[:r_func].eql? 'ceil'
      params[:r_func] = lambda { |x| x.ceil }
    elsif params[:r_func].eql? 'floor'
      params[:r_func] = lambda { |x| x.floor }
    else 
      raise BadRound, "Rounding method must be 'ceil' or 'floor'."
    end
    # blah blah blah
  end

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

Ответы [ 3 ]

7 голосов
/ 12 октября 2009

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

Если вы хотите ограничить пользователя потолком и полом, просто дайте им пропустить символ :ceiling или :floor в. Более гибкий дизайн позволил бы методу принимать блок, который получает один параметр , число, которое будет округлено. Затем пользователь может использовать любой алгоритм округления, который он предпочитает, в том числе пользовательский.

Кстати, Numeric#humanize попадает в эту категорию обезьяньих патчей с таким популярным именем, что вы, скорее всего, столкнетесь с коллизиями пространства имен (и, как следствие, с небольшими ошибками) во всем, кроме небольшого личного проекта.

3 голосов
/ 12 октября 2009

Я не вижу смысла в том, чтобы звонящий передавал лямбду, если вы на самом деле не собираетесь звонить. Вместо этого сделайте его символом, и вы сможете сделать что-то вроде:

raise BadRound, "Rounding method must be :ceil or :floor." unless [:ceil, :floor].include? params[:r_func]
op = lambda {|x| x.send params[:r_func]}
# blah blah blah
2 голосов
/ 12 октября 2009

Почему они передают указатель на функцию вместо логического? Таким образом, вы избегаете проблемы проверки функции.

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