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

Странная синтаксическая ошибка с parens

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

Однако я столкнулся с примером, где это не так:

''.split(/ ./) # => []
''.split /./   # => []
''.split / ./  # !> SyntaxError: unexpected '.'

Является ли это ошибкой/регрессией (я тестировал ее с 2.1.2 → 2.4.1 Rubys)?

Существуют ли другие общие случаи, когда отбрасывание парнеров не работает должным образом?


Сообщить об этом, давайте посмотрим.


Обновление. Билет был отклонен неоднозначно. Неясно, если это ошибка или нет, но она не будет исправлена ​​и использование %r{} в этих ситуациях было предложено. Причина в том, что начальная косая черта интерпретируется как деление.

4b9b3361

Ответ 1

Помимо ответа thesecretmaster, загляните внутрь анализатора Ruby:

require 'ripper'
require 'pp'

pp Ripper.lex("''.split /./")
# [[[1,  0], :on_tstring_beg,     "'"    ],
#  [[1,  1], :on_tstring_end,     "'"    ],
#  [[1,  2], :on_period,          "."    ],
#  [[1,  3], :on_ident,           "split"],
#  [[1,  8], :on_sp,              " "    ],
#  [[1,  9], :on_regexp_beg,      "/"    ],
#  [[1, 10], :on_tstring_content, "."    ],
#  [[1, 11], :on_regexp_end,      "/"    ]]

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

pp Ripper.lex("''.split / ./")
# [[[1,  0], :on_tstring_beg, "'"    ],
#  [[1,  1], :on_tstring_end, "'"    ],
#  [[1,  2], :on_period,      "."    ],
#  [[1,  3], :on_ident,       "split"],
#  [[1,  8], :on_sp,          " "    ],
#  [[1,  9], :on_op,          "/"    ],
#  [[1, 10], :on_sp,          " "    ],
#  [[1, 11], :on_period,      "."    ],
#  [[1, 12], :on_op,          "/"    ]]

Существуют ли другие общие случаи, когда отбрасывание парнеров не работает должным образом?

Упрощенный пример:

def foo(i = 1)
  10 * i
end

foo(- 2) #=> -20
foo - 2  #=> 8

Другой:

b = 2
def a(arg)
  arg
end

a *b    #=> 2

a = 5

a *b    #=> 10

Первый a *b интерпретируется как a(*b), тогда как второй становится a * b. Добавление скобок заставляет Ruby вызывать метод:

a(*b)   #=> 2

Ответ 2

Хотя это, безусловно, похоже на проблему, это не очень важно, потому что \s в regex будет ловить пробелы. Например:

''.split(/ ./) # => []
''.split /./   # => []
''.split / ./  # !> SyntaxError: unexpected '.'
''.split /\s./ # => []

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

''.split /\ ./ # => []

Ruby должен анализировать аргументы одинаково внутри или снаружи parens, поэтому я бы написал ошибку, но это не очень срочно, и рубины могут быть счастливы, просто оставив это.

Собственно, @Stefan упомянул в комментариях к тем, что, вероятно, анализатор читает его как девиз, что является наиболее вероятным объяснением, поэтому это даже не ошибка. Но это один из тех забавных маленьких рубиновых причуд.

@Stefan также добавил, что вы можете создать недвусмысленный литерал регулярного выражения с синтаксисом %r{ .}.

Ответ 3

Разделение или регулярное выражение?

Как написано в @Stefan answer, Ruby пытается разобрать его как деление.

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

Например, как выглядит Ruby:

a /b/i

?

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

def a(object)
  puts object.class
end
b = 4
i = 3

a /b/i
# Regexp

a = 24
a /b/i
# 2

Если a определяется как переменная перед тем, как быть методом, script вызовет имяEnror:

a = 24
def a(object)
  puts object.class
end
a(/b/i)
#Regexp
a /b/i
# 5:in `<main>': undefined local variable or method `b' for main:Object (NameError)

Я бы сказал, что нечеткая логика разбора делает некоторые ошибки или неожиданные результаты неизбежными.

%: разделитель строк или по модулю?

Здесь аналогичный пример, на этот раз с %q. Является ли это разделителем строк или modulo q?

def a(x)
  puts x
end

a(%q+t+)
# t
a %q+t+
# t

a = 4
def a(x)
  puts x
end

a(%q+t+)
# t
a %q+t+
# syntax error, unexpected end-of-input

Это первый случай, когда я вижу SyntaxError в зависимости от предыдущего значения переменной.

&: Proc- > Block, Побитовое ИЛИ или заданное пересечение?

a &b можно интерпретировать как минимум тремя различными способами:

def a
  yield
end

b = ->{ puts "BLOCK" }

a &b
# BLOCK

a = 3
b = 5
a &b
# 1

a = [1,2,3]
b = [3,4,5]
a &b
# [3]

Многие символы используются более чем одним способом с Ruby, поэтому, вероятно, есть много других примеров нечеткого синтаксиса.