let's talk about output ranges
Adam D. Ruppe
destructionator at gmail.com
Thu Feb 6 08:21:51 PST 2014
splitting from the ARC thread
On Thursday, 6 February 2014 at 15:47:48 UTC, Johannes Pfau wrote:
> As they do not keep references there's no need for ARC or GC,
> we just need a way to tell every function how it should
> allocate.
yea. I think it is time we hashed out output ranges the same way
we've done with input ranges. Right now, output ranges just have
put(T). I think it would be useful to add extensions similarly to
random access ranges, infinite ranges, etc..
What I want to see work is:
char[3] buffer;
char[] got = toLowerWithRange(buffer, "FOO"); // if we allow it
w/o slicing
assert(got.ptr is buffer.ptr);
assert(got == "foo");
char[] got = toLowerWithRange(buffer, "FOOL"); // throws, out no
more space
char[] got = toLowerWithRange(buffer[], "FOO"); // same result as
above
char[] got = toLowerWithRange(buffer[], "FOOL"); // MAyBE
reallocates
(I call it toLowerWithRange just to avoid any overloading
ambiguities when reusing the toLower name. Names aren't important
to me though.)
What do we have here? When passed a static array, it must not
grow beyond its length - the only allocation allowed is the
exception it throws.
When passed a slice though, things are a bit more interesting. I
think then it should try to put it directly in the slice, but if
that isn't possible, go ahead and reallocate.
Though that's not necessarily sane either. Maybe slice should
also throw if there isn't enough room.
toLower would prolly just call put(), with std.array or std.range
defining it for static vs dynamic arrays.
With user defined types, this behavior would be tweakable,
similarly to how input ranges might hasLength!T. Other
similarities:
* A slice should also be a random access output range. Not all
values are generated in order, one char at a time.
* Allocators should *offer* output ranges, but not necessarily
*be* output ranges, similarly to the relationship between
containers and input ranges (a view into the container). This
could argue that passing a static buffer without slicing it is
wrong
* We want this stuff to just work without a bajillion explicit
wrappers, again, like input ranges.
* Output ranges would probably make the most sense to pass places
by ref (as is the case with them most the time right now).
Eh, I gotta go, but let's start talking about this.
BTW for the growable thing, I wrote this little array thingy:
http://arsdnet.net/dcode/array2.d
it uses a static buffer up to an estimated size, then switches to
GC. The idea being it can use infinite length, but for the
majority of the input, uses stack space and thus avoids
allocating at all. I'd like to see this thing be easy to use with
phobos functions (perhaps with some additions but the same basic
idea) as I find this pattern of guessing with a prealloced stack
buffer very useful.
> Exceptions currently can't work on a system without GC cause we
> always use 'throw new' and nobody ever explicitly frees
> Exceptions.
Exceptions only come in exceptional circumstances anyway, so I
think they are ok to be an... exception. LOL
but seriously, the exception path is rarely fully optimized in
the first place. If you want to avoid them, use nothrow or
preallocate them or something.
More information about the Digitalmars-d
mailing list