Live data from Hacker News

Static Typing for Ruby: Adopting Sorbet at Scale

shopify.engineering

21–30 of 72 posts

Re: Static Typing for Ruby: Adopting Sorbet at Scale

#21
post #4

I wish this had been available years ago! I think Ruby was an excellent replacement for Lua to do ML, once Torch ran out of steam due to LuaJIT memory limitations. However, historically, MRI Ruby was slow and problematic. Personally, I prefer Ruby to Python. Ruby is very close to Smalltalk, with some ideas from Perl and Lisp.

Hm interesting, for anyone interested, LuaJIT has a 2 GiB limit, which is unsurprisingly problematic for machine learning:

https://kvitajakub.github.io/2016/03/08/luajit-memory-limita...

https://github.com/karpathy/char-rnn/issues/80

Re: Static Typing for Ruby: Adopting Sorbet at Scale

#22
post #3
post #2

The second part of this two-part blogpost is here: https://shopify.engineering/adopting-sorbet

Happy to answer any questions here about our process, results or tools!

Do you have any tips or tricks for migrating a Rails app from Sorbet `srb rbi` generated files to one using Tapioca?

I was unsure exactly which bits of Sorbet rbi were still required with tapioca https://github.com/Shopify/tapioca/issues/114

We are currently using `sorbet-rails` but it appears Tapioca would be a replacement for that as well, is that correct?

Re: Static Typing for Ruby: Adopting Sorbet at Scale

#23

This looks great in general, but does anyone else find Sorbet's signature formulation offputting? Feels cluttered and not at-a-glance readable. > sig {params(name: String, id: String).returns(Integer)} My ruby isn't quite good enough to parse the language constructs that make up that line, but it's not pretty. I guess....sig is a class method which takes a block....and params is a class method (Added to BasicObject o…

The block passed to sig is evaluated in a different context, one where the local object has those methods. The methods aren't added globally, which is why you need the first method to switch the context. It's generally a good policy to avoid adding those class methods at the top level, which Sorbet does assiduously.

Sig also turns into a no-op if you have runtime verification turned off, which is another good reason not to call params right away, because (in ruby) you can ignore everything in the block if the block is not called, sort of like a debug macro in C, but you can't do that with a method that is called - it must evaluate its parameters.

Re: Static Typing for Ruby: Adopting Sorbet at Scale

#24
post #4

I wish this had been available years ago! I think Ruby was an excellent replacement for Lua to do ML, once Torch ran out of steam due to LuaJIT memory limitations. However, historically, MRI Ruby was slow and problematic. Personally, I prefer Ruby to Python. Ruby is very close to Smalltalk, with some ideas from Perl and Lisp.

God do I love Ruby. It's just such a beautiful language. Feels more expressive and imaginative than any other language I've touched by a mile.

But while I personally enjoy it more than Python, Python will always be the one I would recommend to anyone for work or learning-- it's so much more straightforward and predictable. The "one right way to do things" mentality that pervades python makes things so consistent and intuitive. Ruby, on the other hand, gives you 10+ ways to form a loop. The paradox of choice and all.

Re: Static Typing for Ruby: Adopting Sorbet at Scale

#25
post #10
post #6

Earlier quoted context omitted.

> MRI Ruby was slow and problematic. Why problematic? On the slowness, I would agree that Ruby is slower than many languages, but as an interpreted language this is -up to a certain point- by design, or at least an accepted part of the trade-off one accepts when he takes a programming language. Moreover, Ruby's natural competitor is Python, not -say- Clojure; and I wouldn't that Ruby is significantly slower than Pyth…

It had lots of memory leaks. I love Ruby, and I used it anyway, but this bothered me a lot back in the mid-to-late 2000s.

It's gotten a lot better since then, but so have all the other languages! I still love Ruby but I would use Python for ML in a heartbeat.

Re: Static Typing for Ruby: Adopting Sorbet at Scale

#26

This looks great in general, but does anyone else find Sorbet's signature formulation offputting? Feels cluttered and not at-a-glance readable. > sig {params(name: String, id: String).returns(Integer)} My ruby isn't quite good enough to parse the language constructs that make up that line, but it's not pretty. I guess....sig is a class method which takes a block....and params is a class method (Added to BasicObject o…

params in rails is pretty standard for controllers. wrapping it in something like sig makes the namespacing not collide.

https://github.com/search?l=Ruby&q=params&type=code

Re: Static Typing for Ruby: Adopting Sorbet at Scale

#27

This looks great in general, but does anyone else find Sorbet's signature formulation offputting? Feels cluttered and not at-a-glance readable. > sig {params(name: String, id: String).returns(Integer)} My ruby isn't quite good enough to parse the language constructs that make up that line, but it's not pretty. I guess....sig is a class method which takes a block....and params is a class method (Added to BasicObject o…

The block passed to sig is evaluated in a different context, one where the local object has those methods. The methods aren't added globally, which is why you need the first method to switch the context. It's generally a good policy to avoid adding those class methods at the top level, which Sorbet does assiduously. Sig also turns into a no-op if you have runtime verification turned off, which is another good reason…

That's super informative, thank you! Can you also add a word of explanation as to how the `sig` call gets associated with the method that follows it? What ties them together, is there some static parser?

Re: Static Typing for Ruby: Adopting Sorbet at Scale

#28
post #12

Earlier quoted context omitted.

Like others have stated in the thread, Crystal is a different language that shares some its syntax with Ruby. Our aim is to keep our Ruby codebase but adopt static types gradually.

Is there any runtime performance gain to be had in the interpreter at runtime when adding types. I understand the benefits to your workflow but is there an opportunity to allow the interpreter to do less work when types are used?

Currently, no. On the contrary, since Sorbet syntax is pure Ruby, it needs a runtime component, so there is actually a small negative impact in performance at runtime. The reason why we cannot use types to make the interpreter do optimizations is because the interpreter is not aware of types.

Having said that, such optimizations are indeed possible and we are already thinking about how we can use the type information we have to that effect. There are still many things that need to line up for that to be a thing, so we are not expecting any new developments on this soon. But this is a very exciting direction for our Ruby Infrastructure team at Shopify.

Re: Static Typing for Ruby: Adopting Sorbet at Scale

#29
post #22
post #3

Earlier quoted context omitted.

Happy to answer any questions here about our process, results or tools!

Do you have any tips or tricks for migrating a Rails app from Sorbet `srb rbi` generated files to one using Tapioca? I was unsure exactly which bits of Sorbet rbi were still required with tapioca https://github.com/Shopify/tapioca/issues/114 We are currently using `sorbet-rails` but it appears Tapioca would be a replacement for that as well, is that correct?

Ultimately, the goal is for Tapioca to replace all `srb rbi` tooling and `sorbet-rails`. Right now, we exclusively use Tapioca for gem RBIs and we don't use any `srb rbi` tooling at Shopify. That works perfectly fine, but you don't get any `sorbet-typed` RBIs, which, right now is not a concern for us.

The DSL generators are not 100% complete to fully replace `sorbet-rails` right now, but we are preparing a 1.0 release of the gem that should be able to do that.

Re: Static Typing for Ruby: Adopting Sorbet at Scale

#30
post #10

Earlier quoted context omitted.

It had lots of memory leaks. I love Ruby, and I used it anyway, but this bothered me a lot back in the mid-to-late 2000s.

It's gotten a lot better since then, but so have all the other languages! I still love Ruby but I would use Python for ML in a heartbeat.

I work with Ruby, Python, and R daily.

I use Ruby for everything I can, Python for ML, and R for data analysis. I just find it easier to not swim upstream and force ruby onto all of those contexts when the other 2 languages have loads of inertia behind them in those spaces. It's unfortunate.

Post reply on HN