New in Ruby 3.2 - Data.define (2024)

Brandon Weaver

Posted on • Updated on

New in Ruby 3.2 - Data.define (2) New in Ruby 3.2 - Data.define (3) New in Ruby 3.2 - Data.define (4) New in Ruby 3.2 - Data.define (5) New in Ruby 3.2 - Data.define (6)

Victor Shepelev (Zverok) has just landed an extremely useful feature in Ruby, Data.define. You can find the merge here:

https://github.com/ruby/ruby/pull/6353

...and the Ruby discussion here:

https://bugs.ruby-lang.org/issues/16122

So what is it and what does it do? Well that's what we're going to take a look into.

What it Does

Succinctly put Data.define creates an immutable Struct-like type which can be initialized with either positional or keyword arguments:

Point = Data.define(:x, :y)origin = Point.new(0, 0)north_of_origin = Point.new(x: 0, y: 10)

Note: This does not inherit from Struct

...and because the API supports pattern matching you can very much do things like this still:

case originin Point[x: 0 => x, y] # rightward assignment, pattern matching Point.new(x:, y: y + 5) # shorthand hash syntaxelse originend

It can also take a block for creating additional methods if you'd like, much like Struct:

Point = Data.define(:x, :y) do def +(other) = new(self.x + other.x, self.y + other.y)end

Then Why Not Struct?

You can absolutely use Struct still. Given that why should you use Data instead?

Because it's stricter, and the values it produces are immutable. With the advent of more functional patterns in Ruby this can be a very useful thing.

Consider data passing in Ractors which requires immutable state, this becomes incredibly useful for value objects and message passing for what may inevitably be our next generation of Puma and other web servers.

Why not dry-rb?

Interestingly the dry-rb folks are very pragmatic about things like this. In fact some of their core folks are already talking about how to wrap this new feature into their immutable structs to build on top of it, rather than in parallel:

https://twitter.com/solnic29a/status/1577683251086376963

They did the same with pattern matching, and it's great to see how we build on top of what the language formally adopts.

What Do You Think of It?

Personally? I like it. I plan to use it a lot in the REPL whenever I need a quick data type I can match against without pulling out a full Struct for it as often times I don't intend to mutate it and the keyword_init flag can be a bit pesky to remember.

It reminds me a lot of case classes from Scala:

case class Book(isbn: String)val frankenstein = Book("978-0486282114")

...and of data classes from Kotlin:

data class User(val name: String = "", val age: Int = 0)

So this is not a novel concept, but a useful one for Ruby to adopt.

Closing Thoughts

While the new language features have certainly slowed, in accordance with Matz's focus on tooling, we're still seeing some interesting movement in the language core. Of course there's a lot of fascinating tooling too, and I'm thrilled to see those coming to fruition, and perhaps soon I'll write about them as well.

In the mean time thanks to Zverok for seeing this through, and everyone who participated!

Top comments (9)

Subscribe

Billy

Billy

Freelancer, Ruby prograrmmer, Linux Geek.

Dec 15 '22

  • Copy link

This Data.define stolen from Crystal. The key different with Struct is:

Struct is just a conveniently way to create a class, it is reference, create on heap.
Data.define is a value, create on stack.

Janko Marohnić

Janko Marohnić

Ruby-off-Rails evangelist, open source contributor

  • Email

    janko@hey.com

  • Location

    Brno, Czechia

  • Education

    Mathematics and Computer Science

  • Work

    Senior Ruby Engineer

  • Joined

Oct 6 '22 • Edited on Oct 6 • Edited

  • Copy link

I love it, I was excited to see this alternative implementation of Struct. However, you noted in this article that the Data class inherits from Struct, whereas I understood from the PR that it inherits from Object. How did you find that out? The docs also seem to indicate that Data is an alternative implementation:

See also Struct, which is a similar concept, but has more container-alike API, allowing to change contents of the object and enumerate it.

Tjad Clark

Tjad Clark

  • Joined

Oct 10 '22

  • Copy link

Yeah, and doing a call to ancestors shows that it doesn't inherit from Struct

New in Ruby 3.2 - Data.define (14)

Brandon Weaver

Brandon Weaver

Senior Staff Eng at One Medical. Autistic / ADHD, He / Him. I'm the Lemur guy.

  • Location

    San Francisco, CA

  • Work

    Senior Staff Eng at One Medical

  • Joined

Oct 13 '22

  • Copy link

Article amended to reflect that. In the past it was going to loosely inherit it so I must have missed that fork

Tjad Clark

Tjad Clark

  • Joined

Oct 15 '22

  • Copy link

In the source code, it is written in the struct.c file - there is some relation

Tjad Clark

Tjad Clark

  • Joined

Oct 10 '22

  • Copy link

Based on this post, I was playing around with Data, thinking that it would be a good fit for Ractor. The idea that Data is immutable is sound, however the reality is that it may be misleading, as to fully gain advantage of Ractor communication, the object needs to be fully immutable (or deeply immutable). So by default Data instances will still be copied to each instance of Ractor, unless Ractor.make_shareable was called to deep freeze the data instance.

Bart de Water

Bart de Water

  • Joined

Oct 20 '22

  • Copy link

It would be useful to have a with method to clone an instance with new data (like Sorbet's T::Struct): bugs.ruby-lang.org/issues/19000

Martin Chabot

Martin Chabot

  • Joined

Jan 6 '23

  • Copy link

The only thing that bugs me is that is that there's no way to set default values.

niku

niku

A programmer live in Hokkaido, Japan.

  • Location

    Hokkaido, Japan

  • Joined

Feb 27 '23 • Edited on Mar 11 • Edited

  • Copy link

You can override initialize method to set default values.

Point = Data.define(:x, :y) do def initialize(x: 0, y: 1) super endendp1 = Point.newp p1 # => <data Point x=0, y=1>p2 = Point.new(x: 3, y: 4)p p2 # => <data Point x=3, y=4>

docs.ruby-lang.org/en/3.2/Data.htm...

Note that Measure#initialize always receives keyword arguments, and that mandatory arguments are checked in initialize, not in new. This can be important for redefining initialize in order to convert arguments or provide defaults:

hope it helps.

For further actions, you may consider blocking this person and/or reporting abuse

New in Ruby 3.2 - Data.define (2024)

References

Top Articles
AdventHealth Proposes 400-Bed Hospital Complex in South Lakeland
Health eCareers hiring AHMG Cardiovascular Surgery PA-C at AdventHealth Orlando in Orlando, FL | LinkedIn
Jps Occupational Health Clinic
Smoothie Operator Ruff Ruffman
Milkhater05 Of
Haul auf deutsch: Was ist das? Übersetzung, Bedeutung, Erklärung - Bedeutung Online
Arcanis Secret Santa
Vacature Ergotherapeut voor de opname- en behandelafdeling Psychosenzorg Brugge; Vzw gezondheidszorg bermhertigheid jesu
Jobs Hiring Start Tomorrow
Steve Wallis Wife Age
50 budget recipes to feed a large crowd
Equipment Hypixel Skyblock
Ups Open Today Near Me
Craigslist Southern Oregon Coast
Champion Enchant Skyblock
What Is Opm1 Treas 310 Deposit
My Scheduler Hca Cloud
Nextdoor Myvidster
Lowell Holiday Wrestling Tournament 2022
Job Skills That Start With Y
Maximise Your Funding: Key Insights on Accounting for Grants
Th 8 Best Army
Craigslist Yamhill
Volstate Portal
Brake Masters 208
Myzynrewards
BCLC Launches PROLINE Sportsbook at B.C. Retail Locations
Kup telewizor LG OLED lub QNED i zgarnij do... 3000 zł zwrotu na konto! Fantastyczna promocja
The Eye Doctors North Topeka
Redgifs.comn
My Eschedule Greatpeople Me
Kathy Carrack
Ontpress Fresh Updates
Papamurphys Near Me
The 10 Craigslist Guys You’ll Live With in DC
Stellaris Resolution
Craigslist Musicians Phoenix
Waifu Fighter F95
Diablo 3 Metascore
5Gomovies
In Memoriam | September 2024
Farmers Branch Isd Calendar
Culver's Flavor Of The Day Little Chute
marie claire Australia January 2016 Robyn Lawley, Rachel Taylor, Sarah Snook • EUR 11,50
600 Aviator Court Vandalia Oh 45377
Ehc Workspace Login
Diora Thothub
Edible Arrangements Track
Winta Zesu Net Worth
Kentucky TikTok: 12 content Bluegrass State creators to know
Lottozahlen für LOTTO 6aus49 | LOTTO Bayern
49 CFR Part 581 -- Bumper Standard
Latest Posts
Article information

Author: Rueben Jacobs

Last Updated:

Views: 6056

Rating: 4.7 / 5 (77 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Rueben Jacobs

Birthday: 1999-03-14

Address: 951 Caterina Walk, Schambergerside, CA 67667-0896

Phone: +6881806848632

Job: Internal Education Planner

Hobby: Candle making, Cabaret, Poi, Gambling, Rock climbing, Wood carving, Computer programming

Introduction: My name is Rueben Jacobs, I am a cooperative, beautiful, kind, comfortable, glamorous, open, magnificent person who loves writing and wants to share my knowledge and understanding with you.