The Crystal Programming Language Forum

Destructing named tuple?

Is there a way to destruct named tuple?

prices_daily = [
  { year: 2000, month: 1, day: 1, price: 1 },
  { year: 2000, month: 1, day: 2, price: 2 },

  { year: 2000, month: 2, day: 1, price: 3 },
]
grouped_by_month = prices_daily.group_by do |tuple| 
  { tuple[:year], tuple[:month] }
end

I was trying to use something like code below, but it wont’ compile

grouped_by_month = prices_daily.group_by do | year, month |
  { year, month }
end

Unpacking works for tuples (but not named tuples). Ref: https://crystal-lang.org/reference/syntax_and_semantics/blocks_and_procs.html#unpacking-block-arguments

Even if you create a macro macro proj(t, :year, :month) that will transform the code to { t[:year], t[:month} } it wont be much different to the first code:

prices_daily.group_by { |t| proj(t, :year, :month) }
prices_daily.group_by { |t| { t[:year], t[:month] } }

Note that there is no way a method in a named tuple would be able to preserve the typing from the named tuple components to a tuple, so that why I mention a macro,.

Thanks, any plans to extend it for named tuples too in the future? In theory it looks reasonable

NamedTuple

array = [{number: 1, word: "one"}, {number: 2, word: "two"}]
array.each do |{number, word}|
  puts "#{number}: #{word}"
end

Tuple

array = [{1, "one"}, {2, "two"}]
array.each do |(number, word)|
  puts "#{number}: #{word}"
end

A limitation with named tuples is that {A: 1} is a valid named tuple, but A is not a valid local variable.

And something like the following is a bit less fun probably.

array = [{Number: 1, Word: "one"}, {Number: 2, Word: "two"}]
array.each do |{Number: number, Word: word}|
  puts "#{number}: #{word}"
end

No plans AFAIK

1 Like