Iota

Steven Schveighoffer schveiguy at gmail.com
Fri Aug 5 00:12:40 UTC 2022


On 8/4/22 3:06 PM, H. S. Teoh wrote:
> On Thu, Aug 04, 2022 at 05:52:46PM +0000, Paul Backus via Digitalmars-d wrote:
>> On Thursday, 4 August 2022 at 16:28:14 UTC, React wrote:
>>> What I want to highlight, it's the fact that iota seems flawed: it
>>> assumes that every type supporting increment operators will generate
>>> a nice, consecutive, ordered sequence of values.
>>>
>>> Iota specialises on floating point values exactly because of the
>>> problem above, but assumes that *any* other type will nicely behave
>>> as long you can put a ++ near a value.
>>>
>>> We can ignore the hypotetical situation in which someone will find
>>> an unusual usage of ++ (probably there is one person that never
>>> imagined that << can be used for console output), but we already
>>> have a candidate where iota will fail: CustomFloat from std.numeric.
>>
>> Yeah, this is a classic case of what Andrei calls ["generality
>> creep"][1].
>>
>> You start out with the obviously-correct core functionality. Then you
>> start gradually extending it to handle new edge cases. Each one seems
>> reasonable enough on its own, but by the end of the process, you find
>> yourself with an API that's complex and hard to use, wondering where
>> it all went wrong.
>>
>> [1]: https://forum.dlang.org/thread/q6plhj$1l9$1@digitalmars.com
> 
> I'm probably partly to blame for this. :-/   Cf.:
> 
> 	https://issues.dlang.org/show_bug.cgi?id=6447
> 
> After thinking about this, I think in its barest essentials, the only
> version of iota we need is the one that takes a single int argument, and
> that generates that many numbers, starting from 0.  Everything else can
> be built on top of this with other existing library functions.
> 
> For example, if you want a range that starts from 10 and ends at 20,
> just write:
> 
> 	iota(10).map!(i => i + 10)
> 
> If you want a range that starts at 3 and steps by 5 each time, just write:
> 
> 	iota(n).map!(i => 3 + i*5)
Sorry, I'd rather specify the start, end, and steps, then have to work 
backwards from the formula what it means. Clarity is important.

Also important is not making the compiler do extra calculations (or the 
optimizer) when it doesn't have to. A mapping might correctly express 
intent, but might also fool the optimizer from using a better path that 
++ or += would use.

As for the floating point thing, `foreach(i; 0.5 .. 7.6)` works, it 
should too for `iota`.

-Steve


More information about the Digitalmars-d mailing list