I keep asking questions about sets in Raku to several AIs.
Now I asked again a question about sets in Raku to Deepseek.
It gave me the following example
# Create a mutable SetHash
my %set := SetHash.new(1, 2, 3);
# Add elements
%set.set(4);
%set ∪= set(5, 6);
# Remove an element
%set.unset(2);
# Check membership
say 3 ∈ %set; # Output: True
say 2 ∈ %set; # Output: False
# Display the set
say %set; # Output: SetHash(1 3 4 5 6)
I tested the example, and it worked fine.
My question is, is it ok to declare (not scalar) variables using binding, or is there any downside to that ?
If you do not use binding in this case:
my %set = SetHash.new(1, 2, 3);
you will store the result of SetHash.new(1,2,3)
in a Hash called %set
. And then consequently, %set.set(4)
will fail with: No such method 'set' for invocant of type 'Hash'
.
If you don't like the binding syntax, you can use the alternate syntax using the is
trait:
my %set is SetHash = 1, 2, 3;
To get back to your question: "My question is, is it ok to declare (not scalar) variables using binding, or is there any downside to that ?"
Yes, it is ok, and in situations like this, required to get the desired result.
tldr: Yes (its OK to do this) and No (there are no downsides)
Longer version.
You have probably read this https://docs.raku.org/language/containers - I link here for others who may not yet have checked this out. Examples are given for Hash rather than SetHash since that's a more common situation.
We are playing with two dimensions here:
%set
denotes a Hash%set
Instead, you could have:
$set
In this case, the application of type constraints,
my Int %h := Hash[Int].new: (:a(1), :b(2), :c(3));
... constrain values and check container type
becomes
my Hash[Int] $h := Hash[Int].new: (:a(1), :b(2), :c(3));
... constrain container type
So the %
sigil provides some nice coder feel for what the variable contains and adds syntax to check that the contents are a well formed Hash (as opposed to eg. an Int) ... but otherwise that's just a decoration on the variable record in the symbol table. Raku auto containerizes so if you bind or assign (eg) a Hash to a $
scalar, it will make a container and put a "reference" to the Hash in it. It will then auto decont when you use it.
%set
In this case, the application of type constraints,
my Int %h := Hash[Int].new: (:a(1), :b(2), :c(3));
... constrain values and check container type
becomes
my Int %h = Hash.new: (:a(1), :b(2), :c(3));
... values are copied and checked at runtime
So the :=
binding adds a new symbol to the object on the RHS, whereas the =
assignment copies the values on the RHS to a new object on the LHS.
One of the neat features of raku is that features are independent and composable so by combining sigils and binding/assignment the coder can exert tight control over the underlying operations in a consistent way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With