Thread overview
D beginner's article about D's Metaprogramming and Testing
Dec 17, 2023
Renato
Dec 18, 2023
aberba
Dec 18, 2023
monkyyy
Dec 19, 2023
Sergey
Dec 19, 2023
Mike Shah
Dec 20, 2023
Renato
Dec 20, 2023
Renato
December 17, 2023

Hi.

I'm new to D and after playing around with D a bit I decided to publish my thoughts about the language, focusing on its metaprogramming and testing support.

https://renato.athaydes.com/posts/testing-dlang

I would be interested in feedback and corrections from more experienced D enthusiasts :).

Hope you like it!

December 18, 2023

On Sunday, 17 December 2023 at 21:51:59 UTC, Renato wrote:

>

Hi.

I'm new to D and after playing around with D a bit I decided to publish my thoughts about the language, focusing on its metaprogramming and testing support.

https://renato.athaydes.com/posts/testing-dlang

I would be interested in feedback and corrections from more experienced D enthusiasts :).

Hope you like it!

This:

>

D seems like a good balance. It looks familiar while having some very interesting features. It’s been around long enough that it’s no longer trying to find itself and changing every 6 months.

...is exactly why I love D. It's the only system programming language that's a joy to write. Also, unlike others wanting D to change, I personally like that the focus in on stability and improvements.

I'm addition, I want code written 8yrs ago to still work. I wanted dub packages to still work even with update for the next 8yrs+.

December 18, 2023

On Sunday, 17 December 2023 at 21:51:59 UTC, Renato wrote:

>

Hi.

I'm new to D and after playing around with D a bit I decided to publish my thoughts about the language, focusing on its metaprogramming and testing support.

https://renato.athaydes.com/posts/testing-dlang

I would be interested in feedback and corrections from more experienced D enthusiasts :).

Hope you like it!

assuming your are trying to be a resource, I'd focus more on template specialization, the variadic functions, and op overloads; before mixin templates. Mixin templates are more "walter doesnt like templates that work like this so they are ugly and require 2 keywords now"

December 19, 2023

On Sunday, 17 December 2023 at 21:51:59 UTC, Renato wrote:

>

Hi.

I'm new to D and after playing around with D a bit I decided to publish my thoughts about the language, focusing on its metaprogramming and testing support.

https://renato.athaydes.com/posts/testing-dlang

I would be interested in feedback and corrections from more experienced D enthusiasts :).

Hope you like it!

Nice article! Thanks for sharing it :)

December 19, 2023

On Sunday, 17 December 2023 at 21:51:59 UTC, Renato wrote:

>

Hi.

I'm new to D and after playing around with D a bit I decided to publish my thoughts about the language, focusing on its metaprogramming and testing support.

https://renato.athaydes.com/posts/testing-dlang

I would be interested in feedback and corrections from more experienced D enthusiasts :).

Hope you like it!

Very nice -- might I recommend adding to the wiki here?
https://wiki.dlang.org/Articles#Metaprogramming

December 19, 2023

On Sunday, 17 December 2023 at 21:51:59 UTC, Renato wrote:

>

Hi.

I'm new to D and after playing around with D a bit I decided to publish my thoughts about the language, focusing on its metaprogramming and testing support.

https://renato.athaydes.com/posts/testing-dlang

Excellent!

>

I would be interested in feedback and corrections from more experienced D enthusiasts :).

Some comments:

"static if is an if block that’s executed at compile-time… it doesn’t exist at runtime."

I see what you are going for, but the static if block is included or excluded based on what the compile-time condition is. The condition is executed at compile time, and if the condition is true, the block exists, if not, it doesn't exist. But in the case of your code, clearly the block exists at runtime (you are adding 2 runtime values together).

Regarding more descriptive unittests, try out the compiler parameter -checkaction=context to get more descriptive asserts: https://dlang.org/dmd-osx.html#switch-checkaction

there are also options to build your own unittest runner, see https://dlang.org/phobos/core_runtime.html#.Runtime.extendedModuleUnitTester

While this gives you only granularity of the module-level unittests, it allows you to do things like select only certain modules to run. And you do not need to build compile-time lists of all unittests yourself, the compiler links it all together for you (see the example in that function on what the default does).

-Steve

December 20, 2023

On Tuesday, 19 December 2023 at 23:56:59 UTC, Steven Schveighoffer wrote:

>

"static if is an if block that’s executed at compile-time… it doesn’t exist at runtime."

I see what you are going for, but the static if block is included or excluded based on what the compile-time condition is. The condition is executed at compile time, and if the condition is true, the block exists, if not, it doesn't exist. But in the case of your code, clearly the block exists at runtime (you are adding 2 runtime values together).

Hm, I meant that the if condition, which was static if (is(T: double)), is evaluated at compile-time and hence, "disappears" at runtime. Did you interpret that as "the whole if block disappears at runtime"? If so, how can I make that clearer that I am talking about the if check, not the branch which gets executed?

Perhaps "static if is evaluated at compile-time, and only the branch that executes is present at runtime, i.e. the if condition itself doesn't exist at runtime"?

>

Regarding more descriptive unittests, try out the compiler parameter -checkaction=context to get more descriptive asserts: https://dlang.org/dmd-osx.html#switch-checkaction

That would be awesome! But it seems there's some problem on my machine:

dmd -L-ld_classic -unittest -checkaction=context -run main.d
Undefined symbols for architecture x86_64:
  "__D4core8internal7dassert__T24miniFormatFakeAttributesTiZQBdFNaNbNiNfMKxiZAya", referenced from:
      __D4core8internal7dassert__T14_d_assert_failTxiZ__TQxTiZQBcFNaNbNiNfMxAyaMKxiMxiZAya in main.o
      __D4core8internal7dassert__T14_d_assert_failTmZ__TQwTiZQBbFNaNbNiNfMxAyaMKxmMxiZAya in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: linker exited with status 1

Compilation exited abnormally with code 1 at Wed Dec 20 19:34:11

Do you know what this may be? Looks like the Mac OS's linker just doesn't work well with the DMD compiler?!

>

there are also options to build your own unittest runner, see https://dlang.org/phobos/core_runtime.html#.Runtime.extendedModuleUnitTester

While this gives you only granularity of the module-level unittests, it allows you to do things like select only certain modules to run. And you do not need to build compile-time lists of all unittests yourself, the compiler links it all together for you (see the example in that function on what the default does).

-Steve

Didn't I mention that in my blog post? Or is this not the same as that example where I showed this:

Runtime.moduleUnitTester = &tester;

Thanks for the feedback, and thanks everyone for the kind words! I really appreciated it :)

December 20, 2023

On Tuesday, 19 December 2023 at 23:56:59 UTC, Steven Schveighoffer wrote:

>

On Sunday, 17 December 2023 at 21:51:59 UTC, Renato wrote:

>

Hi.

I see what you are going for, but the static if block is included or excluded based on what the compile-time condition is. The condition is executed at compile time, and if the condition is true, the block exists, if not, it doesn't exist. But in the case of your code, clearly the block exists at runtime (you are adding 2 runtime values together).

I've edited the post to clarify this.

>

Regarding more descriptive unittests, try out the compiler parameter -checkaction=context to get more descriptive asserts: https://dlang.org/dmd-osx.html#switch-checkaction

I got this working, obviously I forgot the -main flag before... too many flags to remember, I need to start using dub I suppose.

Also, added a note mentioning this and linked to your post.

Thanks!

December 21, 2023

On Wednesday, 20 December 2023 at 18:39:12 UTC, Renato wrote:

>

Perhaps "static if is evaluated at compile-time, and only the branch that executes is present at runtime, i.e. the if condition itself doesn't exist at runtime"?

Looks better now!

> >

Regarding more descriptive unittests, try out the compiler parameter -checkaction=context to get more descriptive asserts: https://dlang.org/dmd-osx.html#switch-checkaction

That would be awesome! But it seems there's some problem on my machine:

dmd -L-ld_classic -unittest -checkaction=context -run main.d
Undefined symbols for architecture x86_64:
  "__D4core8internal7dassert__T24miniFormatFakeAttributesTiZQBdFNaNbNiNfMKxiZAya", referenced from:
      __D4core8internal7dassert__T14_d_assert_failTxiZ__TQxTiZQBcFNaNbNiNfMxAyaMKxiMxiZAya in main.o
      __D4core8internal7dassert__T14_d_assert_failTmZ__TQwTiZQBbFNaNbNiNfMxAyaMKxmMxiZAya in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: linker exited with status 1

Compilation exited abnormally with code 1 at Wed Dec 20 19:34:11

Do you know what this may be? Looks like the Mac OS's linker just doesn't work well with the DMD compiler?!

From your later message:

>

I got this working, obviously I forgot the -main flag before... too many flags to remember, I need to start using dub I suppose.

Great to hear, but man that is a terrible error message for such a thing! I wonder why this is the result? And what is "miniFormatFakeAttributes"?!

> >

there are also options to build your own unittest runner, see https://dlang.org/phobos/core_runtime.html#.Runtime.extendedModuleUnitTester

While this gives you only granularity of the module-level unittests, it allows you to do things like select only certain modules to run. And you do not need to build compile-time lists of all unittests yourself, the compiler links it all together for you (see the example in that function on what the default does).

Didn't I mention that in my blog post? Or is this not the same as that example where I showed this:

Runtime.moduleUnitTester = &tester;

First, I did not see that you are using the module unit tester assignment, though it does make sense because that's how you override it.

But I should clarify that it is possible to override the unittest tester and still use the module unittests provided by the compiler. What you get is a function pointer per module to the unittest aggregate that calls all the individual unittests. And of course you have the module name.

So for example, if you wanted to catalog which modules run unittests, you do not need to use __traits(getUnittests). If you wanted to only run unittests from a given module/package based on runtime args, that also is possible. And the further advantage is that it works without having to use compile-time introspection to build the tester (i.e. you don't have to import all the testable modules).

I hope this makes things a bit clearer.

-Steve