
Ruby 2.7 - sadiqmmm
https://www.ruby-lang.org/en/news/2019/12/25/ruby-2-7-0-released/
======
seanmccann
I had wondered why most recent Ruby releases were on Christmas Day and
recently found out why. The Ruby creator Matz is religious (LDS), and he
considers it a Christmas gift to the community. I thought that was really
cool.

------
ufo
One of the interesting news is that they are now going to start requiring a
C99 compiler, instead of only C90.

I've been considering to do the same on my own projects. What does HN have to
say about this? Is anyone here still working in a context where C99 is not an
option? Did anyone else also recently switch to C99? How did it go?

~~~
brudgers
Why? Not being facetious. Wondering about the weights of benefits versus costs
for users.

~~~
codr7
Mostly portable implementations of extensions for me; __thread, bool,
inttypes.h, variadic macros, flexible array members etc. But declaring
variables closer to the point of use is nice, as is struct initializers,
compound literals and single line comments.

Compared to the rest, C99 contains a lot of useful improvements.

------
burlesona
> Calling a private method with a literal self as the receiver is now allowed.

Oof. Call me old fashioned, but I liked the consistency of not being able to
call private methods with an explicit receiver. Oh well!

The rest of this looks great, thanks Ruby team!

~~~
atmosx
Funny thing: I always bring up how Ruby has private methods while Python
doesn't, when toying around with colleagues about languages, etc. well there
goes that I guess.

Sidenote: I can't think of a use case where this is a good idea.

~~~
cheald
You've been able to use `send` to pierce the protected/private restriction
forever, so this doesn't particularly change the nature of Ruby's method
visibility rules. Now you can just use `self.foo` and it's the same as
`self.send :foo`.

    
    
        class Foo
          def test
            priv             # works
            self.send(:priv) # works
            self.priv        # doesn't work under ruby 2.6-
            Foo.new.priv     # doesn't work
          end
    
          private
    
          def priv
            puts "ran private"
          end
        end
    

You shouldn't typically need to be using `self` at all, except when it's
clarifying or disambiguating, so you shouldn't generally run into that issue.
On occasion, though, you add a `self.` prefix to a method call and can break
code that was otherwise working, because you've subjected your code to a scope
protection that it wasn't subject to before.

~~~
atmosx
> You've been able to use `send` to pierce the protected/private restriction
> forever, so this doesn't particularly change the nature of Ruby's method
> visibility rules.

I wasn't aware, thanks for pointing that out.

~~~
Lio
Previously this was a good reason for preferring public_send over send where
possible.

------
faitswulff
I know it's slow at the moment, but is anyone planning on using pattern
matching for anything in particular? Curious what use cases are particularly
suitable for it.

~~~
ljm
I’d love to, if it helps with things like Either/Maybe types. Although from
what I’ve looked at briefly the syntax felt a little less intuitive than I’ve
seen in other languages.

Will have to properly try it out.

~~~
jolux
what's the purpose of Either and Maybe in a dynamically typed language?

~~~
ljm
Maybe I’ve just been bitten by the functional bug but I find they can
communicate intent much better than scattering around null checks or catching
exceptions (many of which require reading the source to understand what
exceptions you might get).

It’s great in large scale projects, which I think is where a dynamic language
starts to show its warts.

~~~
obstacle1
An alternative to scattering null checks around or using exceptions for
control flow could be more thoughtfully designing your data/object model. No
additional language constructs required!

~~~
coldtea
That attitude is the source of billions of dollars in bugs...

Never manually do the work that the compiler / runtime could do.

You can design "more thoughtfully designing your data/object model" (in other
regards) AND have the compiler make sure you're not doing null referencing for
you (so that that's not your concern anymore) -- instead of manually and in an
ad-hoc way per project implementing another menial responsibility into the
design of your model.

------
sergiotapia
Pattern matching is awesome in Elixir, it's great to see functional language
traits stain the Ruby language more. It's all the better for it.

~~~
papito
I was introduced to it in Scala. I like how all "classic" languages are
cherry-picking features from functional programming. It will make people less
shell-shocked in the future, when they try it for real.

~~~
nobleach
Yup, Scala, F#/OCaml and Rust have the best pattern matching implementations
I've seen. I'm happy to see other languages slowly coming around. Java has a
JEP for it (although nowhere near as nice as Scala's). Even JavaScript has a
TC-39 proposal, although its champion has gone on to focus more on Rust. I'm
excited for the future.

------
z92
The compaction GC was the most important change. I haven't measured Ruby's
performance specifically but in general the difference and improvements over a
non-compacting GC is so huge. Specially for long running processes.

~~~
chucke
Its an important change, but not huge, at least not yet: it's not yet
integrated in the GC, which means you have to explicitly request it. And most
of the fragmentation comes anyway from the allocations heap. That being said,
I think this will improve in the coming releases.

~~~
ultrarunner
What criteria should be monitored to request compaction in a long-running
process? Is a timer sufficient (at what interval?) or are there other tools
available in Ruby to make that decision?

~~~
brandur
It's likely to be most useful for anyone using a Unicorn-style process forking
model in Ruby.

You call `GC.compact` in the parent right before forking off your child
processes and because the memory in the children are copy-on-write (COW), it
lets them share memory with their parent far longer than they normally would
be able to.

Any change in a page (i.e. an object allocated or deallocated) causes it to be
copied to a child process, and because previously pages were a mix of objects
of all kinds of longevity and slots which may be empty or used, children
tended to copy their parent's entire memory space very quickly. Running a GC
and compact before forks improves the likelihood that shared pages are mostly
full of still-in-use, longer-lived objects, and gives the COW strategy a
fighting chance.

------
mattmarcus
I'm most excited for _Enumerable#tally_ for counting occurrences of elements.

From the example in the release:

    
    
      ["a", "b", "c", "b"].tally
      #=> {"a"=>1, "b"=>2, "c"=>1}
    

There's more about this change here
([https://medium.com/@baweaver/ruby-2-7-enumerable-
tally-a706a...](https://medium.com/@baweaver/ruby-2-7-enumerable-
tally-a706a5fb11ea)). I probably do this a few times a week:

    
    
      list.each_with_object(Hash.new(0)) { |v, h| h[v.something] += 1 }

~~~
meowface
For Python developers: this exists as collections.Counter.

~~~
Twirrim
I stumbled across collections.Counter during last year's Advent of Code, and
promptly kicked myself for the number of times I'd implmeented that by hand.

------
tyingq
Does the pattern matching do something that Ruby's map() can't do?

Coming from Perl, map() there can return fewer elements than the source list,
so pattern matching works already. A short skim of Ruby's map seems to imply
it always returns something with the same number of elements.

Edit: I was confused about what this feature did. So this subthread is still
interesting, but mostly unrelated.

~~~
rubyfan
Yeah afaik something is always returned from the block (even if it’s nil).
Occasionally I recall my self doing something where the block might return nil
and then I’d call `compact` to get rid of extra nil stuff. It works when you
want a modified version of the enumerable but don’t want nil stuff. If you
just want to match a subset then I think `select` is probably what you want.

Further, the pattern matching feature is significantly different than `map`
imo.

~~~
knrz
In JavaScript, Elixir, and Ruby I use flatMap for this purpose. You can return
an empty array on the block to “skip” over the element.

~~~
Rafert
2.7 introduces `Enumerable#filter_map` for that. Example from the NEWS file:

[1, 2, 3].filter_map {|x| x.odd? ? x.to_s : nil } #=> ["1", "3"]

------
claudiug
great! i truly like this language.

------
atraktor
Love Matz & Ruby, Merry Christmas!

