Skip to content

Issue 6447 & 10762: support user-defined types in iota() #2895

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

Merged
merged 4 commits into from
Jan 26, 2015

Conversation

quickfur
Copy link
Member

Fixes: https://issues.dlang.org/show_bug.cgi?id=6447
Partially fixes: https://issues.dlang.org/show_bug.cgi?id=10762

Basically, as long as a type supports comparison via < and incrementing via ++, iota should work.

This is an initial stab at issue 10762; it provides the baseline for the most general user-defined types, so the returned range for non-built-in types will only be input ranges. Subsequent PRs will gradually refine this, e.g., to support random access if x + y*k is a supported operation in the underlying type.

H. S. Teoh added 2 commits January 22, 2015 09:50
Add Params:. Use Returns:.

Include previously-overlooked overload that broke a ddoc'd unittest.
@PetarKirov
Copy link
Member

Maybe it's a bit of an overkill, but have you considered using begin != end when opCmp is not available for the common type? For example in C++, != is used predominantly for iterators. I may be wrong, but I think equality is a more generic relation (or at least easier to support).

@PetarKirov
Copy link
Member

Apart from that, LGTM. I especially find the documentation more readable now 👍

@quickfur
Copy link
Member Author

I did consider using begin != end but decided against it in case the user type in question is a custom float and you're trying to do iota(1.0, 2.5), so begin != end will never be true.

@quickfur
Copy link
Member Author

One alternative is to use < when it's available, but fall back to != otherwise.

@PetarKirov
Copy link
Member

in case the user type in question is a custom float

That's a good point. Though, I think that if your are using custom floats you may accumulate a larger error with this version, than with specialized one, which directly returns start + step * index in front() (index is an integer), instead of incrementing start.

One alternative is to use < when it's available, but fall back to != otherwise.

OK, let's use != only as a fall back.

@quickfur
Copy link
Member Author

Well, the idea is that this is just the most general, basic implementation. Later on, the plan is to extend it to take advantage of types that provide multiplication -- not only that will eliminate accumulation of roundoff errors, it will also allow us to return a random-access range instead of just an input range.

@quickfur
Copy link
Member Author

There's also the case of detecting when a type supports +=, and allowing the step parameter in that case.

if (!isIntegral!(CommonType!(B, E)) &&
!isFloatingPoint!(CommonType!(B, E)) &&
!isPointer!(CommonType!(B, E)) &&
is(typeof(++B.init)) &&
Copy link
Member

Choose a reason for hiding this comment

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

this spells trouble if B.init is an rvalue

Copy link
Member

Choose a reason for hiding this comment

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

there was a pull request for lvalueInit

Copy link
Member Author

Choose a reason for hiding this comment

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

Which PR was that?

@andralex
Copy link
Member

what's with the failures?

@quickfur
Copy link
Member Author

No idea, I saw outbuffer failures on somebody else's unrelated PR too. Some kind of intermittent bug that somehow slipped into the code maybe?

@quickfur
Copy link
Member Author

Fixed to use ref.

@yebblies
Copy link
Member

No idea, I saw outbuffer failures on somebody else's unrelated PR too. Some kind of intermittent bug that somehow slipped into the code maybe?

That was #2902

@quickfur
Copy link
Member Author

Ah, so that's what it was.

@quickfur
Copy link
Member Author

The autotester is now green. Anything else that needs to be fixed?

@andralex
Copy link
Member

OK, that's a good first step. I keep on thinking we should define abstract algebra paraphernalia like isGroup, isMonoid, etc.

@andralex
Copy link
Member

Auto-merge toggled on

andralex added a commit that referenced this pull request Jan 26, 2015
Issue 6447 & 10762: support user-defined types in iota()
@andralex andralex merged commit b159a5b into dlang:master Jan 26, 2015
@quickfur quickfur deleted the iota_bigint branch January 26, 2015 17:58
@quickfur
Copy link
Member Author

@andralex The problem with that is, some things can't be tested at compile-time, e.g., isAbelian can't be feasibly implemented without code introspection. Also, how would you categorize a type that supports ++x but not x+y?

@quickfur
Copy link
Member Author

If we don't stick to abstract algebra, though, I suppose we could usefully have templates like isIncrementable, isAssignAddable, etc.. But I'd be hard-pressed to find use cases for most of these outside of iota.

@JakobOvrum
Copy link
Member

But I'd be hard-pressed to find use cases for most of these outside of iota.

Although I'm not necessarily arguing for their inclusion, they would be useful for std.range.enumerate too (#1866).

@quickfur
Copy link
Member Author

Hmm. Maybe it's worth adding, then. If nothing else, it would make the sig constraints more readable...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants