4 ms·
Ruby itself has zero changes from sorbet, so all sorbet syntax has to be valid Ruby. `sig` is implemented as a library. In this case, your example is not valid
by bhuga 7y ago
Ruby itself has zero changes from sorbet, so all sorbet syntax has to be valid Ruby. `sig` is implemented as a library.
In this case, your example is not valid syntax, which violates this rule. Not that I personally could tell you why the parser makes a distinction here, but it's at least part of the reason :)
irb(main):010:0> foo {a: "b"}
SyntaxError: (irb):10: syntax error, unexpected ':', expecting '}'
foo {a: "b"}
^
(irb):10: syntax error, unexpected '}', expecting end-of- input
foo {a: "b"}
^
from /Users/bhuga/.rbenv/versions/2.4/bin/irb:11:in `<main>'
irb(main):011:0> foo {params(a: "b")}
NoMethodError: undefined method `foo' for main:Object
from (irb):11
from /Users/bhuga/.rbenv/versions/2.4/bin/irb:11:in `<main>'
irb(main):012:0>
The `sig` syntax has gone through multiple iterations; within the boundaries of Ruby syntax this is the best we've had.
- mnarayan01 7y agoThe parser thinks that's a block not a hash.
- cutler 7y agoRight, so why not implement the sig as a block and keep the syntax concise - the Ruby Way.
- bhuga 7y agoThe sigs are implemented as blocks. We had them as hashes for a while, but it meant that code in all sigs was loaded as the code was loaded, even if runtime typechecking was disabled. We were forced to load all constants in any signature in a file, an effect which cascades quickly. It had a big impact on the dev-edit-test loop. For example, if we're testing `method1` on `Foo`, but `method2` has a sig that references `Bar`, we'd have to load `Bar` to run a test against `method1`. Now sigs are blocks and lazy, and we pay that load penalty the first time the method is called and a typecheck is performed.
- mnarayan01 7y agoThen you'd need an extra set of delimiters, e.g.: sig {{name: String, returns: Integer}}
- BenMorganIO 7y agoBut that would make the hash braces redundant so you could just use parenthesis.
- mnarayan01 7y agoThat's a block returning a Hash; see bhuga's sibling comment where he notes that they're using blocks to lazy load the constants in the type definition, which may seem silly for e.g. Integer, but consider e.g. some high-dependency Rails model which requires auto-loading 10,000 other classes.