January 10, 2019 Re: Named constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Atila Neves | On Thu, Jan 10, 2019 at 02:00:25PM +0000, Atila Neves via Digitalmars-d wrote: > On Thursday, 10 January 2019 at 12:37:38 UTC, H. S. Teoh wrote: [...] > > Don't worry, this is Atila we're talking about. If he comes up with any solution, you can be sure it will not hurt his precious compile times! ;-) > > Actually, they're so bad right now anyway from a baseline of acceptability > to me that nothing I add on top makes it that much worse. Currently > I'm trying to work out an efficient way to interpret D to run unit > tests so I don't have to pay the linker tax and just avoid compiling > code whilst developing. It'll be a lot of work, though... :( Recently I've started to compile unittests separately from the final executable. The default behaviour of running unittests before main() is nice for one-off scripts and short-term projects, but for serious code I'm finding more and more that it makes more sense to compile and run unittests separately. I haven't gotten to the point of evading linker tax, though. But I surmise it should be relatively easy to just compile modules separately with -unittest -run, using -i to automatically pick up imports. Put this in a test target in your build script and have the tests built and run incrementally. Not sure how much time will be saved, due to -i potentially causing the same tests to run multiple times. I should try this out on one of my larger projects to see how it does. T -- They pretend to pay us, and we pretend to work. -- Russian saying |
January 10, 2019 Re: Named constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Thursday, 10 January 2019 at 16:22:27 UTC, H. S. Teoh wrote: > These days, whenever my functions start needing so many optional arguments that this becomes a problem, I just start using a struct to encapsulate them instead. I wouldn't claim it's the perfect solution, but it does pretty much have equivalent functionality: you can pass values in order (MyArgs(...)), or pass them by name (MyArgs args; args.field1 = 123;), and there can be default arguments (default field values). It does need a bit more typing, but other than that it works pretty well. This is a viable solution. It works for many usecases. APIs like Vulkan and Direct3D like to use the struct solution to pass arguments to their methods. https://github.com/wilzbach/DIPs/blob/b1283b455b635d7dcbc2c871d2aa47cc67190059/DIPs/DIP1xxx-sw.md would make it much sweeter to work with structs though. |
January 10, 2019 Re: Named constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to JN | On 01/10/2019 06:35 AM, JN wrote: > the real cost is the fact that you have to create all those structs > meticulously and you can only use that with functions that expect such > usage. Weka uses the generic TypedIdentifier for integers: https://github.com/weka-io/mecca/blob/master/src/mecca/lib/typedid.d#L532 Ali |
January 10, 2019 Re: Named constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to JN | On Thursday, 10 January 2019 at 14:35:33 UTC, JN wrote: > On Thursday, 10 January 2019 at 13:53:40 UTC, Atila Neves wrote: >> >> What's the _real_ difference between `someFunc(firstName="Alice")` and `someFunc(FirstName("Alice"))`? The former saves one character? Is that really worth the cost of language support? I have a feeling a lot of feature requests neglect that each and every one of them has a cost, and there's only enough budget for so many. >> > Isn't there a performance cost added when using structs like that? No. > And the real cost is the fact that you have to create all those structs meticulously Meticulously? It's a name and the type you were going to write anyway. You can always call the field `_` to avoid even more typing. > and you can only use that with functions that expect such usage. Yes. But I'm writing the API. > With language support, you could have named arguments for every code there exists. I'd love to see a DIP that did that and dealt with all the corner cases. I suspect that it's not as easy as implied here. > Anyway, the fact that arguments are named are only a bonus, the real strength of named arguments comes with optional arguments. Again, I want a library for this. I know how to write it, I just haven't yet. > Look at the Builder pattern, it's pretty much a workaround for lack of named/keyword arguments. Java doesn't have variadic templates, D does. No builder pattern needed. > Also, named/keyword arguments shouldn't be an issue in regards to overloading and argument order. Every language I know that has named/kw arguments allows either only keyword arguments or keywords arguments at the end of the argument list. You can do: > > foo(x=10) > foo(10, 20, z=30) > > but you can't do: > > foo(x=10, 20) > > because it'd be ambiguous. I don't know of any language that does that and has overloading. Walter knows way more about this than I do. |
January 10, 2019 Re: Named constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Thursday, 10 January 2019 at 16:33:51 UTC, H. S. Teoh wrote:
> On Thu, Jan 10, 2019 at 02:00:25PM +0000, Atila Neves via Digitalmars-d wrote:
>> [...]
> [...]
>> [...]
>
> Recently I've started to compile unittests separately from the final executable. The default behaviour of running unittests before main() is nice for one-off scripts and short-term projects, but for serious code I'm finding more and more that it makes more sense to compile and run unittests separately. I haven't gotten to the point of evading linker tax, though.
>
> But I surmise it should be relatively easy to just compile modules separately with -unittest -run, using -i to automatically pick up imports. Put this in a test target in your build script and have the tests built and run incrementally. Not sure how much time will be saved, due to -i potentially causing the same tests to run multiple times. I should try this out on one of my larger projects to see how it does.
>
>
> T
I _only_ build unit tests apart from the production code now. I'm toying with not using `unittest` at all since I can reflect and find tests on my own, and I don't have to pay the compile time tax of importing a phobos module with `-unittest`.
|
January 10, 2019 Re: Named constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Atila Neves | On Thu, Jan 10, 2019 at 06:29:27PM +0000, Atila Neves via Digitalmars-d wrote: > On Thursday, 10 January 2019 at 16:33:51 UTC, H. S. Teoh wrote: [...] > > Recently I've started to compile unittests separately from the final executable. The default behaviour of running unittests before main() is nice for one-off scripts and short-term projects, but for serious code I'm finding more and more that it makes more sense to compile and run unittests separately. I haven't gotten to the point of evading linker tax, though. > > > > But I surmise it should be relatively easy to just compile modules separately with -unittest -run, using -i to automatically pick up imports. Put this in a test target in your build script and have the tests built and run incrementally. Not sure how much time will be saved, due to -i potentially causing the same tests to run multiple times. I should try this out on one of my larger projects to see how it does. [...] > I _only_ build unit tests apart from the production code now. I'm toying with not using `unittest` at all since I can reflect and find tests on my own, and I don't have to pay the compile time tax of importing a phobos module with `-unittest`. The last time somebody looked, the real problem wasn't that Phobos (or any 3rd party library) unittests were being compiled over and over; it was caused by a change in template instantiation behaviour when -unittest is specified, such that many more templates are instantiated that probably don't need to be, thus causing the observed compile-time spike. There's a reason it was done this way, but I'm here gnashing my teeth wishing that there was a way to turn off this annoying behaviour. T -- Why waste time learning, when ignorance is instantaneous? -- Hobbes, from Calvin & Hobbes |
January 10, 2019 Re: Named constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thu, 10 Jan 2019 10:12:24 -0800, Ali Çehreli wrote: > On 01/10/2019 06:35 AM, JN wrote: > > > the real cost is the fact that you have to create all those structs > > meticulously and you can only use that with functions that expect > > such usage. > > Weka uses the generic TypedIdentifier for integers: > > https://github.com/weka-io/mecca/blob/master/src/mecca/lib/ typedid.d#L532 > > Ali Which can be done equally well with std.typecons.Typedef. It still has a lot of the same issues as custom structs, but at least you can use a different module's named arg structs as long as they're not doing anything funky. Here's a slightly better version: --- struct Named(T) { template opDispatch(string name) { alias opDispatch = Typedef!(T, T.init, name); } } struct Arg { template opDispatch(string name) { alias opDispatch = makeTypedef!name; } } template makeTypedef(string name) { Typedef!(T, T.init, name) makeTypedef(T)(T value) { return Typedef!(T, T.init, name)(value); } } --- Usage: --- void foo(Named!int.age a, Named!string.name b) { writefln("name: %s age: %s", b, a); } void main() { foo(Arg.age(12), Arg.name("Rydia")); } --- Something like that is the best you're likely to get with the struct-per- argument model. |
January 10, 2019 Re: Named constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 1/10/19 1:49 PM, H. S. Teoh wrote:
> The last time somebody looked, the real problem wasn't that Phobos (or
> any 3rd party library) unittests were being compiled over and over; it
> was caused by a change in template instantiation behaviour when
> -unittest is specified, such that many more templates are instantiated
> that probably don't need to be, thus causing the observed compile-time
> spike. There's a reason it was done this way, but I'm here gnashing my
> teeth wishing that there was a way to turn off this annoying behaviour.
Yes, it's that when unittest is enabled effectively -allinst is enabled as well.
That wasn't the only problem, but it was the main reason why importing e.g. std.regex with -unittest was a huge penalty.
-Steve
|
January 11, 2019 Re: Named constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to JN | On 11/01/2019 3:35 AM, JN wrote:
> Also, named/keyword arguments shouldn't be an issue in regards to overloading and argument order. Every language I know that has named/kw arguments allows either only keyword arguments or keywords arguments at the end of the argument list. You can do:
>
> foo(x=10)
> foo(10, 20, z=30)
>
> but you can't do:
>
> foo(x=10, 20)
>
> because it'd be ambiguous.
Actually every example there is ambiguous and problematic in D.
It conflicts with AssignExpression which is identical in syntax and usage!
|
January 11, 2019 Re: Named constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to rikki cattermole | On Friday, 11 January 2019 at 07:53:56 UTC, rikki cattermole wrote:
> On 11/01/2019 3:35 AM, JN wrote:
>> Also, named/keyword arguments shouldn't be an issue in regards to overloading and argument order. Every language I know that has named/kw arguments allows either only keyword arguments or keywords arguments at the end of the argument list. You can do:
>>
>> foo(x=10)
>> foo(10, 20, z=30)
>>
>> but you can't do:
>>
>> foo(x=10, 20)
>>
>> because it'd be ambiguous.
>
> Actually every example there is ambiguous and problematic in D.
> It conflicts with AssignExpression which is identical in syntax and usage!
well, it's because I used the equality sign, languages like C# use :,
I guess:
foo(x:10, 20)
would be better?
|
Copyright © 1999-2021 by the D Language Foundation