parens的语法错误

ndn*_*kov 20 ruby

除了作为最后一个参数的哈希之外,您可以在方法调用中删除Ruby中的括号并获得一致的结果(您仍然需要考虑优先级).

但是,我遇到了一个不是这种情况的例子:

''.split(/ ./) # => []
''.split /./   # => []
''.split / ./  # !> SyntaxError: unexpected '.'
Run Code Online (Sandbox Code Playgroud)

这是一个错误/回归(我用2.1.2测试它 - > 2.4.1 Rubys)?

是否有其他一般情况下丢弃parens不能按预期工作?


报道了,让我们看看.


更新:票有点含糊不清.目前尚不清楚它是否是一个bug,但它不会得到修复,%r{}并建议在这些情况下使用.原因确实是开头的斜线被解释为分裂.

Ste*_*fan 19

除了这些秘密主管的回答之外,让我们来看看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,      "/"    ]]
Run Code Online (Sandbox Code Playgroud)

添加空格使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,          "/"    ]]
Run Code Online (Sandbox Code Playgroud)

是否有其他一般情况下丢弃parens不能按预期工作?

举例:

def foo(i = 1)
  10 * i
end

foo(- 2) #=> -20
foo - 2  #=> 8
Run Code Online (Sandbox Code Playgroud)

另一个:

b = 2
def a(arg)
  arg
end

a *b    #=> 2

a = 5

a *b    #=> 10
Run Code Online (Sandbox Code Playgroud)

第一个a *b被解释为a(*b),而第二个变为a * b.添加括号会强制Ruby调用该方法:

a(*b)   #=> 2
Run Code Online (Sandbox Code Playgroud)

  • 您可以在最后一个示例的末尾调用`a(*b)`以获得更好的WTF效果. (3认同)

the*_*ter 9

虽然这看起来确实是一个问题,但它并不是一个非常重要的问题,因为\s在正则表达式中会占用空间.例如:

''.split(/ ./) # => []
''.split /./   # => []
''.split / ./  # !> SyntaxError: unexpected '.'
''.split /\s./ # => []
Run Code Online (Sandbox Code Playgroud)

或者,如果你只想匹配一个空间,你必须正确地逃避它:

''.split /\ ./ # => []
Run Code Online (Sandbox Code Playgroud)

Ruby应该在parens内部或外部解析相同的参数,所以我会提交一个bug,但这并不是非常紧急,而且ruby人可能会因为离开它而感到高兴.

实际上,@ Stefan在评论中提到它可能是解析器将其视为devision,这是最可能的解释,因此它甚至不是一个bug.但它是那些有趣的小红宝石怪癖之一.

@Stefan还补充说,您可以使用%r{ .}语法创建一个明确的正则表达式文字.


Eri*_*nil 9

分区还是正则表达式?

正如在@ Stefan的回答中所写,Ruby试图将其解析为一个分支.

但是,如果没有parens,分裂和正则表达式分开真的很难.

例如,Ruby如何解析:

a /b/i
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,作为一个部门或正则表达式,取决于上下文.

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

a /b/i
# Regexp

a = 24
a /b/i
# 2
Run Code Online (Sandbox Code Playgroud)

如果a在作为方法之前将其定义为变量,则脚本将引发NameError:

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)
Run Code Online (Sandbox Code Playgroud)

我要说解析背后的模糊逻辑会使一些错误或令人惊讶的结果不可避免.

%:字符串分隔符或模数?

这是一个类似的例子,这次是%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
Run Code Online (Sandbox Code Playgroud)

这可能是我第一次看到一个SyntaxError取决于变量的先前值.

&:Proc-> Block,Bitwise AND或set intersection?

a &b 可以用至少3种不同的方式解释:

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]
Run Code Online (Sandbox Code Playgroud)

许多符号在Ruby中以不止一种方式使用,因此可能还有许多其他模糊语法示例.