Ruby to_s специальный метод? [Дубликат]

Вместо того, чтобы бросать код на вас, есть два понятия, которые являются ключом к пониманию того, как JS обрабатывает обратные вызовы и асинхронность. (это даже слово?)

Модель цикла события и параллелизма

Есть три вещи, о которых вам нужно знать; Очередь; цикл события и стек

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

while (queue.waitForMessage()) {
   queue.processNextMessage();
}

Как только он получает сообщение для запуска чего-то, он добавляет его в очередь. Очередь - это список вещей, которые ждут выполнения (например, ваш запрос AJAX). Представьте себе это так:

 1. call foo.com/api/bar using foobarFunc
 2. Go perform an infinite loop
 ... and so on

Когда одно из этих сообщений будет исполнено, оно выталкивает сообщение из очереди и создает стек, стек - это все, что нужно выполнить JS для выполнения инструкции в сообщение. Таким образом, в нашем примере ему говорят позвонить foobarFunc

function foobarFunc (var) {
  console.log(anotherFunction(var));
}

. Так что все, что foobarFunc должно выполнить (в нашем случае anotherFunction), будет вставлено в стек. исполняемый, а затем забытый - цикл события затем переместится на следующую вещь в очереди (или прослушивает сообщения)

. Главное здесь - порядок выполнения. Это

КОГДА что-то будет запущено

Когда вы совершаете вызов с использованием AJAX для внешней стороны или выполняете любой асинхронный код (например, setTimeout), Javascript зависит от ответ, прежде чем он сможет продолжить.

Большой вопрос, когда он получит ответ? Ответ в том, что мы не знаем, поэтому цикл событий ждет, когда это сообщение скажет: «Эй, забери меня». Если JS просто ждал этого сообщения синхронно, ваше приложение замерзнет, ​​и оно сосать. Таким образом, JS продолжает выполнение следующего элемента в очереди, ожидая, пока сообщение не будет добавлено обратно в очередь.

Вот почему с асинхронной функциональностью мы используем вещи, называемые обратными вызовами. Это похоже на обещание буквально. Как и в I , обещание что-то вернуть в какой-то момент jQuery использует специальные обратные вызовы, называемые deffered.done deffered.fail и deffered.always (среди других). Вы можете увидеть их все здесь

Итак, вам нужно передать функцию, которая в какой-то момент будет выполнена с переданными ей данными.

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

function foo(bla) {
  console.log(bla)
}

, поэтому большую часть времени (но не всегда) вы пройдете foo не foo()

. Надеюсь, это будет иметь смысл. Когда вы сталкиваетесь с такими вещами, которые кажутся запутанными, я настоятельно рекомендую полностью прочитать документацию, чтобы хотя бы понять ее. Это сделает вас намного лучшим разработчиком.

59
задан Andrew Marshall 28 October 2014 в 13:27
поделиться

2 ответа

Обратите внимание, что все это относится к каждой паре «коротких» (например, to_s / to_i / to_a / to_h) против «long» (например, to_str / to_int / to_ary / to_hash) в Ruby (для их соответствующих типов), поскольку все они имеют одинаковую семантику.


Они имеют разные значения. Вы не должны реализовывать to_str, если ваш объект не действует , как строка, а не просто , представляемый строкой. Единственным основным классом, который реализует to_str, является сама строка.

Из Programming Ruby (цитируется из в этом сообщении в блоге , в котором стоит прочитать все ):

[to_i и to_s] не являются особенно строгими: если у объекта есть какое-то достойное представление в виде строки, например, у него, вероятно, будет to_s метод ... [to_int и to_str] являются строгими функциями преобразования: вы реализуете их только в том случае, если [ваш] объект может быть естественным образом использован в каждом месте, где может использоваться строка или целое число.

Документация Older Ruby из файла Pickaxe гласит:

В отличие от to_s, который поддерживается почти всеми классами, to_str обычно реализуется только те классы, которые действуют как строки.

Например, в дополнение к Integer оба Float & amp; Числовой реализует to_int (to_i эквивалент to_str), потому что оба они могут легко заменить Integer (все они фактически являются числами). Если ваш класс не имеет тесных отношений с String, вы не должны реализовывать to_str.

71
ответ дан Andrew Marshall 27 August 2018 в 09:33
поделиться

Чтобы понять, следует ли использовать / реализовать to_s / to_str, давайте посмотрим на некоторые примеры. Это показывает, когда этот метод терпит неудачу.

1.to_s              # returns "1"
Object.new.to_s     # returns "#<Object:0x4932990>"
1.to_str            # raises NoMethodError
Object.new.to_str   # raises NoMethodError

Как мы видим, to_s счастлив превратить любой объект в строку. С другой стороны, to_str вызывает ошибку, когда ее параметр не похож на строку.


Теперь давайте посмотрим на Array#join.

[1,2].join(',')     # returns "1,2"
[1,2].join(3)       # fails, the argument does not look like a valid separator.

Полезно, что Array#join преобразуется в строку элементов в массиве (независимо от того, что они есть на самом деле) до их присоединения, поэтому Array#join вызывает to_s на них.

Однако разделитель должен быть строкой - кто-то, вызывающий [1,2].join(3), скорее всего, совершит ошибку. Вот почему Array#join вызывает to_str в разделителе.


Тот же принцип, по-видимому, применяется для других методов. Рассмотрим to_a / to_ary на хеш:

{1,2}.to_a      # returns [[1, 2]], an array that describes the hash
{1,2}.to_ary    # fails, because a hash is not really an array.

В общем, вот как я это вижу:

  • вызывать to_s, чтобы получить строку который описывает объект.
  • вызывает to_str, чтобы убедиться, что объект действительно действует как строка.
  • реализовать to_s, когда вы можете построить строку, описывающую ваш объект.
  • реализовать to_str, когда ваш объект может полностью вести себя как строка.

Я думаю, что случай, когда вы могли бы реализовать to_str самостоятельно, возможно, это класс ColoredString - строка с прикрепленным к ней цветом. Если вам кажется, что передача цветной запятой join не является ошибкой и должна привести к "1,2" (даже если эта строка не будет окрашена), тогда выполнит to_str на ColoredString.

17
ответ дан Eldritch Conundrum 27 August 2018 в 09:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: