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

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

<code># 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
</code>

Ответы на вопрос(5)

Решение Вопроса

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

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

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

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

def Capital
    nil
end

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

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

Method names are full down-case, with underscores _ as separators for words into the name (e.g. Math::sqrt, Array#each_index, ...).

Predicates have a question mark ? as last character (e.g. Array#empty?, Hash#has_key?, ...). While predicates usually return boolean values, this is not always the case: these methods just need to return nil or false if the predicate evaluates to false, any other value otherwise (e.g. File::size? returns nil if the file does not exist, the size of the file as an Integer otherwise).

Methods that modify the state of the object on which they are invoked, or that have an unusual behavior have an exclamation mark ! as last character; this methods are sometimes called mutators because they usually are destructive or in-place versions of other methods (e.g. Array#sort!, Array#slice!, ...).

Setters have an equal sign = as last character (e.g. Array#[]=, ...); the Ruby interpeter offers syntactic sugar for invokation of setter methods:

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 ,[] метод, который обычно используется для доступа к массиву и значениям хеша.[] Метод может быть определен с произвольной арностью.

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

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

 11 мая 2012 г., 18:07
Также есть некоторые символы, которые могут использоваться только в качестве полного имени метода, то есть вы можете определить методы с именем - + * ** / (если вы перегружаете эти операторы), но не метод с именем foo + bar
 24 окт. 2013 г., 19:34
У меня также есть проблемы с определением способа+= в классе. Вы можете определить+ просто отлично, но не с сеттером, как вы подразумеваете. Я действительно не знаю, почему, и я не уверен, что это ошибка.
 11 мая 2012 г., 16:19
Спасибо за совет, я отредактировал соответственно.
 12 мая 2012 г., 00:38
Я думал, что они выходят за рамки вопроса, но я добавил их для полноты.
 11 мая 2012 г., 10:50
Отличный ответ! В качестве небольшого примечания: это обычно для методов предикатов (с?) вернуть фальси (nil или жеfalse) или истинные (все остальное) значения, не обязательноtrue а такжеfalse, Возвращаемое значение предназначено для использования вif заявления, где он ведет себя как если бы это былоtrueа такжеfalse но фактическое возвращаемое значение часто не является частью интерфейса предполагаемого метода, просто является истинным или ложным свойством.

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

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

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

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

test 'Some Controller#Method' do

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

test 'Some Controller_Method' do

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

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

Чтобы добавить одну вещь: вы также можете сказать объект для запуска м, метод сno name at all и он попытается вызвать метод с именем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 & apos; JBuilder:

https://github.com/rails/jbuilder

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

Ruby 1.9 offers an additional way to invoke a Proc object; as an alternative to square brackets, you can use parentheses prefixed with a period:

z = f.(x,y)

.() looks like a method invocation missing the method name. This is not an operator that can be defined, but rather is syntactic-sugar that invokes the call method. It can be used with any object that defines a call method and is not limited to Proc objects.

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

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

Ваш ответ на вопрос