Подтвердить что ты не робот

Каковы ограничения для имен методов в Ruby?

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

# This is a predicate useful for the doc:guides task of applications.
def bundler?
  # Note that rake sets the cwd to the one that contains the Rakefile
  # being executed.
  File.exists?('Gemfile')
end
4b9b3361

Ответ 1

Имена методов в Ruby могут содержать прописные и строчные буквы, цифры, символы подчеркивания _ и знаки пунктуации !, ?, =.

Имя метода не может начинаться с числа, а символы !, ? и = могут появляться только в конце.

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

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

def Capital
    nil
end

Capital    # NameError: uninitialized constant Capital
Capital()  # => nil

Некоторые очень широко и последовательно используемые соглашения при определении имен методов:

  • Имена методов полны вниз, с символами подчеркивания _ в качестве разделителей для слов в имени (например, Math::sqrt, Array#each_index,...).

  • Предикаты имеют знак вопроса ? как последний символ (например, Array#empty?, Hash#has_key?,...). Хотя предикаты обычно возвращают логические значения, это не всегда так: эти методы просто должны возвращать nil или false, если предикат оценивает значение false, любое другое значение в противном случае (например, File::size? возвращает nil, если файл не существует, размер файла как Integer в противном случае).

  • Методы, которые изменяют состояние объекта, на котором они вызывают или имеют необычное поведение, имеют восклицательный знак ! в качестве последнего символа; эти методы иногда называют мутаторами, потому что они обычно являются деструктивными или локальными версиями других методов (например, Array#sort!, Array#slice!,...).

  • Сеттеры имеют знак равенства = как последний символ (например, Array#[]=,...); интерпретатор Ruby предлагает синтаксический сахар для вызова методов setter:

    a = [4, 5, 6]
    a[0] = 3    # Shorthand for a.[]=(0, 3)
    

Ruby также позволяет определять операторы с использованием символа оператора в качестве имени метода:

╔═══════════════════════════╦═════════════════════════════════════════════╦═══════╗
║ Operators (by precedence) ║                 Operations                  ║ Arity ║
╠═══════════════════════════╬═════════════════════════════════════════════╬═══════╣
║ ! ~ +                     ║ Boolean NOT, bitwise complement, unary plus ║     1 ║
║                           ║ (define with method name [email protected], Ruby 1.9+)     ║       ║
║                           ║                                             ║       ║
║ **                        ║ Exponentiation                              ║     2 ║
║                           ║                                             ║       ║
║ -                         ║ Unary minus (define with method name [email protected])    ║     1 ║
║                           ║                                             ║       ║
║ * / %                     ║ Multiplication, division, modulo            ║     2 ║
║                           ║                                             ║       ║
║ + -                       ║ Addition, subtraction                       ║     2 ║
║                           ║                                             ║       ║
║ << >>                     ║ Bitwise shift                               ║     2 ║
║                           ║                                             ║       ║
║ &                         ║ Bitwise AND                                 ║     2 ║
║                           ║                                             ║       ║
║ | ^                       ║ Bitwise OR, Bitwise XOR                     ║     2 ║
║                           ║                                             ║       ║
║ < <= => >                 ║ Ordering                                    ║     2 ║
║                           ║                                             ║       ║
║ == === != =~ !~ <=>       ║ Equality, pattern matching, comparison      ║     2 ║
╚═══════════════════════════╩═════════════════════════════════════════════╩═══════╝

Унарные методы оператора не передаются никакими аргументами; бинарные методы оператора передаются аргументом и работают на нем и на self.

Важно строго придерживаться сущности операторов; в то время как можно определить методы оператора с другой реальностью (например, метод +, который принимает два аргумента), Ruby не позволит вам вызывать метод с синтаксисом оператора (однако он будет работать с точечным синтаксисом).

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

Язык также предлагает синтаксический сахар для специального метода non-operator, [], который обычно используется для доступа к массиву и хэш-значениям. Метод [] может быть определен с произвольной arity.

Для каждого бинарного оператора в таблице, кроме упорядочения, равенства, сравнения и сопоставления шаблонов, Ruby также предлагает сокращенное обозначение сокращенного присвоения (например, x += y расширяется до x = x + y); вы не можете определить их как методы, но вы можете изменить их поведение, определяя операторы, на которых они основаны.

Ни один из этих символов не может использоваться внутри имен обычных методов (например, do&print или start-up - недопустимые имена методов).

Ответ 2

То, что говорят другие, верно для встроенного синтаксиса, однако, по-видимому, нет никаких внутренних ограничений на то, что можно использовать, если вы используете такие методы, как define_method + send:

define_method(:'$% ^&') { 0 }
define_method(:'你好') { 1 }

send(:'$% ^&') == 0 or raise
send(:'你好') == 1 or raise

Этот факт может быть полезен: например, метод Rails ActiveSupport:: Testing:: Declarative.test использует его, чтобы не делать сложные преобразования:

test 'Some Controller#Method' do

для более здравого имени, которое может противоречить другому тесту с именем:

test 'Some Controller_Method' do

Это упоминается в Руководство по тестированию.

Любопытство: аналогичная вещь происходит в Java, где имя метода байт-кода дает больше выбора, чем язык Java: Почему JVM позволяет нам называть функцию, начинающуюся с цифры в байтекоде?

Ответ 3

Имена методов могут заканчиваться на !, ? или =. Подчеркивания также допускаются. Кроме того, существует несколько методов, которые выглядят как операторы (например, +, *, >>, []), которые вы можете определить для своих собственных классов.

Ответ 4

Чтобы добавить одно: вы также можете указать объекту на запуск метода без имени вообще, и он попытается вызвать метод с именем call:

#!/usr/bin/env ruby

class Foo

=begin
  def call(*args)
    puts "received call with #{args.join(' ')}"
  end
=end

  def method_missing(m, *args, &block)
    puts "received method_missing on `#{m}(#{args.join(', ')})`"
  end

end

f = Foo.new
f.('hi')             # Not a syntax error! method_missing with m of :call
f.send :'', 'hmm'    # method_missing with m set to :''
f.send nil, 'bye'    # raises an error

На самом деле нет метода с именем call, определенного на Object, но есть один из классов Method и Proc.

В некоторых языках () является оператором для вызова функции, и это похоже на то, что происходит здесь.

Это используется, например. в Rails JBuilder:

https://github.com/rails/jbuilder

Это описано на странице 196 книги О'Рейли Руби:

Ruby 1.9 предлагает дополнительный способ вызова объекта Proc; в качестве альтернативы квадратным скобкам вы можете использовать круглые скобки с префиксом периода:

z = f.(x,y)

.() выглядит как вызов метода, в котором отсутствует имя метода. Это не оператор, который можно определить, а скорее синтаксический сахар, который вызывает метод call. Он может использоваться с любым объектом, который определяет метод call и не ограничивается Proc объектами.

Ответ 5

Допустимые символы: a-Z,, 0-9, если не в начале, _ и ? (для булевых функций) и ! (для деструктивных функций) и = ( для сеттеров).