10

[I ran into the issues that prompted this question and my previous question at the same time, but decided the two questions deserve to be separate.]

The docs describe using destructuring assignment with my and our variables, but don't mention whether it can be used with has variables. But Raku is consistent enough that I decided to try, and it appears to work:

class C { has $.a; has $.b }
class D { has ($.a, $.b) }
C.new: :a<foo>;  # OUTPUT: «C.new(a => "foo", b => Any)»
D.new: :a<foo>;  # OUTPUT: «D.new(a => "foo", b => Any)»

However, this form seems to break attribute defaults:

class C { has $.a; has $.b = 42 }
class D { has ($.a, $.b = 42) }
C.new: :a<foo>;  # OUTPUT: «C.new(a => "foo", b => 42)»
D.new: :a<foo>;  # OUTPUT: «C.new(a => "foo", b => Any)»

Additionally, flipping the position of the default provides an error message that might provide some insight into what is going on (though not enough for me to understand if the above behavior is correct).

class D { has ($.a = 42, $.b) }
# OUTPUT:
===SORRY!=== Error while compiling:
Cannot put required parameter $.b after optional parameters

So, a few questions: is destructuring assignment even supposed to work with has? If so, is the behavior with default values correct/is there a way to assign default values when using destucturing assignment?

(I really hope that destructuring assignment is supported with has and can be made to work with default values; even though it might seem like a niche feature for someone using classes for true OO, it's very handy for someone writing more functional code who wants to use a class as a slightly-more-typesafe Hash with fixed keys. Being able to write things like class User { has (Str $.first-name, Str $.last-name, Int $.age) } is very helpful for that sort of code)

codesections
  • 8,900
  • 16
  • 50

1 Answers1

0

This is currently a known bug in Rakudo. The intended behavior is for has to support list assignment, which would make syntax very much like that shown in the question work.

I am not sure if the supported syntax will be:

class D { has ($.a, $.b = 42) }
D.new: :a<foo>;  # OUTPUT: «D.new(a => "foo", b => 42)»

or

class D { has ($.a, $.b) = (Any, 42) }
D.new: :a<foo>;  # OUTPUT: «D.new(a => "foo", b => 42)»

but, either way, there will be a way to use a single has to declare multiple attributes while also providing default values for those attributes.

The current expectation is that this bug will get resolved sometime after the RakuAST branch is merged.

codesections
  • 8,900
  • 16
  • 50