problem-solving
problem-solving copied to clipboard
Issues with the design of `assuming` method
While I was working on my Curry module, I stumbled upon things that I consider issues. Now, some of them might be bugs, but most of them seem to be by design, if you look at roast; although they might be against the design documents(if I've interpreted it correctly), though that is not what defines the language.
In short, it changes function's signature and loses information and data. Maybe I don't know the reasons behind its current design, but I'll list them here to know what others think.
assuming
- loses the default value of optional positional parameters
sub f1 ($a, $b = 2) { $a + $b; } say &f1.assuming(1).signature.raku; # :($b?) say &f1.assuming(1).signature.params[0].default.defined; # False say &f1.assuming(1)(); # Use of Nil in numeric context # ... # 1 -
- removes default value of named parameters from signature of functions, but keeps its default value
sub f2 ($a, :$b = 2) { $a + $b; } say &f2.signature.raku; # :($a, :$b = 2) say &f2.assuming(1).signature.raku; # :(:$b) say &f2.assuming(1).signature.params[0].default.defined; # False say &f2.assuming(1)(); # 3 - loses default value of definite named parameters:
sub f2_2 ($a, Int:D :$b = 2) { $a + $b; } say &f2_2.signature.raku; # :($a, Int:D :$b = 2) say &f2_2.assuming(1).signature.raku; # :(Int:D :$b) say &f2_2.assuming(1).signature.params[0].default.defined; # False say &f2_2.assuming(1)(); # Parameter '$b' of routine '__PRIMED_ANON' must be an object instance of # type 'Int', not a type object of type 'Int'. Did you forget a '.new'? # ...
- removes default value of named parameters from signature of functions, but keeps its default value
- keeps the named parameter, even though the named argument was applied (roast says "Since you can override named params .assuming does not alter sig")
sub f3 ($a, :$b) { $a + $b; } say &f3.assuming(:b(2)).signature.raku; # :($a, :$b) say &f3.assuming(:b(2))(1, :b(3)); # 4 sub f4 ($a, :$b!) { $a + $b; } say &f4.assuming(1).signature.raku; # :(:$b!) say &f4.assuming(:b(2)).signature.raku; # :($a, :$b) say &f4.assuming(:b(2))(1, :b(3)); # 4 - removes parameter constraints from signature, but constraints are applied when partial function is called
sub f5 ($a, @b where .all ~~ Int) { [×] $a, |@b; } say &f5.signature.raku; # :($a, @b where { ... }) say &f5.signature.params[1].constraints.raku; # all(-> ;; $_ { #`(Block|73998640) ... }) say &f5.assuming(2).signature.raku; # :(@b) say &f5.assuming(2).signature.params[0].constraints.raku; # all() sub f6 ($a, &b:(Int :$c!)) { b c => $a; } say &f6.signature.raku; # :($a, &b where { ... }) say &f6.signature.params[1].constraints; # all(-> ;; $_ { #`(Block|77388240) ... }) say &f6.assuming(2).signature.raku; # (&b) say &f6.assuming(2).signature.params[0].constraints; # all() - doesn't set the type of a parameter whose type has been captured (roast mentions the design being incomplete), but its type will actually be checked
sub f7 (::T $a, T $b) { [×] $a, $b; } say &f7.assuming(2).signature.raku; # ($b) say &f7.assuming(2).signature.params[0].type; # (Any) - removes sub-signature from parameters, but type check will be done
sub f8 ($a, @b (Int $c, Str $d)) { [×] $a, $c, $d; } say &f8.signature.raku; # :($a, @b (Int $c, Str $d)) say &f8.signature.params[1].sub_signature.raku; # :(Int $c, Str $d) say &f8.assuming(2).signature.raku; # (@b) say &f8.assuming(2).signature.params[0].sub_signature.raku; # Signature
There might be other things I have not tried.
Another case:
2.2. loses default value of definite named parameters:
sub f2_2 ($a, Int:D :$b = 2) {
$a + $b;
}
say &f2_2.signature.raku;
# :($a, Int:D :$b = 2)
say &f2_2.assuming(1).signature.raku;
# :(Int:D :$b)
say &f2_2.assuming(1).signature.params[0].default.defined;
# False
say &f2_2.assuming(1)();
# Parameter '$b' of routine '__PRIMED_ANON' must be an object instance of
# type 'Int', not a type object of type 'Int'. Did you forget a '.new'?
# ...
In my view, these are all bugs – and should get much easier to solve with Raku AST (.assuming really wants to be a macro!) See this stack overflow question for some related discussion.