Replies: 6 comments 22 replies
-
If this is a poll, I am voting for 3). PS.: I think the union splitting is very efficient for the case it was implemented for, namely for the temporary variables introduced during iteration, where the variable of union type is located in a very small section of the code. For variables spread over the whole function and interaction between variables of type function h(x)
f = rand() < 0.5 ? sin : cos
g = rand() < 0.5 ? cos : tan
return f(x) + g(x)
end # this will infer ok
function h(x)
f = rand() < 0.5 ? sin : cos
g = rand() < 0.5 ? cos : tan
return [f(i) + g(i) for i in 1:x]
end # this won't |
Beta Was this translation helpful? Give feedback.
-
Could you not avoid breaking type stability by passing callback functions? In your examples something like function do_something_with_iso
function do_something_with_nonisomorphic
function is_isomorphic(G,H, do_something_with_iso, do_something_with_nonisomorphic)
[...]
if are_isomorphic
return do_something_with_iso(G,H, ISO)
else
return do_something_with_nonisomorphic(G,H)
end
end I am unsure whether one can require an exact signature for the functions passed as arguments (but probably one can?). I also want to remark that it is possible for certain functions to have different algorithms depending on whether one only wants to know the bool or also the auxiliary information. |
Beta Was this translation helpful? Give feedback.
-
There are no really good options here:
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
So right now I am trying to apply this to the function
This leaves the question how to deal with corner cases, once in
Of course the answers may differ for the two functions:
Aaaanyway: for now I will follow the precedent we set with
Sounds OK? |
Beta Was this translation helpful? Give feedback.
-
On Tue, May 24, 2022 at 12:31:18AM -0700, Max Horn wrote:
Not really, other in "trivial" cases, but I mean, the trivial group is trivial to handle with anyway, no need to apply p-group code to it.
Anyway, for `prime_pgroup` it's clear to me that the trivial group should just give an error.
Now if the trivial group can pop up and results in an error when calling `is_pgroup_with_prime` on it, then some code may need to add checks like `is_trivial(G)` before that. Which of course is not a major issue, just slightly inconvenient.
But what about non-trivial non-pgroups? What should the second return value for `is_pgroup_with_prime` be? If we don't want a "fake prime" like 0 here, what else then? (to be clear: I am not a fan of "fake" return values either -- likewise the non-bijective homomorphism returned by `is_isomorphic_with_map` is also borderline for me).
Perhaps the answer in this case is to simply not bother with `is_pgroup_with_prime`, as there is no cost saving for using it over `is_pgroup` plus `prime_pgroup` anyway? Alas, that this is so is kind of an implementation detail, so I am slightly wary about settling on that...
The convention (or my understandanding) is that
is_..._with_...
has 2 cases
true + meaningful
false + garbage
historically, for type stability, garbage had to ave the correct type
(hence fake primes and similar - and I was bitten by it as I ignored the
false...)
If julia is up to it, I'd be happy with false + nothing
But the key point is to, mostly, not throw errors but return false
… --
Reply to this email directly or view it on GitHub:
#1348 (reply in thread)
You are receiving this because you commented.
Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
We have all kinds of computations that "naturally" (based on the name) return one value, but for applications one often really wants multiple return values... But we have different conventions for these. It would be good to agree on a common scheme!
To this end, I'll try to describe the primary variants I am aware of with examples. Note that these are not always mutually exclusive, nor can every one applied in every case.
At the end I'll write some of my personal thoughts. I hope for feedback and opinions by everyone, though!
always return the "optional" return values: we used to do this for
is_isomorphic
, and e.g.is_pgroup
still always returns a pairbool, hom
is_pgroup
just return a boolean?")keyword arguments: e.g.
direct_sum
for modules: takes a keyword argumenttask::Symbol
which indicates what to return: it always returns the direct sum as a module; and then either nothing more; or the injection maps; projection maps; or both injections and projections.task
must be coordinated between all implementations (and it currently isn't, at least according to the doc string). This can be addressed in principle (e.g. by setting a globalconst default_direct_sum_task = :none
or so and using it everywhere; or by renaming the existingdirect_sum
methods to, say,direct_sum_internal
and then adding a single frontenddirect_sum
method which delegates todirect_sum_internal
but determines the default value), though neither options seems particularly nice?multiple functions:
is_isomorphic
returns just a boolean, if one also wants the isomorphism, useis_isomorphic_with_map
is_isomorphic
can be added which just callsis_isomorphic_with_map
and discards the second return value (simplifies implementations), while it is still possible to provide an optimized version that does not bother to compute an actual homomorphism (e.g. if both groups have same order and it is prime, they must be isomorphic...)false, nothing
which breaks type stability, but arguably is nicer for the user (and still not too bad, as Julia is quite good at splitting Union types over just two types)direct_sum
,direct_sum_with_injections
,direct_sum_with_projections
,direct_sum_with_injections_and_projections
d, i, p
ord, p, i
is returned)allow returning
nothing
: as a variant to the previous point, one can also decide that a function likeisomorphism(G, H)
should be allowed to return a special value (typicallynothing
) in case no isomorphism exists.is_pgroup
,is_isisomorphic
but not fordirect_sum
)use exceptions: of course
isomorphism(G,H)
could also throw an exception of there is no isomorphism. But exceptions are very expensive. But this is still a good option for functions where the failure mode is very rare, or does not matter to "typical" callers (but what is that? Hmm), or if the function is very expensive anyway (isomorphisms for groups quickly get very expensive; but of course if you only deal with tiny ones, that might be different)... more?
Here are my personal thoughts:
is_FOO
functions returning anything besides a boolean, that's confusing; so I'd like to get rid of thesenothing
, so this is also a great option from my POVBeta Was this translation helpful? Give feedback.
All reactions