June 22, 2013 Re: What features of D are you using now which you thought you'd never goint to use? | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 06/23/2013 12:55 AM, H. S. Teoh wrote:
> On Sat, Jun 22, 2013 at 10:57:53PM +0200, Jacob Carlborg wrote:
>> On 2013-06-22 18:40, H. S. Teoh wrote:
>>
>>> Yeah that one made my eyes glaze over. I still have trouble wrapping my
>>> brain around the strange syntax of is(), and why its diverse uses have
>>> been shoehorned into deceptively similar syntax.
>>
>> Isn't quite a lot of the is-expression features undocumented?
> [...]
>
> Really? Well, even if so, the cases that *are* currently documented
> share a lot of syntax, but aren't necessarily related in a way that the
> syntax might imply. This is very confusing. One example that comes to
> mind is using is(T _ == U) instead of is(T == U). I'm guessing most
> people don't even know what the difference is, or why a dummy identifier
> _ has to be added.
>
>
> T
>
It's not a dummy identifier. It introduces _ as an alias to T if used inside a static if condition. Otherwise there is no difference.
void main(){
static if(is(int _ == int)){
_ x;
}
static assert(is(typeof(x)==int));
}
I don't know what the point of this feature is.
There used to be the issue that some forms of is were only available when the alias identifier was used. This has been fixed.
|
June 23, 2013 Re: What features of D are you using now which you thought you'd never goint to use? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 6/22/13 2:58 PM, monarch_dodra wrote:
> long story short: we don't have rfind. C++ does.
We do, just that it's for random-access ranges. C++ offers it for bidirectional ranges too. We could of course support it if bidirectional ranges were required to have something like r1.before(r2) that, assuming r2 is reachable from r1, returns the portion in r1 that's before r2.
Andrei
|
June 23, 2013 Re: What features of D are you using now which you thought you'd never goint to use? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr Attachments:
| On Sat, Jun 22, 2013 at 4:15 PM, Timon Gehr <timon.gehr@gmx.ch> wrote: > On 06/23/2013 12:55 AM, H. S. Teoh wrote: > >> On Sat, Jun 22, 2013 at 10:57:53PM +0200, Jacob Carlborg wrote: >> >>> On 2013-06-22 18:40, H. S. Teoh wrote: >>> >>> Yeah that one made my eyes glaze over. I still have trouble wrapping my >>>> brain around the strange syntax of is(), and why its diverse uses have been shoehorned into deceptively similar syntax. >>>> >>> >>> Isn't quite a lot of the is-expression features undocumented? >>> >> [...] >> >> >> Really? Well, even if so, the cases that *are* currently documented share a lot of syntax, but aren't necessarily related in a way that the syntax might imply. This is very confusing. One example that comes to mind is using is(T _ == U) instead of is(T == U). I'm guessing most people don't even know what the difference is, or why a dummy identifier _ has to be added. >> >> >> T >> >> > It's not a dummy identifier. It introduces _ as an alias to T if used inside a static if condition. Otherwise there is no difference. > > > void main(){ > static if(is(int _ == int)){ > _ x; > } > static assert(is(typeof(x)==int)); > } > > I don't know what the point of this feature is. > > There used to be the issue that some forms of is were only available when the alias identifier was used. This has been fixed. > if that the case can we add it to http://dlang.org/deprecate.html (as 'future' deprecation)? |
June 23, 2013 Re: What features of D are you using now which you thought you'd never goint to use? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Sunday, 23 June 2013 at 01:34:53 UTC, Andrei Alexandrescu wrote:
> On 6/22/13 2:58 PM, monarch_dodra wrote:
>> long story short: we don't have rfind. C++ does.
>
> We do, just that it's for random-access ranges. C++ offers it for bidirectional ranges too. We could of course support it if bidirectional ranges were required to have something like r1.before(r2) that, assuming r2 is reachable from r1, returns the portion in r1 that's before r2.
>
> Andrei
That sounds like exactly what I needed for a version of toUpper I was playing with that added support for output ranges.
The implementation is rather trivial:
Writer toUpper(S, Writer)(S s, Writer w) @trusted
if(isSomeString!S)
{
size_t count = 0;
foreach (c, i; s)
{
if (std.uni.isLower(c))
{
c = std.uni.toUpper(c);
}
put(w, c);
count = i;
}
return w;
}
Works just fine with something like Appender. The problem is that if you pass in dynamic or static array slice to store the result in you have no way of knowing how much of the target array was filled by the function. You could use save() and keep track of how many bytes were consumed and return a slice of that size but that feels very clunky (and could be tricky to implement correctly if the input string is a different encoding than the output range).
|
June 23, 2013 Re: What features of D are you using now which you thought you'd never goint to use? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Saturday, 22 June 2013 at 20:09:01 UTC, monarch_dodra wrote:
> #2: Extremelly bad compatibility with simple no bidir/non-slicing ranges: There is no way to iterate over a specific part of a range, and making a range out of what was just iterated over. For example "Get the beggining of this range until the first x": not possible without slicing.
Not sure if I understood the question correctly, but the way I understood it:
1) To iterate over a specific part of a non-random-access range, you can use `drop` in conjunction with `take` or `takeExactly`.
2) To get an existing foreach loop to emit a range, move its body to the predicate of `map`, and break conditions to the predicate of `until` / `countUntil`.
3) As I understand, "get the beggining of this range until the first x, without slicing" is what `until` (or `countUntil` + `take`) does.
|
June 23, 2013 Re: What features of D are you using now which you thought you'd never goint to use? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | On Sunday, 23 June 2013 at 04:08:22 UTC, Vladimir Panteleev wrote:
> On Saturday, 22 June 2013 at 20:09:01 UTC, monarch_dodra wrote:
>> #2: Extremelly bad compatibility with simple no bidir/non-slicing ranges: There is no way to iterate over a specific part of a range, and making a range out of what was just iterated over. For example "Get the beggining of this range until the first x": not possible without slicing.
>
> Not sure if I understood the question correctly, but the way I understood it:
>
> 1) To iterate over a specific part of a non-random-access range, you can use `drop` in conjunction with `take` or `takeExactly`.
>
> 2) To get an existing foreach loop to emit a range, move its body to the predicate of `map`, and break conditions to the predicate of `until` / `countUntil`.
>
> 3) As I understand, "get the beggining of this range until the first x, without slicing" is what `until` (or `countUntil` + `take`) does.
All of these will *iterate* over part of said range, but none will actually return the subrange I iterated on.
V
[ . . X . . . . . . . . ]
I want:
[ . . X ]
D gives me:
[ X . . . . . . . . ]
countUntil + take can kind of mitigate the problem, but that warps the type system: The type of take is not the type of the range.
|
June 23, 2013 Re: What features of D are you using now which you thought you'd never goint to use? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Sunday, 23 June 2013 at 09:10:03 UTC, monarch_dodra wrote: > All of these will *iterate* over part of said range, but none will actually return the subrange I iterated on. `until` does not iterate, it simply returns a range which ends when your condition is satisfied. > V > [ . . X . . . . . . . . ] > > I want: > [ . . X ] Isn't this what `until` does? > countUntil + take can kind of mitigate the problem, but that warps the type system: The type of take is not the type of the range. I believe wrapper ranges like `take` return ranges with the same capabilities as the ranges they wrap. This modularity design assumes that you will use the result in functions that accept ranges, i.e. templated functions that expect that the types of their parameters satisfy the is*Range constraints. To avoid misunderstanding or miscommunication, could you post the practical problem you encountered, with context? |
June 23, 2013 Re: What features of D are you using now which you thought you'd never goint to use? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | On Sunday, 23 June 2013 at 09:44:09 UTC, Vladimir Panteleev wrote: > On Sunday, 23 June 2013 at 09:10:03 UTC, monarch_dodra wrote: >> All of these will *iterate* over part of said range, but none will actually return the subrange I iterated on. > > `until` does not iterate, it simply returns a range which ends when your condition is satisfied. "Lazily iterates range until value sentinel is found, at which point it stops." >> V >> [ . . X . . . . . . . . ] >> >> I want: >> [ . . X ] > > Isn't this what `until` does? Not quite, it returns an object that returns those items when iterated on. But it is not the same type. >> countUntil + take can kind of mitigate the problem, but that warps the type system: The type of take is not the type of the range. > > I believe wrapper ranges like `take` return ranges with the same capabilities as the ranges they wrap. This modularity design assumes that you will use the result in functions that accept ranges, i.e. templated functions that expect that the types of their parameters satisfy the is*Range constraints. Same capabilities, different types. > To avoid misunderstanding or miscommunication, could you post the practical problem you encountered, with context? The problem always boils down the fact that while we can get the same iteration scheme, it's never the same range type: Range r = some_range; r = r.until!"a == 5"; //Does not compile Until!Range and Range do not match r = r.take(5); //Does not compile: Take!Range and Range do not match |
June 23, 2013 Re: What features of D are you using now which you thought you'd never goint to use? | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On Sunday, 23 June 2013 at 09:54:56 UTC, monarch_dodra wrote: >> Isn't this what `until` does? > > Not quite, it returns an object that returns those items when iterated on. But it is not the same type. OK, I think we had a misunderstanding what "iterate" meant. I used it in the meaning "iterate the range at the time of the call" as opposed to "return a range that, when iterated, iterates its parameter". > The problem always boils down the fact that while we can get the same iteration scheme, it's never the same range type: > > Range r = some_range; > r = r.until!"a == 5"; //Does not compile Until!Range and Range do not match > r = r.take(5); //Does not compile: Take!Range and Range do not match So is it all about reusing a variable? For this, you can use the InputRange interface, and the InputRangeObject template which creates a crass type that inherits from the InputRange interface. Of course, since what you are requesting is essentially runtime polymorphism, this will come with a performance cost of a virtual method call for every range primitive. |
June 23, 2013 Re: What features of D are you using now which you thought you'd never goint to use? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Vladimir Panteleev | On Sunday, 23 June 2013 at 10:37:34 UTC, Vladimir Panteleev wrote:
>> The problem always boils down the fact that while we can get the same iteration scheme, it's never the same range type:
>>
>> Range r = some_range;
>> r = r.until!"a == 5"; //Does not compile Until!Range and Range do not match
>> r = r.take(5); //Does not compile: Take!Range and Range do not match
>
> So is it all about reusing a variable?
It's a bit more than that, it's also about limiting template bloat. For example:
R range;
auto r3 = findSplit(range);
void do_it(r3[0]);
void do_it(r3[1]);
void do_it(r3[2]);
This will actually instantiate 2 different do_it functions. This might sound trivial, but these things scale.
It also means iteration will be more expensive than necessary (take will compare both length and empty).
Also, and this is subtle: If you use take, your range will have a fixed size, whereas a "true" bidirectional range will be defined by a start and end point. For example, with the above find split, taken from a DList:
If I add elements to the DList, a DList.Range will "grow" to accomodate new elements that where inserted between its bounds. Take!(DList.Range), on the other hand, will *not* grow, and as elements are inserted, the back elements will be pushed outside of the Range.
It might not sound like much, but have you *tried* using DList? Or writing an algo meant to specifically exploit DList mechanics? With ranges, it just doesn't really work quite as well as it should...
|
Copyright © 1999-2021 by the D Language Foundation