Hacker News new | comments | ask | show | jobs | submit login
Ruby 2.3.0 Released (ruby-lang.org)
427 points by cremno on Dec 25, 2015 | hide | past | web | favorite | 69 comments



This is actually a really great release.

`&.` removes the really annoying (and slow) `try`.

And I think the string literals freezing is going to solve a lot of problems with memory allocations.

Check out this PR for Rails that covered a lot of similar performance problems created by too many string allocations.

https://github.com/rails/rails/pull/21057/files

I wish Rails 5 could go all in on Ruby 2.3.0 and frozen string literals.


How prevalent is `try` in rails/activesupport? My benchmarks show that the lonely operator is ~2x faster than `try`. I'd expect someone to create a gem that monkey patches `try` for those running 2.3.0.


`try` is different from `try!`. the new lonely operator is like `try!`, which asks only if the object is nil and then calls the method on it if it's not (and will blow up if the object doesn't have the method publically defined). `try`, in contrast, asks if the object is nil or responds to the method and returns nil if it doesn't.


There isn't really anyway to monkeypatch `try` to use the operator. `try` API is inherently based on metaprogramming (passing a symbol to call), and have different semantics than the operator (by default it won't throw if a non-existent method is called in a non-nil object, while the operator will thrown a NoMethodError)

https://github.com/rails/rails/blob/4-2-stable/activesupport...


`try` is pretty prevalent in rails dev from what I've seen in the field.


`try` is bad for a number of reasons.

Because itll never throw an error, you see it hiding issues.

And I keep seeing colleagues writing `hash.try(:[], :some_key)`

`try!` is better.

But I'll stick to `&.` from now on.


Using `try` is definitely a code smell, but unfortunately it's often a necessary one in production environments that have seen some wear and tear in the integrity of their database structures.


Keep in mind string literal freezing is still off by default.

I like that they did it this way, give a chance to see if it actually brings performance improvements in real world scenarios before imposing it on all code.


I've turned it on for all of my projects.

But I think the real benefits will always be in framework code.


It's really great to see that with every big release, Ruby is making the language even more pleasant to use in addition to the regular performance improvements.

Ruby just keeps getting better and better.


Agreed. Been using Ruby for a few years now and it never stops being enjoyable. Hoping it keeps going for many more years!


Fun fact: Ruby 1.0 was released 19 years ago on this day.


Nice to see "Did You Mean" suggestions flourishing across various tools now, e.g. Git too. Error messages can be a whole lot more than indecipherable jargon, even for command-line warriors.

I'm also looking forward to never writing "if foo && foo.bar" again!

Congrats and happy holidays Ruby team :).


Well, git's "did you mean" is probably the most frustrating command line experience imaginable, but it's quite nice in a language!


It's the worst when it says something to the effect of "you made a typo, so we already ran this unrelated command for you!"

Tip: run the following to add a 1-second pause between the message and the "fixed" command being executed:

  git config --global help.autocorrect 10


I seriously saw this and thought it might be the reason for the ruby-colored banner.

facepalm


We can say it's for both Christmas and Ruby relesae. :)


The fact that Christmas is almost over where I am - and I saw the normal banner all day - might explain it :)


This will always work, since Ruby always releases on Christmas. :)


The banner is ruby red, so why not.


doh! till I read this I thought hn had simply rolled out a new stylesheet.


Ho ho ho!


Anyone knows if Ruby has accepted IBM's contribution of JIT for Cruby??

https://news.ycombinator.com/item?id=10715610

And below is the Presentation from Ko1 on compiling Ruby

http://rubykaigi.org/2015/presentations/ko1


(IBMer working on said JIT here)

As Chris Seaton points out as well, we're not really open source yet. Working on getting there, but it's going to take time. The important thing now is that we can start talking with the community and making it more likely that when we do get open source, it can happen in a way consumable by the Ruby community.


I can tell you that I tried your fork on some toy projects and.. nothing really to report, other than, I'm really scared something this good won't go anywhere.

Fingers crossed to seeing this hit mainline soon.


do you have any status of the project? Or any dates when we can expect?


Unfortunately no dates. We're still working on this, but we really want to do it right, so we're taking the time we need. Sorry!


I don't think that will happen for a while, if it does happen. They haven't even released their patch under a compatible licence yet, or their library as open source, for example.


Thanks for reposting this. Wonder why it's not making bigger waves. What are the performance numbers of this thing like? I feel this IBM OMR is a reply to MS opening .Net CLR


Looks like some nice additions. I try to limit the use of .try in rails, however when working with legacy codebases it is much nicer then:

if @user && @user.address && @user.address.city city = @user.address.city end

Even though I write less Ruby then I once did, I still credit it as the language which shaped my career the most. I have worked so many great jobs because of Ruby.


Yup. In addition to the general purpose safe navigation operator we also have Hash#dig now which helps with those pesky nested params:

params.dig(:user, :address, :city)


Ah, YARV finally adds bytecode compilation and loading as an "experimental" feature. It'll be interesting to see what people do with it.


I could see it making deployment faster or nicer. Imagine being able to compile all the byte code for a Rails app locally and just shoving that up instead of waiting on bundling and all that.

Also I think this would make possible hot code upgrades which are cool but probably more work than their worth. Unless you can build smart hooks into background job and web server libraries that only change the byte code in between jobs and requests. Oh the possibilities!


After reading the patch that introduced the byte code compilation it seems what I was hoping to use it for are clearly not goals of the project: https://bugs.ruby-lang.org/issues/11788


I'm not sure the prospects are so bleak. I made some tests and I could run the compiled code on another machine with a different directory structure. See https://ilconnettivo.wordpress.com/2015/12/25/ruby-2-3-0-ins...


I was curious just like you and gave this a try too. Seems that while the project is intended for this you can easily build this. Thank you for writing that up!


As someone else pointed out, at https://bugs.ruby-lang.org/issues/11788 they explain that:

They are not goals of this project:

- packing scripts to one package

- migrate obfuscate binary to other node to hide source code

---

But.. what I don't get is: why wouldn't this works as a cheap way to obfuscate some ruby code?

After all, isn't it true that when a script is compiled to byte-code then it is interpreted by the runtime as-is (and without being re-translated to the original script in memory or on disk) ?

If so - I understand that rebuilding the original ruby script would not be a big deal for a developer - but wouldn't this still pose a small barrier to the casual prying user?


Here are two bash functions so that you can compile and execute the bytecode in the terminal:

i.e.

rubyc test.rb

ruby-do test.rbc

in .bashrc:

function rubyc() {

ruby -e "File.open('$1c', 'wb').write(RubyVM::InstructionSequence.compile_file('$1').to_binary)"

}

function ruby-do() {

ruby -e "RubyVM::InstructionSequence.load_from_binary(File.open('$1', 'rb').read).eval"

}


with the existence of Perl6, Clojure, F#, Rust, Go, and few others ...

For someone who doesn’t know Ruby, why learn it today?


For my money, Ruby comes closest to realizing the "promise" of dynamic languages. That is, it's fast to build with when prototyping, flexible when refactoring, reasonably fast enough and not so memory hungry that it can't handle "web scale".

Obviously there are languages that are better in each of these areas, but few that combine so many as well as Ruby. In other words, if you know that you'll be working in a problem domain (e.g. high concurrency) where specific advantages of some other language (e.g. Go/Erlang) are likely to be needed, use that language. If you're just building something, then Ruby's a fine place to start.


It's still one of the most terse and transparent languages around, plus there are tons of jobs for working with it.

I quite like Go, Python, TypeScript, etc but Ruby is in a league of its own when it comes to short and sweet. It's a pleasure to write.


The Rails ecosystem is mature now, which means you can find an off-the-shelf gem to do just about anything you want. So building things in Rails is very very fast. It's hard to beat for MVP-style development.


For me: because nothing else approaches it in terms of linguistic flexibility. I learned Ruby about two years ago, after learning...a dozen-ish languages? Something like that. I don't write web applications in it, because Rails grinds my gears for a whole host of reasons, but for my money it is the can-opener language. If I have a problem, I feel like I can generally explore it faster in Ruby (holla, Pry) and build a solution iteratively without really burning a lot of mental effort on it.

The second part, aside from Ruby's general applicability and ease of exploration, is that I think Ruby scales, in terms of application design, from that garbage-y first-cut code to really elegant, really clean code that's fun to work in and easy to maintain. That first solution, borne mostly out of dumping my REPL history, may not be great, but that's okay: with the help of the excellent ecosystem around the language I can reify my expectations in tests and swap out the original exploratory system for good, easy-to-work-with code that's clear in its behaviors. Of course you can do that with other languages, too--but I've never found one that makes it as easy to stretch in both directions, from noodling around to code I'd trust with my business (and I'm doing exactly that), other than Ruby.

But as for the languages you namedropped:

- Perl 6 is great, but it's a decade late and it isn't sufficiently compatible with Perl 5, so it's starting miles and miles behind where Ruby is right now. It's not dead out of the gate, but it keeps lurching toward the green and making everybody nervous. Practically nobody knows Perl 6 now, I don't know why somebody would pick it over Ruby if they're lining both languages up side by side.

- Clojure is super interesting and Rich Hickey is a supergenius and we're all lucky he didn't go into supervillaining because I think he'd be really good at it. And Leiningen is an amazing build system. But Clojure suffers from what I view are the usual problems a Lisp has around readability and the hands-on-keyboard experience (and I like Lisp, I've got DrRacket installed on my laptop for a reason, but I've been writing Lisps for a decade or more now and grinding out Clojure code is slow). Love the people, love the community...would rather write Ruby.

- Rust doesn't do nearly the same thing as Ruby. They're useful for different things. I feel like Rust inherited the good parts of the Ruby ethos from the participation of folks like Steve Klabnik. Big fan of the language and the community, but it's not incompatible with Ruby where it matters anyway so who cares?

- F# is a great language and, like Rust, also has little overlap with what I use Ruby for. If I cared about Ruby for the web, maybe there would be more overlap, but F#-for-web is swimming upstream anyway. (Doable, but harder than C#.)

- Go, while it as a language deserves some small credit for introducing co-routines to people who come from Python (he said, only somewhat snarking while he makes Lua gang signs), is close to an unmitigated disaster of an ecosystem that tries to be prescriptive when it should be hands-off and hands-off when it should be prescriptive. It is also a tremendously limited language in terms of syntactic flexibility and ability to do stuff like "second-order" metaprogramming; this is a design decision that can be debated, or could be debated if I hadn't been convinced long ago by better languages that crippling a programmer to make writing an execution environment easier to always be the wrong thing. Do not want.


You should take a look at Crystal!


I have, actually. I really like the idea of it and the project is super impressive (bootstrapping as quickly as they have is legit!), but in practice it doesn't feel right to me. A lot of it is library fit, but a lot of it is inherent to the way that Crystal works. I, personally, find relatively heavy metaprogramming to be super valuable and to make me significantly more productive with my tools. I live on `instance_eval` and `send`, and Crystal's flavor of compile-time macros doesn't do it for me.

I love that it exists, and as it matures I will totally consider it for Big Time Web Application Development (for me that's Kotlin right now). But I don't think it'll ever be quite as "stretchy" as Ruby is, and Ruby's a good all-purpose language, for me, because of that stretch.


What about Elixir?


Never used it. Looks nice enough? But never looked like something I'd open in a REPL to hash out a problem. Could be wrong.


I've used both Elixir and Erlang, but as eropple said about other languages, I feel they solve different problems from Ruby. It's also no way near as mature/popular, so a lot of things you may need to write yourself instead of using an off the shelf gem.


And python...


It's got an elegant syntax, great for meta-programming (tends to be useful in large and/or complex applications), strong community (there are gems for almost everything, i.e. no need to reinvent the wheel over and over again).

It's used by some interesting applications, such as Github, Shopify, Heroku, Square, Zendesk and AirBnB.


if everything came down to just what you type in the editor (e.g. functionally equivalent programs in any language performed the same everywhere), i would always prefer ruby.

it's just a nicer language to use than most, or maybe all others.


I couldn't find any actual examples on how to use the new frozen string literals. Lots of discussion in the link provided, but that's it.


The NEWS file defines what the pragma actually is,[1], but you'd use it like so:

    # frozen_string_literal: true
    str = 'foo'
    str << 'bar'
This will now produce an error:

    # main.rb:3:in `<main>': can't modify frozen String (RuntimeError)
It's equivalent to Ruby 2.1's String#freeze:[2]

    str = 'foo'.freeze
    str << 'bar'

    # main.rb:2:in `<main>': can't modify frozen String (RuntimeError)
Except that it will affect all strings created after the pragma mark.

You can also trigger this behavior globally with the --enable=frozen-string-literal option.

[1]: https://github.com/ruby/ruby/blob/v2_3_0/NEWS#L17-L26

[2]: http://ruby-doc.org/core-2.2.3/Object.html#method-i-freeze


Interested to see how people start using safe navigation! I personally tend to avoid `try` in Rails in favor of other `nil` handling patterns.


Why? Genuinely curious.


'try' is relatively slow compared to other control logic, as allowing an exception to be thrown involves constructing an exception stack trace. This is slow in all VMs I know. Theoretically you could detect that the trace isn't used and remove it through escape analysis, but this is not easy, or you could do some crazy thing with lazily creating the stack trace, but that's a research project.


I wrote a script to benchmark some of the diff strategies for anyone curious. https://gist.github.com/hopsoft/ae361319c54bbcb4f8e2


I think you are confused, `try` is not raise/rescue. The ActiveSupport `try` implementation does not involve allowing an exception to be raised.

https://github.com/rails/rails/blob/v4.2.5/activesupport/lib...

It should be as performant as other ways of checking for nil/empty.


Ah yes you're right - I was confusing this with raise/rescue.


Not him, but I try to use patterns that are portable outside Rails where possible.


I love '&.'

I really missed this feature from C# 6.0


Does lonely operator support safe navigation in case of method calls with params too?

    obj&.foo(1)&.bar(2)&.zoo


this is working just fine:

  nil&.+(3)&.+(5)&.-(7)


nobody noticed the bytecode section?


yes. care to elaborate? first thing that came to mind was "APC-style" (https://secure.php.net/manual/en/intro.apc.php) caches. but im not super up on deployment, i thought YARV was already supposed to achieve this.


APC exists because PHP reloaded source files each time a script was executed through your webserver. No such parallel exists in Ruby; once source files are loaded in a process, they stay loaded for that process.

In theory it might allow for faster loading of Ruby code (more analogous to Python's .pyc files), but IIRC early experiments (in the early 2.0 days) showed it to be counterproductive in many cases.


ruby-2.3.0.tar.bz2 does not seem to have

    /ruby-2.3.0/bin/ruby

?


Its the source, you have to compile it yourself. Checkout the readme :)


Thanks for the reminder.




Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: