-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AddSet, UniteSet, etc. could give more helpful error message if the list argument is not mutable #3597
Comments
The error message could be better, but this is correct behaviour. |
I think AddSet, RemoveSet, UniteSet etc. etc. should explicitly check for the first argument being immutable, and then print an appropriate error message. |
Would it be reasonable to extend method selection to say things like "The first argument must not be immutable", if the first argument always requires immutable, and the object isn't immutable? Then we wouldn't need to special-case certain methods. I haven't thought carefully about how reasonable this would be. |
@ChrisJefferson We could attempt to give better error messages for all no method found calls based on the declaration(s) of the Operations. So if every declaration requires argument As an alternative, we could do the same thing based on installed methods -- if every method requires |
The problem with such a general approach is that it only really works if the involved filters are really "simple", like e.g. just Perhaps a general solution would be useful, but in this case, I think we should perhaps start with a much simpler solution -- e.g. installing methods for those operations that apply to arbitrary lists, and which check for mutability, and for immutable inputs print the desired error (and otherwise do That should be fairly easy to implement, too. |
Thought about it some more; one way to make this generic along the lines @stevelinton suggests would be to introduce a function which can "describe" arbitrary filters. Here is some sample code which shows a way this could be implemented. filterDesc:=[];
# format of entries: if a filter with flags [f1, f2, f3] gets a description,
# then we add an entry to filterDesc[i] where i ranges over f1,f2,f3 of the form [ [f1,f2, f3], desc ]
# Then
AddFilterDesc := function(filter, desc)
local tf, n, i;
tf := TRUES_FLAGS(FLAGS_FILTER(filter));
Assert(0, IsSet(tf));
for n in tf do
if IsBound(filterDesc[n]) then
i := PositionProperty(filterDesc[n], x -> x[1] = tf);
if i <> fail then
Error("a description for filter ", filter, " has already been set");
fi;
else
filterDesc[n] := [];
fi;
AddSet(filterDesc[n], [tf, desc]);
od;
end;
AddPropertyDesc := function(prop, desc)
Assert(0, IsProperty(prop));
AddFilterDesc(prop, desc);
AddFilterDesc(Tester(prop), Concatenation("know if it is ", desc));
end;
# TODO: extend the following; possibly also extend DeclareCategory, DeclareFilter,
# DeclareProperty, ... to take this kind of description as an extra argument
AddFilterDesc(IsList, "a list");
AddFilterDesc(IsMutable, "mutable");
AddPropertyDesc(IsFinite, "finite");
# turn a filter into a list of strings...
DescribeFilter:=function(filter)
local tf, desc, n, candidates;
tf := Set(TRUES_FLAGS(FLAGS_FILTER(filter)));
desc := [];
while Length(tf) > 0 do
n := Last(tf);
if IsBound(filterDesc[n]) then
candidates := Filtered(filterDesc[n], x -> IsSubset(tf, x[1]));
if Length(candidates) > 0 then
# TODO: if there is more than one candidate, pick one, but how???
# prefer those with more flags over those with fewers?
# how to deal with a tie?
# ideally these issues should be prevented by having most descriptions
# apply only to filters with very few flags (1 or 2)
SortBy(candidates, x -> -Length(x[1]));
if Length(candidates) > 1 then
#Error("TODO: more than one candidate\n");
fi;
Add(desc, candidates[1][2]);
SubtractSet(tf, candidates[1][1]);
continue;
fi;
fi;
# last resort: use filter name
Add(desc, String(FILTERS[n]));
RemoveSet(tf, n);
od;
return desc;
end;
# example:
filter:=IsList and IsMutable and IsFinite;
desc:=DescribeFilter(filter);
# we can now combine this in various ways, e.g.
msg := Concatenation("First argument must be ", JoinStringsWithSeparator(desc, " and ")); |
Observed behaviour
Copy and paste GAP banner (to tell us about your setup)
The text was updated successfully, but these errors were encountered: