Skip to content
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

Fix issue #13352 - Only perform Algebraic arithmetic with allowed types. #2452

Merged
5 commits merged into from
Sep 11, 2014

Conversation

s-ludwig
Copy link
Member

Adds a static check allowed!T before trying any particular numeric type. Also checks for an exact type match in case of a raw (non-Variant) operand and prefers that to one of the fixed numeric types. Finally, it loosens the restriction for opArithmetic to only work for equal Variant types.

https://issues.dlang.org/show_bug.cgi?id=13352

@s-ludwig
Copy link
Member Author

Hm, it seems like the rest of VariantN uses assert(false) instead of throwing exceptions. Although that feels a little fragile, that probably means that I should be doing that in opArithmetic, too. Any thoughts?

@s-ludwig
Copy link
Member Author

Ah scratch that, there is VariantException used for this in several places.

@bearophile
Copy link

I think it's not a good idea to allow arithmetic operations among values of Algebraic types. I think functional languages don't do that because it muddles the semantics of what an Algebraic data type is.

@yebblies
Copy link
Member

I think it's not a good idea to allow arithmetic operations among values of Algebraic types. I think functional languages don't do that because it muddles the semantics of what an Algebraic data type is.

It you think of Algebraic as a restricted Variant then it makes sense.

@bearophile
Copy link

I want to pattern match with a switch on an Algebraic. I don't want to read code written by other people where there's a + among two Algebraic values.

Please take a look at what an algebraic data type is, its purposes, look at how they are used and meant in functional languages like Haskell and ML where they are native, and don't add random features to them just because you can in D.

Sometimes the point of a language (or library) construct comes from what you can't do with it (like you can't mutate a const, can't print from a pure function, etc).

@s-ludwig
Copy link
Member Author

The thing is that this is already possible and I don't see that it's going to be removed. Based on that I think that crippled support for such operations is worse than one with clean semantic rules (even if even with this pull request they are still far from perfect).

Apart from that, there are use cases where such behavior is definitely desired (JSONValue), but maybe there should have been two distinct types with one possibly based on the other one. What I'd also really like to have is a kind of TaggedAlgebraic (maybe there is a better name) with a type ID that can be used with switch for pattern matching.

@s-ludwig
Copy link
Member Author

BTW, what's up with the autotester, It seems to just constantly retest everything since many hours. The same seems to be true for most other open pull requests. @braddr, any idea, or is this normal behavior?

@quickfur
Copy link
Member

AFAIK, whenever any of dmd, druntime, or phobos changes (nowadays basically due to PR merges), the autotester will restart from scratch. I suppose the idea is to ensure that test results are always with the latest bleeding-edge toolchain, and that automerges don't introduce problems into the repos because a code conflict or incompatibility arises between a recently-merged PR and a PR being automerged, that the autotester would miss if it didn't reset everything after each merge.

@mihails-strasuns
Copy link

Yes, this is the case. You can open "Details" to see if there were failures in build history though.

@mihails-strasuns
Copy link

I agree with @s-ludwig about this - while strict tagged union based algebraic type for pattern matching may be interesting addition, changing anything fundamental about existing implementation is not an option and needs to be as good as possible in already defined niche. That PR does the right thing in my opinion.

If anything I am more concerned about new restrictions breaking any of existing code. Are there any cases where it did compile before (even if worked wrong) and won't after the PR is merged?

@s-ludwig
Copy link
Member Author

I'm relatively sure that it should only extend the type combinations that work. Cases that before failed for sure, because the result was a !allowed!T type, can now fall back to another, possibly allowed type.

The future direction should probably be to extend the code, so that it iterates over the actual types of the Algebraic instead of just trying the built-in numeric types. But that needs some care so that the priority and ambiguity rules of the language are properly mirrored.

@quickfur
Copy link
Member

quickfur commented Sep 4, 2014

ping
Should we merge this?

@mihails-strasuns
Copy link

This is in dire need of more reviewers (change is not trivial) @DmitryOlshansky @monarchdodra @JakobOvrum ?

@DmitryOlshansky
Copy link
Member

I recall looking at this PR before and overall I like it. Will re-review later today.

string tryUseType(string tp) {
import std.string : format;
return q{
static if (allowed!%s && T.allowed!%s)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use %1$s for the format specifier everywhere and then pass tp only once.

Adds a static check allowed!T before trying any particular numeric type. Also checks for an exact type match in case of a raw (non-Variant) operand and prefers that to one of the fixed numeric types. Finally, it loosens the restriction for opArithmetic to only work for equal Variant types.

Conflicts:
	std/variant.d
@ghost
Copy link

ghost commented Sep 10, 2014

Ok, it LGTM now. Anyone else have comments?

@mihails-strasuns
Copy link

Still LGTM :)

result = mixin("get!(double) " ~ op ~ " other.get!(double)");
else
result = mixin("get!(real) " ~ op ~ " other.get!(real)");
string tryUseType(string tp) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use the Phobos bracket style

@ghost
Copy link

ghost commented Sep 11, 2014

Auto-merge toggled on

ghost pushed a commit that referenced this pull request Sep 11, 2014
Fix issue #13352 - Only perform Algebraic arithmetic with allowed types.
@ghost ghost merged commit 67db0d6 into dlang:master Sep 11, 2014
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants