between and among: worth Phobosization?
Chris Cain
clcain at uncg.edu
Tue Dec 17 13:29:22 PST 2013
On Tuesday, 17 December 2013 at 18:06:27 UTC, Andrei Alexandrescu
wrote:
> That's problematic. "Between" is a preposition. Naming a
> function as a preposition is fine as long as a verb is implied
> (e.g. "a in b" really means "a _is_ in b", or "a.between(b, c)"
> really means "a _is_ between b and c" etc).
I see... interesting. But this doesn't suggest that the concept
is bad, just the name.
> "x in between(2, 7)" is cute but just that - it's a lucky
> strike that relies on word ordering in a particular phrase and
> is unlikely to work in many other places.
I agree it's cute and just lucky. I'm not attached to the name,
but I'd like some sort of name that evokes the purpose like that
does (as an example of something I wouldn't like reading, `x in
iota(2, 7)` ...)
> Reifying "between" to the status of object is weird. One
> constructs a "between" object and then what are its primitives?
> How can one even talk about it? "Yeah I have a between here and
> I copy it to another between"...
To be honest, I'm just the kind of person to come up with very
weird ideas, so it's not surprising people might find my idea
weird. It doesn't necessarily have to be called "between" but
some sort of object (being able to contain the state is
important) could contain the concept of a range of values
("inclusive lowerbound", "exclusive upperbound", support things
like "opIn" or an opCall to test a value for membership). It'd
also be needed for it to have a simple way to get the smallest
acceptable type for the range of values the "between" object
could represent. So a for a Between!(uint, int) that would be a
uint, and a Between!(int, uint) that would be a long, and so on.
Obviously some things _don't_ have acceptable types, such as a
Between!(long, ulong) (no integral type currently can actually
hold all of those values).
Something like this, like I showed, could be used to pass to
other functions like std.random.uniform which request a range to
generate. Or you should be able to pass it to something like
std.algorithm.find, std.algorithm.count, etc (predicates that
take one parameter).
On Tuesday, 17 December 2013 at 01:02:28 UTC, Chris Cain wrote:
> but its main value would probably come improved readability and
> reduced code duplication
Actually, I thought about this a bit more and its value might be
greater than previously thought... what about the issues people
have with unsigned vs signed comparisons? (consider, someone in
this very topic corrected your proposed code because of this very
issue):
---
int a = -1;
uint b = 0;
assert(a < b); // oops, fails.
---
This isn't a new revelation or anything, and the solution, of
course, is to do more complex tests like `assert(a < 0 || a <
b);` but the compiler doing those sorts of things automatically
is questionable. Instead, covering the use-cases with
functions/objects like `between` where template magic can insert
these extra tests automatically might be a viable strategy.
And as another example of something falling prey to this
"unexpected" behavior, look no further than the example I've
already given: std.random.uniform ...
---
writeln(uniform(-1, 1u));
// std.random.uniform(): invalid bounding interval [-1, 1)
// Wat?
foreach(_; 0..5) {
writeln(uniform(-2, uint.max));
// Oops! Always prints out 4294967294
// as if the bounding interval was [-2u, -1u)
}
---
https://d.puremagic.com/issues/show_bug.cgi?id=11758
These types of things are apparently very common issues. Having
an object encapsulating the behavior needed to check this stuff
and using it is preferable to reimplementing the checks each time
(and potentially failing each time in subtle ways).
More information about the Digitalmars-d
mailing list