April 24, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 4/24/20 4:24 AM, Walter Bright wrote:
> On 4/23/2020 11:00 PM, Manu wrote:
>> I guess this is the key case you need to solve for:
>>
>> template T(Args...) {}
>> T!(Tup) -> T!(0, 1, 2)
>> T!(Tup)... -> T!0, T!1, T!2
>>
>> And the parallel expansion disambiguation is also critical:
>> T!(Tup, Tup2...)... -> T!(0, 3, 4, 5), T!(1, 3, 4, 5), T!(2, 3, 4, 5)
>>
>> If you can solve those, the rest will probably follow.
>
> Fair enough. Though there needs to be a rationale as to why those two particuler cases are needed and critical.
I think there's a fundamental piece missing from the requirements, you need to be able to specify where the expansion should stop. Otherwise, the expressions become very difficult to use effectively.
e.g.:
T!(U!(V!(Tup))...) -> T!(U!(V!0), U!(V!1), U!(V!2))
-Steve
|
April 24, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Friday, 24 April 2020 at 08:04:29 UTC, Walter Bright wrote: > On 4/24/2020 1:03 AM, Walter Bright wrote: >> On 4/24/2020 12:10 AM, Manu wrote: >>> alias Tup = AliasSeq!(0, 2, 3); >>> void fun(int); >>> fun(Tup); // scalar argument receives tuple, it can expand, so: fun(0), fun(1), fun(2) >> >> Write it as: >> >> Tup.fun(); > > Incidentally, belay that. That will currently produce: fun(0, 2, 3); This syntax is an unfortunate inconsistency with your proposal, but how often is variadic UFCS used ATM? Its existence has been pointed out in a NG reply before (I think by Timon), but it seemed to surprise people. Perhaps it could be deprecated - use fun(Tup) instead. The latter is more intuitive as people tend to think UFCS is for the first argument, not multiple arguments. The spec doesn't seem to suggest variadic UFCS is supported: https://dlang.org/spec/function.html#pseudo-member > Of course, > > fun(1, Tup); > > cannot be rewritten in this way AliasSeq!(1, Tup).fun(); // fun(1); fun(0); fun(2); fun(3); |
April 24, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 4/24/20 8:47 AM, Steven Schveighoffer wrote:
> assert( [myArr[Tup + 1] ] == [ myArr[Tup[0] + 1]], myArr[Tup[1] + 1]]
Missed a bracket:
assert( [myArr[Tup + 1] ] == [ myArr[Tup[0] + 1]], [ myArr[Tup[1] + 1]]
-Steve
|
April 24, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | On Friday, 24 April 2020 at 06:42:53 UTC, Stefan Koch wrote: > On Friday, 24 April 2020 at 06:37:42 UTC, WebFreak001 wrote: >> On Friday, 24 April 2020 at 06:32:16 UTC, Walter Bright wrote: >>> [...] >>> >>>> // replace staticMap >>>> alias staticMap(alias F, T...) = F!T...; >>> >>> alias staticMap(alias F, T...) = F!T; >>> >>> [...] >> >> this would be a breaking change: >> >> currently: >> template F(T...) >> { >> } >> >> alias staticMap(alias F, T...) = F!T; >> >> pragma(msg, staticMap!(F, int, short).stringof); >> -> F!(int, short) >> >> but with that change suddenly: >> pragma(msg, staticMap!(F, int, short).stringof); >> -> SomeTuple!(F!int, F!short) > > nope, compile error. > F does not have an eponymous member. um no? try it on https://run.dlang.io/ : template F(T...) { } alias staticMap(alias F, T...) = F!T; pragma(msg, staticMap!(F, int, short).stringof); (link shortener was broken when I posted this) |
April 24, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 24 April 2020 at 12:22:51 UTC, Steven Schveighoffer wrote:
> On 4/24/20 1:16 AM, Simen Kjærås wrote:
>> On Friday, 24 April 2020 at 00:16:52 UTC, Manu wrote:
>>> On a slightly unrelated note; there's a really interesting idea up-thread
>>> about making nested `...` not be expanded by the outer `...`
>>> For instance:
>>>
>>> template T(A, B...) { ... }
>>> T!(Tup1, Tup2...)...
>>
>> I'm wondering if perhaps that's the wrong way around - AliasSeq already does that:
>>
>> T!(Tup1, AliasSeq!Tup2)... // Should only expand Tup1
>
> No, this means:
>
> T!(Tup1[0], AliasSeq!(Tup2[0])), T!(Tup1[1], AliasSeq!(Tup2[1]), ...
Yup, I noticed a little while ago. In my defense I had a migraine when I wrote that. :p
--
Simen
|
April 24, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On 4/24/20 2:45 AM, Manu wrote:
>>> AliasSeq!(10, Tup..., 20) -> ( 10, 0, 1, 2, 20 )
>>
>> AliasSeq!(10, Tup, 20) -> ( 10, 0, 1, 2, 20 )
>
>
> This is just normal D, but the first case (above) needs an expression.
The first is trivial anyway, no expansion needed. This case isn't important for the proposal
-Steve
|
April 24, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 4/24/20 4:03 AM, Walter Bright wrote:
> On a philosophical point, I am generally opposed to adding syntax just to support some unusual cases. I am sure one could come up with examples where the .... syntax won't work, too. For example, could it work with creating a new tuple out of every third tuple member? I'm not looking for a specific answer, but for a meta answer of "should we support these operations at all with special syntax"?
The point of this is to reduce the amount of "trivial" templates. Every time a template is instantiated, it consumes memory in the compiler, it creates more stuff to manage in the symbol tables, and because templates have to "be the same" for every instantiation, you have weird paradoxes.
One of the fundamental problems with template power in D is that in order to operate on lists, you need a functional-style recurse or divide and conquer, which multiplies the number of templates needed by possibly hundreds or thousands. This takes time, resources, and can result in things that don't compile or are extremely slow to compile.
What I think this proposal does is to remove an entire class of recursive templates, and replaces them with simple loops that the compiler can execute blindfolded with 4 cores tied behind its back with ease, faster than the template expansions required by e.g. staticMap.
I think the ellipsis version is superior simply because it has more expressive power (see my posts elsewhere). An ideal proposal would allow all things to be handled within one expression, but the ellipsis is better in that it is unambiguous and does not break code.
And actually, with a staticIota-like thing you could do every third tuple member quite easily.
alias everyThird = staticIota!(2, Tup.length, 3); // start, end, step
alias everyThirdMember = (Tup...[everyThird])...;
staticIota is kind of another primitive that is super-useful, and would be easy for the compiler to provide. But could be done via CTFE as well.
-Steve
|
April 24, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 24 April 2020 at 17:10:16 UTC, Steven Schveighoffer wrote:
> staticIota is kind of another primitive that is super-useful, and would be easy for the compiler to provide. But could be done via CTFE as well.
>
> -Steve
"staticIota" *should* be a primitive, and D even supports this functionality in exactly 1 place:
foreach (i; 0..10) { do something }
I wish this was an actual language construct so it could be used in other places, and not just some hard coded syntax sugar.
|
April 24, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manu | On 4/24/2020 1:34 AM, Manu wrote: > On Fri, Apr 24, 2020 at 6:20 PM Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com <mailto:digitalmars-d@puremagic.com>> wrote: > > On 4/24/2020 12:39 AM, Manu wrote: > > It doesn't make much sense to think in terms of primitive types. As I > just said > > (but you truncated), operator overloads are almost certainly part of this > equation. > > Operator overloads don't change it. > > > This claim doesn't make sense. A custom type can BinOp any adjacent type it likes. I can't see the legitimate use case for: ((t[0] + t[1]) + t[2]) for a tuple if relying on diverse types with operator overloading, because of the associative ordering dependency. If anyone relied on that, it would be a major code smell. Adding new syntax for tuples to support that would be a mistake. > > I think it's more common to do a fold like this with logical operators > though; > > `&&` appears 9 times out of 10 in my code. > > [ cast(bool)Tup ] > > And then fold them? Since then it's an array, use the existing array folding methods. |
April 24, 2020 Re: I dun a DIP, possibly the best DIP ever | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | On 4/24/2020 1:54 AM, Simen Kjærås wrote:
>> Operator overloads don't change it.
>
> Sure they do - just think of expression templates.
We're not adding features to support expression templates with tuples.
ETs were "discovered" in the early aughts, and caused great excitement in the C++ community. Lots of articles, presentations, and projects were done using ETs.
Then ... nothing. They just vanished from the conversation. The problem is they were ugly, clumsy, incomprehensible to debug, incredibly slow to compile, did not work at scale (blowing up the compilers) and impossible to work with if you weren't an expert.
They're a failed experiment.
|
Copyright © 1999-2021 by the D Language Foundation