Re: Doubt about type Inference on templates
On Wednesday, 22 November 2023 at 19:37:58 UTC, Paul Backus wrote: This is a bug/limitation in the compiler. I couldn't find an existing report on issues.dlang.org, so I've reported it myself as [issue 24255][1]. Wow: It is a very concise bug example. I tested with ```ldc``` ant it fails too. For now, I think the best way to work around it is to specify the type in the lambda, as in `(int i) => i%2 == 0`. agreed The reason you see `void` is that when the compiler cannot figure out the type of a function literal, it treats it as a template function: ```d static assert(__traits(isTemplate, i => i % 2 == 0)); ``` And for silly historical reasons, when the compiler tries to determine the type of a template, it returns `void` instead of giving an error: ```d template example() {} static assert(is(typeof(example) == void)); // what?? ``` Thanks Paul!!!
Re: Doubt about type Inference on templates
On Wednesday, 22 November 2023 at 17:53:15 UTC, Antonio wrote: Basically, it doesn't know witch version of ```filter``` to use, because it is inferring `i=>i%2==0` is `void` ?!?!?! ``` !()(IIterable!int, void) ``` If I explicitly write `(int i)=>i%2==0`, it compiles correctly again. **Is it mandatory to explicitly tell that `S` is `int` when ```IIterable!S source``` is `IIterable!int` alredy?** This is a bug/limitation in the compiler. I couldn't find an existing report on issues.dlang.org, so I've reported it myself as [issue 24255][1]. For now, I think the best way to work around it is to specify the type in the lambda, as in `(int i) => i%2 == 0`. The reason you see `void` is that when the compiler cannot figure out the type of a function literal, it treats it as a template function: ```d static assert(__traits(isTemplate, i => i % 2 == 0)); ``` And for silly historical reasons, when the compiler tries to determine the type of a template, it returns `void` instead of giving an error: ```d template example() {} static assert(is(typeof(example) == void)); // what?? ``` [1]: https://issues.dlang.org/show_bug.cgi?id=24255
Doubt about type Inference on templates
Just for fun, I'm trying to implement an alternative base library to avoid template/mixin/static/traits code with only one objective: make "intelliSense" code analyzers tasks easier. I need "Generics"... but D has not generics: I use templates in the "simplest" possible way I.E.: ```d interface IIterable(T) { bool empty(); void popFront(); T front(); } IIterable!S toIterable(S)(S[] source) => new ArrayIterable!S(source); IIterable!S filter(S)(IIterable!S source, bool delegate(S item) predicate) => new Filter!S(source, predicate); IIterable!S filter(S)(S[] source, bool delegate(S item) predicate) => toIterable(source).filter(predicate); // ... ``` Then, in main.d I do ```d import std.stdio; void main(){ [1,2,3,4,5,6].toIterable!int.filter!int(i=>i%2==0).map!int(i=>i*2).toArray.writeln(); } ``` It works properly... until I remove the ```!int``` from the ```filter``` method. ``` main.d(3,38): Error: none of the overloads of template `filter` are callable using argument types `!()(IIterable!int, void)` iterable.d(21,13):Candidates are: `filter(S)(IIterable!S source, bool delegate(S item) predicate)` iterable.d(23,13):`filter(S)(S[] source, bool delegate(S item) predicate)` ``` Basically, it doesn't know witch version of ```filter``` to use, because it is inferring `i=>i%2==0` is `void` ?!?!?! ``` !()(IIterable!int, void) ``` If I explicitly write `(int i)=>i%2==0`, it compiles correctly again. **Is it mandatory to explicitly tell that `S` is `int` when ```IIterable!S source``` is `IIterable!int` alredy?**
Re: templates and traits
On Saturday, 18 March 2023 at 20:42:50 UTC, Nick Treleaven wrote: On Saturday, 18 March 2023 at 19:22:07 UTC, Chris Katko wrote: ... So there's multiple sub-problems to solve. I asked this years ago, and got 90% of the way done and then lost the code and cannot find the original forum post. Maybe it was this?: https://forum.dlang.org/post/dqzxnctucwvyhstfz...@forum.dlang.org YES! I tried google search, forum search, even going through all my accounts posts, even my e-mail. I think I accidentally made that post without logging in so it's not attached to my account posts.
Re: templates and traits
On Saturday, 18 March 2023 at 19:22:07 UTC, Chris Katko wrote: ... So there's multiple sub-problems to solve. I asked this years ago, and got 90% of the way done and then lost the code and cannot find the original forum post. Maybe it was this?: https://forum.dlang.org/post/dqzxnctucwvyhstfz...@forum.dlang.org
templates and traits
Given: ```D struct pos {float x, y;} draw(myBitmap, pos(320, 240), centered); draw(pos(320, 240), myBitmap); draw("text", myFont, pos(320, 240)); ``` I'm writing a general "draw" template function that through compile-time, calls an associated DAllegro/Allegro 5 function: ``` draw(myBitmap, pos(320, 240), centered); // al_draw_bitmap(myBitmap, pos.x - myBitmap.w/2, pos.y - myBitmap.h, 0); draw(pos(320, 240), myBitmap); // order doesn't matter draw("text", myFont, pos(320, 240)); // different function al_draw_text(...) ``` So there's multiple sub-problems to solve. I asked this years ago, and got 90% of the way done and then lost the code and cannot find the original forum post. The pos(320,240) part works fine already. I need: - At compile-time, for a variadic template that can take any number of arguments, if specific arguments are available, I branch and use them to call a specific applicable C function. I remember I need to write some sort of enum function that checks "IsAny" if an argument is passed at all, as well as one to find where that argument is. Passing duplicates probably don't matter (at least not right now), first valid argument is fine. I can't seem to write code (or find example code online) that does this. But it's something like ```D enum isAny() = ...; void draw(T...)(T) { if(isAny(bitmap)) { // it's a sprite, now find out if we need it rotated, stretched, etc. } is(isAny(string)) { // its text [...] } } ``` A separate problem I've run into is, the 'centered' construct. If I have rotate(25) (rotate 25 degrees), that works. But I cannot just pass a type named "centered" with no variable attached to it, nor can I--I think--pass an enum. I could do centered(false) or centered(0), but that's clunkier than just saying "if 'centered' is an argument, we center it. If not, we don't." I could have a variable named centered, I guess. or an enum with {isCentered=1, notCentered=0} and detect if the enum is passed. Lot's of ways to skin this cat. The idea here, is I've got a lot of optional arguments (centered, tinted, rotated, scaled, sheared, etc) that I can pick from and I don't want to have to sort through a list of 80 different permutations of function signatures, or, one gigantic megafunction with a ton of zeros/nulls for all the unused arguments. This is a bit of a confusing problem to explain, so I've probably left something necessary out.
Combining Templates While Minimizing Bloat
The code below has two `foo` functions that take slices, one accepts a const(T)* iterator and one accepts a generic Iterator with the property that the slice isn't convertible to the first one. The nice thing about this is that if you pass it with a double* or const(double)*, then it doesn't increase template bloat. The problem, however, is that I have to either have two implementations or a separate `fooImpl` function to implement the desired functionality. Is there any way to combine together the `foo` functions in a way that maintains the template bloat reducing behavior of the first function? The example below uses mir, but it just as easily could be adapted to other types. ```d /+dub.sdl: dependency "mir-algorithm" version="*" +/ import std.stdio: writeln; import mir.ndslice.slice; void foo(T)(Slice!(const(T)*, 1) x) { writeln("here"); writeln("Iterator = ", typeid(IteratorOf!(typeof(x; } void foo(Iterator)(Slice!(Iterator, 1) x) if (!is(Iterator : const(U)*, U)) { writeln("there"); writeln("Iterator = ", typeid(IteratorOf!(typeof(x; } void main() { double[] x = [1.0, 2, 3]; auto y = x.sliced; auto z = y.toConst; foo(y); //prints "here" and "Iterator=const(double)*" foo(z); //prints "here" and "Iterator=const(double)*" auto a = y / 6; foo(a); //prints "there" and "Iterator=(some long template text)" } ``` I tried something like ```d void foo(Iterator)(Slice!(const Iterator, 1) x) {} ``` but this isn't a valid mir iterator since it becomes const(double*) (a const pointer to a const double). What I need is const(double)* (a mutable pointer to a const double).
Re: How to Add CSS and JS to vibe.d templates
On 1/19/23 11:44 PM, seany wrote: Hi Howcan one add CSS and JS to vibe.d templates? Here is my setup (vibe.d project initiated with dub using dub init myproject vibe.d): ./public: main.css main.js ./source: app.d ./views: auth2fa.dt fail.dt login.dt pair.dt passfail.dt userfail.dt I am trying to add a css file using `link(rel="stylesheet", type="text/css", href="main.css")` in the diet templates, but it has no effect. I took the files from here: https://codepen.io/ricardoolivaalonso/pen/YzyaRPN Keep in mind, this literally translates to a `link` tag in the HTML. So here is what happens: 1. your vibe project is running, and passes out the compiled template to the browser. 2. The browser sees the link tag, and attempts to ask the server for the file "main.css" 3. The vibe project tries to match that to its routes, and cannot find it, and so returns an error. So this takes 2 steps to remedy: 1. Register a `serveStaticFiles` route with the glob `public/*`. See the docs here: https://vibed.org/api/vibe.http.fileserver/serveStaticFiles 2. Change your link to refer to `public/main.css`, instead of just `main.css`. This is how it looks in my code: ```d router.get("/public/*", serveStaticFiles("")); ``` And the links look like: ```pug link(rel="stylesheet",href="/public/css/flatpickr.min.css") ``` as an example. Note that I put my css files into a css subdirectory under public, and my javascript files under a js subdirectory. It all depends on how you want to set it up. -Steve
How to Add CSS and JS to vibe.d templates
Hi Howcan one add CSS and JS to vibe.d templates? Here is my setup (vibe.d project initiated with dub using dub init myproject vibe.d): ./public: main.css main.js ./source: app.d ./views: auth2fa.dt fail.dt login.dt pair.dt passfail.dt userfail.dt I am trying to add a css file using `link(rel="stylesheet", type="text/css", href="main.css")` in the diet templates, but it has no effect. I took the files from here: https://codepen.io/ricardoolivaalonso/pen/YzyaRPN Note that (as discussed in my previous post by Steven Schveighoffer) , there are some errors in the jade/pug template file. But even if we correct them, and then I try to use the setup, I do not get the styles. (Of course, i can't point my browser to www.my.server/main.css or so, because those endpoints are not defined. However, as I understood, all non-defined endpoints should anyway be redirected to public) Thank you.
Re: How to use templates in a separate library?
On Thursday, 23 June 2022 at 23:50:42 UTC, monkyyy wrote: On Thursday, 23 June 2022 at 08:12:32 UTC, CrazyMan wrote: linking make sure you use the -i flag when compiling But note, that would be the opposite of using a library.
Re: How to use templates in a separate library?
On Thursday, 23 June 2022 at 08:12:32 UTC, CrazyMan wrote: linking make sure you use the -i flag when compiling
Re: How to use templates in a separate library?
On Thursday, 23 June 2022 at 08:12:32 UTC, CrazyMan wrote: I have a separate library and some template interface in it ```d interface IFoo(T) { void setValue(const(T) value); } ``` But when using it in the main program, it throws a linking error. I found that you can make a sourceLibrary that copies the code instead of creating a binary. But with it, I also get a linking error, and at the same time it is no longer associated with my interface, but with a third-party dependency (bindbc.opengl) What can I do to fix this? This is insufficient information to help you. - Separate library could mean multiple things: a compiler library, a static linked binary, a SO/DLL binary. - What error is thrown? - Are you using `extern` declarations? For a successful build the linker needs to get all symbols from any referenced source. The template isn't an actual symbol, it's just a information for the compiler to generate one. It says nothing about the symbol will be really generated or not. Also the linker needs to know if a library has to be used.
How to use templates in a separate library?
I have a separate library and some template interface in it ```d interface IFoo(T) { void setValue(const(T) value); } ``` But when using it in the main program, it throws a linking error. I found that you can make a sourceLibrary that copies the code instead of creating a binary. But with it, I also get a linking error, and at the same time it is no longer associated with my interface, but with a third-party dependency (bindbc.opengl) What can I do to fix this?
Re: Mixin Templates and Operators
On Wednesday, 6 April 2022 at 17:59:12 UTC, Adam D Ruppe wrote: ooh yeah there's multiple here so the names don't overload and one on the time itself would override the ones from mixin template. You'd have to alias them together on the type. Hello Adam D Ruppe, I see what you mean, thank you very much for your answers! -FA
Re: Mixin Templates and Operators
On Wednesday, 6 April 2022 at 17:33:28 UTC, Steven Schveighoffer wrote: As I mentioned elsewhere, it does work. But the situation I think must be that it's only one mixin template. Probably also you can't have any overloads in the type itself. Note that I also think string mixins would work perfectly fine. And UFCS will never work for operator overloads, but that is by design. -Steve Hello Steve, Thank you very much for your answers, you have been very clear and helpful! -FA
Re: Mixin Templates and Operators
On Wednesday, 6 April 2022 at 16:36:51 UTC, Tejas wrote: Looks like a compiler bug, since substituting the real methods makes the `mixin template` code compile fine Hi Tejas, Thank you very much for your answer! Also, remove the `const`, otherwise the method will word only on `const` instances even if the bug gets fixed And thank you for this advice: I'll definitely remove the `const`! FA
Re: Mixin Templates and Operators
On Wednesday, 6 April 2022 at 17:33:28 UTC, Steven Schveighoffer wrote: As I mentioned elsewhere, it does work. But the situation I think must be that it's only one mixin template. Probably also you can't have any overloads in the type itself. ooh yeah there's multiple here so the names don't overload and one on the time itself would override the ones from mixin template. You'd have to alias them together on the type.
Re: Mixin Templates and Operators
On 4/6/22 12:52 PM, Adam D Ruppe wrote: On Wednesday, 6 April 2022 at 10:36:04 UTC, francesco.andreetto wrote: Am I doing something wrong or it is impossible to use mixin templates like that? mixin templates can't bring in operator overloads. The spec doesn't really say this I think, but that's the way it has been for a long time. It only checks for operator overloads on the direct thing itself, no UFCS, no mixin template. As I mentioned elsewhere, it does work. But the situation I think must be that it's only one mixin template. Probably also you can't have any overloads in the type itself. Note that I also think string mixins would work perfectly fine. And UFCS will never work for operator overloads, but that is by design. -Steve
Re: Mixin Templates and Operators
On 4/6/22 6:36 AM, francesco.andreetto wrote: I have two structs, point and vec, in which I want to implement some arithmetic operations. The operations are: ``` point - point = vec point + vec = point ``` Using mixin templates the code compiles but calling the operations in the main causes an "incompatible type" Error: This seems like a bug in the compiler. You can mixin operator overloads using one mixin template, but not multiple. e.g. raylib-d uses this: https://github.com/schveiguy/raylib-d/blob/89733bab9fd1d3588c14f4aa54b62ad45022a105/source/raymathext.d#L75 I tried to implement a single template: ```d mixin template sumDiff(T, R){ R opBinary(string op)(T rhs) const if (op == "+" || op == "-"){ return mixin("R(x " ~ op ~ " rhs.x, y " ~ op ~ "rhs.y, z " ~ op ~ " rhs.z)"); } } ``` but the same error occurs. This is different from your original. If I do this, it works: ```d mixin template both(T, R) { R opBinary(string op : "+")(T rhs) const { return R(x + rhs.x, y + rhs.y, z + rhs.z); } T opBinary(string op : "-")(R rhs) const { return T(x - rhs.x, y - rhs.y, z - rhs.z); } } struct point{ float x, y, z; mixin both!(vec, point); } ``` If I don't use the mixin templates and, instead, I overload the operations into the structures everything works. It also works to call `opBinary` directly: ```d vec v1 = p1.opBinary!"-"(p2); ``` Which leads me to believe it's not an ambiguity error, but rather just a straight omission on how the operator overloading works. I think you should file a bug. -Steve
Re: Mixin Templates and Operators
On Wednesday, 6 April 2022 at 10:36:04 UTC, francesco.andreetto wrote: Am I doing something wrong or it is impossible to use mixin templates like that? mixin templates can't bring in operator overloads. The spec doesn't really say this I think, but that's the way it has been for a long time. It only checks for operator overloads on the direct thing itself, no UFCS, no mixin template.
Re: Mixin Templates and Operators
On Wednesday, 6 April 2022 at 10:36:04 UTC, francesco.andreetto wrote: I have two structs, point and vec, in which I want to implement some arithmetic operations. The operations are: ``` point - point = vec point + vec = point ``` Using mixin templates the code compiles but calling the operations in the main causes an "incompatible type" Error: ```d mixin template sum(T, R) { R opBinary(string op)(T rhs) const if (op == "+"){ return R(x + rhs.x, y + rhs.y, z + rhs.z); } } mixin template diff(T, R) { R opBinary(string op)(T rhs) const if (op == "-") { return R(x - rhs.x, y - rhs.y, z - rhs.z); } } struct point{ float x, y, z; mixin diff!(point, vec); mixin sum!(vec, point); } struct vec{ float x, y, z; } void main(){ point p1 = {1,2,3}, p2 = {5,6,7}; vec v1 = p1-p2; vec v2 = {2,-1,0}; point p3 = p1+v2; } ``` The output of `dub run` is ``` Performing "debug" build using /usr/bin/dmd for x86_64. query ~master: building configuration "application"... source/app.d(27,13): Error: incompatible types for `(p1) - (p2)`: both operands are of type `point` source/app.d(30,15): Error: incompatible types for `(p1) + (v2)`: `point` and `vec` /usr/bin/dmd failed with exit code 1. ``` I tried to implement a single template: ```d mixin template sumDiff(T, R){ R opBinary(string op)(T rhs) const if (op == "+" || op == "-"){ return mixin("R(x " ~ op ~ " rhs.x, y " ~ op ~ "rhs.y, z " ~ op ~ " rhs.z)"); } } ``` but the same error occurs. If I don't use the mixin templates and, instead, I overload the operations into the structures everything works. ```d struct point{ float x, y, z; vec opBinary(string op)(point rhs) const if (op == "-") { return vec(x - rhs.x, y - rhs.y, z - rhs.z); } point opBinary(string op)(vec rhs) const if (op == "+") { return point(x + rhs.x, y + rhs.y, z + rhs.z); } } struct vec{ float x, y, z; } void main(){ point p1 = {1,2,3}, p2 = {5,6,7}; vec v1 = p1-p2; vec v2 = {2,-1,0}; point p3 = p1+v2; } ``` Am I doing something wrong or it is impossible to use mixin templates like that? Looks like a compiler bug, since substituting the real methods makes the `mixin template` code compile fine Also, remove the `const`, otherwise the method will word only on `const` instances even if the bug gets fixed ```d mixin template sum(T, R) { R opBinary(string op)(T rhs) const if (op == "+"){ return R(x + rhs.x, y + rhs.y, z + rhs.z); } } mixin template diff(T, R) { R opBinary(string op)(T rhs) const if (op == "-") { return R(x - rhs.x, y - rhs.y, z - rhs.z); } } struct point{ float x, y, z; mixin diff!(point, vec); mixin sum!(vec, point); } struct vec{ float x, y, z; } void main(){ point p1 = {1,2,3}, p2 = {5,6,7}; vec v1 = p1.opBinary!"-"(p2); // made - explicit vec v2 = {2,-1,0}; point p3 = p1.opBinary!"+"(v2); // made + explicit }
Mixin Templates and Operators
I have two structs, point and vec, in which I want to implement some arithmetic operations. The operations are: ``` point - point = vec point + vec = point ``` Using mixin templates the code compiles but calling the operations in the main causes an "incompatible type" Error: ```d mixin template sum(T, R) { R opBinary(string op)(T rhs) const if (op == "+"){ return R(x + rhs.x, y + rhs.y, z + rhs.z); } } mixin template diff(T, R) { R opBinary(string op)(T rhs) const if (op == "-") { return R(x - rhs.x, y - rhs.y, z - rhs.z); } } struct point{ float x, y, z; mixin diff!(point, vec); mixin sum!(vec, point); } struct vec{ float x, y, z; } void main(){ point p1 = {1,2,3}, p2 = {5,6,7}; vec v1 = p1-p2; vec v2 = {2,-1,0}; point p3 = p1+v2; } ``` The output of `dub run` is ``` Performing "debug" build using /usr/bin/dmd for x86_64. query ~master: building configuration "application"... source/app.d(27,13): Error: incompatible types for `(p1) - (p2)`: both operands are of type `point` source/app.d(30,15): Error: incompatible types for `(p1) + (v2)`: `point` and `vec` /usr/bin/dmd failed with exit code 1. ``` I tried to implement a single template: ```d mixin template sumDiff(T, R){ R opBinary(string op)(T rhs) const if (op == "+" || op == "-"){ return mixin("R(x " ~ op ~ " rhs.x, y " ~ op ~ "rhs.y, z " ~ op ~ " rhs.z)"); } } ``` but the same error occurs. If I don't use the mixin templates and, instead, I overload the operations into the structures everything works. ```d struct point{ float x, y, z; vec opBinary(string op)(point rhs) const if (op == "-") { return vec(x - rhs.x, y - rhs.y, z - rhs.z); } point opBinary(string op)(vec rhs) const if (op == "+") { return point(x + rhs.x, y + rhs.y, z + rhs.z); } } struct vec{ float x, y, z; } void main(){ point p1 = {1,2,3}, p2 = {5,6,7}; vec v1 = p1-p2; vec v2 = {2,-1,0}; point p3 = p1+v2; } ``` Am I doing something wrong or it is impossible to use mixin templates like that?
Variadic templates with default parameters.
Consider the following code: ```d import std; auto logVariadic(T...)(T x,int line=__LINE__,string file=__FILE__) { writeln(file,":",line," ",x); } int variadicCnt; auto logVariadicWrapper(T...)(T x, int line=__LINE__, string file=__FILE__) { variadicCnt++; logVariadic(x,line,file); } auto args(T...)(T x) { static struct Args(T...) { static foreach(i, t; T) { mixin(t, " v",i,";"); } } return Args!T(x); } auto log(Args)(Args args, int line=__LINE__, string file=__FILE__) { writeln(file,":",line," ",args.tupleof); } int cnt; auto logWrapper(Args)(Args args, int line=__LINE__, string file=__FILE__) { cnt++; log(args,line,file); } void main() { logVariadic("Hello ",1234); logVariadicWrapper(1234, " is a number."); //produces wrong line number and adds line number and file name at the end writeln(variadicCnt); log(args("Hello ",1234)); logWrapper(args(1234, " is a number.")); writeln(cnt); } ``` Produces output: onlineapp.d:32 Hello 1234 onlineapp.d:10 1234 is a number.33onlineapp.d 1 onlineapp.d:35 Hello 1234 onlineapp.d:36 1234 is a number. 1 Any other ways to be able to achieve the same without double wrapping arguments like above? I guess the above is okay but I thought I would see other options. (I know that one can pass line and file as template arguments, but that produces a new instance of log or logWrapper per use).
Re: Help needed to learn templates
On Saturday, 19 March 2022 at 22:31:19 UTC, Stanislav Blinov wrote: It is appearing not in the `static if`, but in the `is` expression, which I described further in the rest of my first reply. Sorry if that wasn't clear. No, it was my mistake, I missed it. The other template syntax - `template foo(alias T)` can take as `T` any symbol, not just a type. I understand this. It comes from you, the programmer. Like I said before, `is(T == U[], U)` means "is T an array of some type, the type which I (the programmer) would like to refer to as U?". That's all there is to it (well, not quite, but it should suffice for starters). You're simply introducing an identifier. So, when `T` is an `int[][][]`, naturally, `U` becomes an alias to `int[][]` (look at the converse - when `U` is `int[][]`, `U[]` is naturally an `int[][][]`). Okay, got it. You can think of that test as this: ```d import std.traits : isDynamicArray; // ... static if (isDynamicArray!T) { alias U = typeof(T.init[0]); // ... } ``` Yes, in this case everything is simple and clear. ...which would roughly be the same thing - you test if `T` is a dynamic array of some type, and then make an alias for that array's element type. It's just that the `is` expression allows you to create such alias in situ. Okay. Got the point. Thanks. Now, I understand that why Ali suggest me to learn **`is()`** expression.
Re: Help needed to learn templates
On Saturday, 19 March 2022 at 13:38:42 UTC, Vinod K Chandran wrote: On Saturday, 19 March 2022 at 11:47:53 UTC, Stanislav Blinov wrote: No. First of all Thanks for the reply. The answer "No" is a wonder to me. Because, from my point of view, `U` is coming from nowhere. My understanding is, we can use any parameter of a template inside the template. So in this case `U` is not in the parameter list. It is suddenly appearing in that `static if`. It is appearing not in the `static if`, but in the `is` expression, which I described further in the rest of my first reply. Sorry if that wasn't clear. The test is not `T t == U[]`. It is `is(T t == U[], U)`. Okay, I understand. Actually, the lower case `t` is not needed there, you can simply write `is(T == U[], U)`. So the `T` is not the type. It's the parameter. Right ? So a template doesn't need a type. Only the parameter, right ? (I think I am too dumb to ask this. Please forgive me.) Oh don't worry, this topic is not at all obvious with the `is` expression having its own syntax and semantics. `T` is a type, a type you instantiate `rank` with. `template rank(T)` *does* expect a type as a parameter. The other template syntax - `template foo(alias T)` can take as `T` any symbol, not just a type. Yes, and `U` then becomes `int[][]`. Which is why the template recurses down and instantiates itself with `U`, until `T` fails the test. In order to understand this, I need to understand from where the `U` comes. It comes from you, the programmer. Like I said before, `is(T == U[], U)` means "is T an array of some type, the type which I (the programmer) would like to refer to as U?". That's all there is to it (well, not quite, but it should suffice for starters). You're simply introducing an identifier. So, when `T` is an `int[][][]`, naturally, `U` becomes an alias to `int[][]` (look at the converse - when `U` is `int[][]`, `U[]` is naturally an `int[][][]`). You can think of that test as this: ```d import std.traits : isDynamicArray; // ... static if (isDynamicArray!T) { alias U = typeof(T.init[0]); // ... } ``` ...which would roughly be the same thing - you test if `T` is a dynamic array of some type, and then make an alias for that array's element type. It's just that the `is` expression allows you to create such alias in situ.
Re: Help needed to learn templates
On Saturday, 19 March 2022 at 16:08:33 UTC, Ali Çehreli wrote: Here is the clickable url: http://ddili.org/ders/d.en/is_expr.html I just read it again and I still like what I wrote there. :) (Usually it is the other way around.) Ali Thanks. Let me read that chapter.
Re: Help needed to learn templates
On Saturday, 19 March 2022 at 15:58:25 UTC, Ali Çehreli wrote: I wrote a chapter about the is expression but it's still mysterious to me. :) ddili.org/ders/d.en/is_expr.html Thanks for the reply. I think I choose the wrong book. I knew about your book but I thought this one is specially written for templates. I will read the template chapters in **`Programming in D`**. It means "if T matches U[] and U is a type". "a type" because it is just U in the is expression list. So as per the eponymous trick, **`enum size_t rank`** will be executed directly. Right ? But in that case, **`rank`** template doesn't take a parameter. There is only the type parameter which is **`T`**. So I am still in confusion about **`U`**. I believe at least some of the traits have been added since that doc document was written. I would write it in a much simpler way using template constraints today: ```d template rank(T) { import std.traits : isArray; import std.range : ElementType; static if (isArray!T) { enum size_t rank = 1 + rank!(ElementType!T); } else { enum size_t rank = 0; } } ``` This template is very easy to understand and I have no confusions about it. Because, it only takes **`T`** as type parameter and there is no magical **`U`**. However, note how the template constraints had to be repeated as isArray!T and !isArray!T in that case. Yeah, I noted. Not at all! The is expression is the weirdest part of D. Oh I see.
Re: Help needed to learn templates
On 3/19/22 08:58, Ali Çehreli wrote: > I wrote a chapter about the is expression but it's still mysterious to > me. :) > >ddili.org/ders/d.en/is_expr.html Here is the clickable url: http://ddili.org/ders/d.en/is_expr.html I just read it again and I still like what I wrote there. :) (Usually it is the other way around.) Ali
Re: Help needed to learn templates
On 3/19/22 06:38, Vinod K Chandran wrote: > On Saturday, 19 March 2022 at 11:47:53 UTC, Stanislav Blinov wrote: >> >> No. >> > First of all Thanks for the reply. The answer "No" is a wonder to me. I wrote a chapter about the is expression but it's still mysterious to me. :) ddili.org/ders/d.en/is_expr.html I may be saying some things wrong there but that's my mental model. > Because, from my point of view, `U` is coming from nowhere. Agreed. It is similar to U's coming from nowhere below: void foo(U)(U[] array) { } So, in my mental model, that use of the is expression is the same but written in the reverse order from foo above: static if (is(T t == U[], U)) It means "if T matches U[] and U is a type". "a type" because it is just U in the is expression list. I believe at least some of the traits have been added since that doc document was written. I would write it in a much simpler way using template constraints today: template rank(T) { import std.traits : isArray; import std.range : ElementType; static if (isArray!T) { enum size_t rank = 1 + rank!(ElementType!T); } else { enum size_t rank = 0; } } Or one can separate the logic in two template definitions: import std.traits : isArray; template rank(T) if (isArray!T) { import std.range : ElementType; enum size_t rank = 1 + rank!(ElementType!T); } template rank(T) if (!isArray!T) { enum size_t rank = 0; } However, note how the template constraints had to be repeated as isArray!T and !isArray!T in that case. > My > understanding is, we can use any parameter of a template inside the > template. So in this case `U` is not in the parameter list. It is > suddenly appearing in that `static if`. In my mental model, the is expression uses at least a part of the template system. >> you can simply write >> `is(T == U[], U)`. >> > So the `T` is not the type. T is the type because it is introduced as simply T in the parameter list. If it were 'int T', then it would be an int. So in that sense, it is a type-kind template parameter. > It's the parameter. Right ? So a template > doesn't need a type. Only the parameter, right ? The way I read it is: "T is a type that matches U[] where U is a type as well." > (I think I am too dumb > to ask this. Please forgive me.) Not at all! The is expression is the weirdest part of D. Ali
Re: Help needed to learn templates
On Saturday, 19 March 2022 at 08:49:02 UTC, Salih Dincer wrote: Thanks for the reply. You explained the idea very well and it's easy to understand for a novice.
Re: Help needed to learn templates
On Saturday, 19 March 2022 at 11:47:53 UTC, Stanislav Blinov wrote: No. First of all Thanks for the reply. The answer "No" is a wonder to me. Because, from my point of view, `U` is coming from nowhere. My understanding is, we can use any parameter of a template inside the template. So in this case `U` is not in the parameter list. It is suddenly appearing in that `static if`. The test is not `T t == U[]`. It is `is(T t == U[], U)`. Okay, I understand. Actually, the lower case `t` is not needed there, you can simply write `is(T == U[], U)`. So the `T` is not the type. It's the parameter. Right ? So a template doesn't need a type. Only the parameter, right ? (I think I am too dumb to ask this. Please forgive me.) Yes, and `U` then becomes `int[][]`. Which is why the template recurses down and instantiates itself with `U`, until `T` fails the test. In order to understand this, I need to understand from where the `U` comes.
Re: Help needed to learn templates
On Saturday, 19 March 2022 at 05:54:26 UTC, Vinod K Chandran wrote: Question 1 - `U` is appearing in the first static if statement. But we had to write `U` on the template line, right? Like - `template rank(T, U)` No. Question 2 - The statif if test is - `T t == U[ ]` What does that mean ? The test is not `T t == U[]`. It is `is(T t == U[], U)`. https://dlang.org/spec/expression.html#is-identifier-equal ``` is ( Type Identifier == TypeSpecialization ) The condition is satisfied if Type is semantically correct and is the same as TypeSpecialization. The Identifier is declared to be either an alias of the TypeSpecialization or, if TypeSpecialization is dependent on Identifier, the deduced type. ``` You simply introduce new identifiers. Basically, the test means "is T an array of some type which I would like referred to as U?". Actually, the lower case `t` is not needed there, you can simply write `is(T == U[], U)`. Question 3 - if `T t == U[ ]` is the test, then I think when we pass ```d rank!(int[ ][ ][ ]) ``` The test will be `int[ ][ ][ ] == U[ ]`, Right ? Yes, and `U` then becomes `int[][]`. Which is why the template recurses down and instantiates itself with `U`, until `T` fails the test.
Re: Help needed to learn templates
On Saturday, 19 March 2022 at 05:54:26 UTC, Vinod K Chandran wrote: Question 1 - `U` is appearing in the first static if statement. But we had to write `U` on the template line, right? Like - `template rank(T, U)` Question 2 - The statif if test is - `T t == U[ ]` What does that mean ? Question 3 - if `T t == U[ ]` is the test, then I think when we pass You don't need anything extra while using it... I think U is declare a range. Here is a recursive pattern. Just like the code I wrote below: ```d import std.stdio; alias outer O; struct outer { int i; O * o; } int rank(T)(T* s) { int count = 1; if(s.o is null) return count; return count + rank(s.o); } void main() { auto test = O(1, new O(2, new O(3, new O))); rank(test.o).writeln; test.i.write(", "); test.o.i.write(", "); test.o.o.i.writeln; } /* CONSOLEOUT: 3 1, 2, 3 */ ``` SDB@79
Help needed to learn templates
Hi all, I am trying to learn D templates with Philippe Sigaud's "D Templates: A Tutorial". So far so good. I have completed first 19 pages and in the 20th page, I found an obstacle. This is the code. ```d module rank1; template rank(T) { static if (is(T t == U[], U)) // is T an array of U, for some type U? enum size_t rank = 1 + rank!(U); // then let’s recurse down. else enum size_t rank = 0; // Base case, ending the recursion. } module using_rank1; import rank1; static assert(rank!(int) == 0); static assert(rank!(int[]) == 1); static assert(rank!(int[][]) == 2); static assert(rank!(int[][][]) == 3); ``` Question 1 - `U` is appearing in the first static if statement. But we had to write `U` on the template line, right? Like - `template rank(T, U)` Question 2 - The statif if test is - `T t == U[ ]` What does that mean ? Question 3 - if `T t == U[ ]` is the test, then I think when we pass ```d rank!(int[ ][ ][ ]) ``` The test will be `int[ ][ ][ ] == U[ ]`, Right ?
Re: Simple way to handle rvalues and templates.
On Sunday, 27 February 2022 at 06:11:28 UTC, Ali Çehreli wrote: I don't like the name readFrom() yet but that works. :) It seems very delicious, can stay as read(): ```d auto read(T, Endian E = Endian.bigEndian, R) (R range) { import bop = std.bitmanip; return bop.read!(T, E)(range); } void main() { import std.system; ubyte[8] d = [ 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xFF, 0xFF ]; ushort us = d[4..6].read!ushort; assert(us == 0x); } ``` SDB79
Re: Simple way to handle rvalues and templates.
On 2/26/22 19:38, Chris Piker wrote: > But this doesn't work: > ```d > import std.bitmanip, std.system; > ubyte[8192] data; > > ushort us = data[4..6].read!(ushort, Endian.bigEndian); > ``` > The reasons for this are probably old hat for seasoned D programmers by > this is really confusing for newbies. Agreed. read() is designed to advance the buffer that it is given. It is thought to be convenient for the next read() operation because the semantics would be "read a ushort and then read an int", etc. And the buffer would be consumed by read(). To play the way read() wants us to play, the first thing that comes to mind is to read original data into a storage and define a range (data below) for read() to consume. However, it requires skipping over bytes by e.g. dropExactly(), which is presumably a very fast operation for slices: void main() { import std.bitmanip, std.system; ubyte[8192] storage; auto data = storage[]; import std.range; data.dropExactly(4); ushort us = data.read!(ushort, Endian.bigEndian); // Here, data is ready for the next read. } Another option is to write a wrapper which takes your slice by copy so that read() is happy as it consumes a parameter instead of your rvalue: import std.system; // Adapting read()'s interface with one difference: 'ref' is removed: auto readFrom(T, Endian endianness = Endian.bigEndian, R)(R range) { import std.bitmanip; return range.read!(ushort, endianness); } void main() { import std.bitmanip, std.system; ubyte[8192] data; ushort us = data[4..6].readFrom!(ushort, Endian.bigEndian); } I don't like the name readFrom() yet but that works. :) Ali
Simple way to handle rvalues and templates.
Hi D I have bit of code that was tripping me up. I need to parse small fields out of a big binary read, and it looks like some operations just can't be composed when it comes to using templates. So this works: ```d import std.bitmanip, std.system; ubyte[8192] data; ubyte[] temp = data[4..6]; ushort us = temp.read!(ushort, Endian.bigEndian); // intentionally provided the default byte order for readability ``` But this doesn't work: ```d import std.bitmanip, std.system; ubyte[8192] data; ushort us = data[4..6].read!(ushort, Endian.bigEndian); ``` The reasons for this are probably old hat for seasoned D programmers by this is really confusing for newbies. Is there a better way to handle this instead of making a bunch of temporary variables that I don't care about? Matlab has this behavior too, statements that should be composable aren't, and it drives me crazy since Java and Python don't seem to suffer from this problem near a much.
Re: Can anyone provide an example of how D templates are overridable by global symbols?
On Saturday, 29 January 2022 at 00:52:10 UTC, H. S. Teoh wrote: Trying out what I suggested on different OS's and toolchains will give you a good idea of what's actually out there. I will just reply with a quote from https://forum.dlang.org/post/mailman.400.1643853436.20251.digitalmars-d-le...@puremagic.com : "In any case, just because it worked by chance does not mean it's OK".
Re: Can anyone provide an example of how D templates are overridable by global symbols?
On 1/28/22 16:17, Siarhei Siamashka wrote: > On Friday, 28 January 2022 at 23:43:00 UTC, H. S. Teoh wrote: >> You don't have to rely on any opinions. Try it out yourself and find >> out for sure. > > I guess, my problem and the source of all confusion is that I'm way too > used to developing C++ code. I am confused too. Weak symbols are a concept beyond D and C++ so it should be the same with C++. Testing, the following C++ program does compile foo as a weak symbol as well: template void foo() { } int main() { foo(); } > And in the C++ ecosystem your > recommendation is a recipe for disaster. And it is. > It's absolutely necessary to > have perfect understanding about what's going on and which guarantees > are provided. Good luck with that. :) There aren't many people who know what linkers and loaders actually do. > Accidentally relying on undefined behavior will backfire, > because [Murphy's law](https://en.wikipedia.org/wiki/Murphy%27s_law) is > unfortunately very real. Yes. What Johan said makes the most sense to me: The onus of ensuring ODR is on the user. Given the state of languages and linkers, I have to ensure that. Ali
Re: Can anyone provide an example of how D templates are overridable by global symbols?
On Sat, Jan 29, 2022 at 12:17:49AM +, Siarhei Siamashka via Digitalmars-d-learn wrote: > On Friday, 28 January 2022 at 23:43:00 UTC, H. S. Teoh wrote: > > You don't have to rely on any opinions. Try it out yourself and find > > out for sure. > > I guess, my problem and the source of all confusion is that I'm way > too used to developing C++ code. And in the C++ ecosystem your > recommendation is a recipe for disaster. It's absolutely necessary to > have perfect understanding about what's going on and which guarantees > are provided. Accidentally relying on undefined behavior will > backfire, because [Murphy's > law](https://en.wikipedia.org/wiki/Murphy%27s_law) is unfortunately > very real. Trying out what I suggested on different OS's and toolchains will give you a good idea of what's actually out there. T -- If lightning were to ever strike an orchestra, it'd always hit the conductor first.
Re: Can anyone provide an example of how D templates are overridable by global symbols?
On Friday, 28 January 2022 at 23:43:00 UTC, H. S. Teoh wrote: You don't have to rely on any opinions. Try it out yourself and find out for sure. I guess, my problem and the source of all confusion is that I'm way too used to developing C++ code. And in the C++ ecosystem your recommendation is a recipe for disaster. It's absolutely necessary to have perfect understanding about what's going on and which guarantees are provided. Accidentally relying on undefined behavior will backfire, because [Murphy's law](https://en.wikipedia.org/wiki/Murphy%27s_law) is unfortunately very real.
Re: Can anyone provide an example of how D templates are overridable by global symbols?
On Fri, Jan 28, 2022 at 11:01:41PM +, Siarhei Siamashka via Digitalmars-d-learn wrote: [...] > Internet seems to disagree about what happens when multiple weak > symbols are encountered and various interpretations can be found: > "Given multiple weak symbols, choose any of the weak symbols", "if > there exists several weak symbols, GCC will choose one that have the > largest size (memory occupation)", etc. And I'm not inclined to > happily rely on either of these opinions. You don't have to rely on any opinions. Try it out yourself and find out for sure. E.g., compile several versions of exactly the same function (e.g, each printing something different), make sure you mark them as weak functions and rename the object files into different names. Link them all together with another object file that contains main() that calls the weak symbol. Running the program ought to tell you which version got linked. Try linking in different orders (specify the object files in different orders in your compile/link command) to see what differences there might be. T -- Democracy: The triumph of popularity over principle. -- C.Bond
Re: Can anyone provide an example of how D templates are overridable by global symbols?
On Thursday, 27 January 2022 at 21:50:12 UTC, kinke wrote: An example: [...] Now if the calls are inlined, the behavior might not be consistent anymore. So separate compilations with different compiler flags can cause observable differences. Thanks! This was very informative. Though I'm not convinced that having a single (but randomly chosen) function used across the whole program is much better than a random mix of multiple versions. Especially if (unlike your example) this function doesn't identify itself in a user visible way. Both cases are bad, one is just much worse than the other. Internet seems to disagree about what happens when multiple weak symbols are encountered and various interpretations can be found: "Given multiple weak symbols, choose any of the weak symbols", "if there exists several weak symbols, GCC will choose one that have the largest size (memory occupation)", etc. And I'm not inclined to happily rely on either of these opinions.
Re: Can anyone provide an example of how D templates are overridable by global symbols?
An example: a.d: ``` import core.stdc.stdio; void foo()() { version (Oops) printf(" foo - oops\n"); else printf(" foo\n"); } void doA() { printf("doA:\n"); foo!(); } ``` b.d: ``` import core.stdc.stdio; import a; void main() { printf("main:\n"); foo!(); doA(); } ``` ```bash $ dmd -c a.d -version=Oops $ dmd -c b.d $ dmd a.o b.o -of=ab $ ./ab main: foo - oops doA: foo - oops $ dmd b.o a.o -of=ba $ ./ba main: foo doA: foo ``` Each object file contains a foo!() instantiation (in a.o, the Oops version). No inlining, so the linker takes one of the weak definitions, and we end up with a consistent behavior for both calls - but the picked version is determined by the order of the object files. Now if the calls are inlined, the behavior might not be consistent anymore. So separate compilations with different compiler flags can cause observable differences.
Re: Can anyone provide an example of how D templates are overridable by global symbols?
On Thursday, 9 December 2021 at 21:06:54 UTC, Siarhei Siamashka wrote: On Thursday, 9 December 2021 at 20:53:52 UTC, Siarhei Siamashka wrote: How would one construct a simple example of a template symbol getting successfully overridden by a global symbol? Forgot to mention that a template function can be overridden by another function with the same name. But only as long as all of this happens in the scope of a single module. Here are a few examples (all of them successfully compile and run): ```D import std.stdio; T f(T)(T a, T b) { return a + b; } int f(int a, int b) { return a - b; } void main() { f(2, 1).writeln; // prints "1" } ``` ```D import std.stdio; int f(int a, int b) { return a - b; } T f(T)(T a, T b) { return a + b; } void main() { f(2, 1).writeln; // prints "1" } ``` ```D import std.stdio; import template_f; int f(int a, int b) { return a - b; } void main() { f(2, 1).writeln; // prints "1" } ``` ```D import std.stdio; import nontemplate_f; T f(T)(T a, T b) { return a + b; } void main() { f(2, 1).writeln; // prints "3" } ``` This mostly agrees with the following part of the D language specification: https://dlang.org/spec/module.html#name_lookup Except that having a template function and a non-template function with the same name within the same module scope doesn't seem to be explicitly documented in the D specification. But such name clash appears to be resolved in favor of a non-template function. And this behavior shouldn't inhibit functions inlining.
Re: How to properly use variadic templates (functions)?
sorry for intervening... :) On Wednesday, 22 December 2021 at 08:17:03 UTC, rempas wrote: No garbage collector, no exceptions GOLDEN WORDS!!! Yeah, Seriously D's developers and user really underestimate the fact that the biggest percent of people not using D are doing so because of the Garbage Collector. D's community makes it like it's not much of a big deal but it actually is. Exactly!
Re: How to properly use variadic templates (functions)?
On Tuesday, 21 December 2021 at 22:50:57 UTC, russhy wrote: I took a look and to be honest, it's the same story as everything in the STD, they try to do everything at the same time, so they up end calling each other, you end up lost in multiple 8k LOC modules, not understanding what the function is doing anymore, it's a rotten place Finally someone said it!!! No offense to the Phobos developers but the library is a huge mess in runtime/compile performance and its API is not always clean and consistent making the library annoying to use some times. Hell, even libc is not very good as it is very bare bones and believe it or not, we could achieve better performance for most staff from libc. We need a new system library that won't depend on anything ASAP! No garbage collector, no exceptions, no complicated struct types etc. Just a simple, clean, consistent, really fast and easy to use library! Plus they are not nogc Yeah, Seriously D's developers and user really underestimate the fact that the biggest percent of people not using D are doing so because of the Garbage Collector. D's community makes it like it's not much of a big deal but it actually is. OP's attempt is clean, you know what's up, you can read the code, free of dependencies (for now), and hopefully nogc i want to encourage more code like that Thanks! Code readability and a clean and easy to use API is the plan for the library. I want people to enjoy using the library while they will have the best possible runtime and compile performance at the same time. I am a novice even to the easier high level programming and so I will not a lot of help. But this will not stop me and hopefully we can make something great together!
Re: How to properly use variadic templates (functions)?
On Tuesday, 21 December 2021 at 18:51:38 UTC, Stanislav Blinov wrote: On Tuesday, 21 December 2021 at 15:42:59 UTC, russhy wrote: Please keep us updated, that'll be interesting to see how a pure D printf would look like! It already exists, it's called std.format.write.formattedWrite, in terms of which things like std.stdio.writef are implemented. I took a look and to be honest, it's the same story as everything in the STD, they try to do everything at the same time, so they up end calling each other, you end up lost in multiple 8k LOC modules, not understanding what the function is doing anymore, it's a rotten place Plus they are not nogc OP's attempt is clean, you know what's up, you can read the code, free of dependencies (for now), and hopefully nogc i want to encourage more code like that
Re: How to properly use variadic templates (functions)?
On Tuesday, 21 December 2021 at 15:42:59 UTC, russhy wrote: Please keep us updated, that'll be interesting to see how a pure D printf would look like! It already exists, it's called std.format.write.formattedWrite, in terms of which things like std.stdio.writef are implemented.
Re: How to properly use variadic templates (functions)?
On Tuesday, 21 December 2021 at 17:33:09 UTC, Steven Schveighoffer wrote: The reason your original isn't working is that indexing a list of differently-typed things cannot be done using a runtime index. I'd say that an inner function + static foreach + switch is the best way to convert from runtime to compile-time values. And in general, I would say having function templates that handle each arg type are usually conducive to clean and easy code. But in the case you are suggesting, as long as you don't need to iterate them out of order, what you can do is foreach the args tuple, and do something like: ```d foreach(arg; args) { writeUpToNextDelimeter(prompt); // updates prompt to point at next delimiter processArg(arg, prompt); } ``` -Steve Got that! Thanks a lot Steve!
Re: How to properly use variadic templates (functions)?
On 12/21/21 4:28 AM, rempas wrote: On Tuesday, 21 December 2021 at 08:42:35 UTC, vit wrote: You can use switch + static foreach: ```d import std.stdio; //this print args in reverse order: void print(T...)(string prompt, T args) { void print_arg(size_t index){ switch(index){ static foreach(i, a; args){ case i: // handle your other types write(a); return; } default: assert(0, "no impl"); } } write(prompt); size_t len = args.length; while(len --> 0) print_arg(len); } void main(){ print("Prompt (ignored): ", "Hello", " world!\n", 123); } ``` Cool! That's probably what I wanted to do! It seems that when looping inside a "static foreach" and taking the index, then I can compare it with a value that is not calculated at compile time. This way I can also check for the type of the variables and do my original plan which will make the function even better! Thanks a lot for the help dude!!! The reason your original isn't working is that indexing a list of differently-typed things cannot be done using a runtime index. I'd say that an inner function + static foreach + switch is the best way to convert from runtime to compile-time values. And in general, I would say having function templates that handle each arg type are usually conducive to clean and easy code. But in the case you are suggesting, as long as you don't need to iterate them out of order, what you can do is foreach the args tuple, and do something like: ```d foreach(arg; args) { writeUpToNextDelimeter(prompt); // updates prompt to point at next delimiter processArg(arg, prompt); } ``` -Steve
Re: How to properly use variadic templates (functions)?
On Tuesday, 21 December 2021 at 15:42:59 UTC, russhy wrote: Please keep us updated, that'll be interesting to see how a pure D printf would look like! Glad someone is interested! I'm actually planning to make a whole library ;) Check my [thread](https://forum.dlang.org/thread/frjbgaymuxjqperis...@forum.dlang.org) were I'm asking about your opinion on formatting and what is my current approach.
Re: How to properly use variadic templates (functions)?
Please keep us updated, that'll be interesting to see how a pure D printf would look like!
Re: How to properly use variadic templates (functions)?
On Tuesday, 21 December 2021 at 08:42:35 UTC, vit wrote: You can use switch + static foreach: ```d import std.stdio; //this print args in reverse order: void print(T...)(string prompt, T args) { void print_arg(size_t index){ switch(index){ static foreach(i, a; args){ case i: // handle your other types write(a); return; } default: assert(0, "no impl"); } } write(prompt); size_t len = args.length; while(len --> 0) print_arg(len); } void main(){ print("Prompt (ignored): ", "Hello", " world!\n", 123); } ``` Cool! That's probably what I wanted to do! It seems that when looping inside a "static foreach" and taking the index, then I can compare it with a value that is not calculated at compile time. This way I can also check for the type of the variables and do my original plan which will make the function even better! Thanks a lot for the help dude!!!
Re: How to properly use variadic templates (functions)?
On Tuesday, 21 December 2021 at 08:26:17 UTC, rempas wrote: On Tuesday, 21 December 2021 at 08:11:39 UTC, Anonymouse wrote: I'm not certain I understand, but won't `foreach (i, a; args) { /* ... */ }` in his example do that? As in, if you necessarily must index `args` instead of using a foreach variable, ```d import core.stdc.stdio : putc, stdout; void print(T...)(string prompt, T args) { foreach (i, a; args) { alias A = typeof(args[i]); static if (is(A : string)) { for (int j = 0; j < args[i].length; j++) { putc(args[i][j], stdout); } } else { // handle your other types print("", A.stringof); } } } void main() { print("Prompt (ignored)", "Hello", " world!\n", 123); } ``` No it will not. I will try to explain it the best way I can. When I say I want to index args, I mean that I want to index and choose which argument to use rather than use them continuously one after another inside a `foreach`. For example check the following call: `print("Hello %s!%c", "world", '\n');` In that case I want to first print print from "H" up to (but not include) "%s". Then I want to print the first argument. After that, I want to print the '!' character and then I want to print the second argument. So I need a way to keep track which argument was the last one I printed and manually choose which argument to use. So `foreach` will not do in that case because I don't want to continuously use the arguments one after another. Is is more clear now? "writef" exists in phobos so I'm pretty sure that there is a way to do that. You can use switch + static foreach: ```d import std.stdio; //this print args in reverse order: void print(T...)(string prompt, T args) { void print_arg(size_t index){ switch(index){ static foreach(i, a; args){ case i: // handle your other types write(a); return; } default: assert(0, "no impl"); } } write(prompt); size_t len = args.length; while(len --> 0) print_arg(len); } void main(){ print("Prompt (ignored): ", "Hello", " world!\n", 123); } ```
Re: How to properly use variadic templates (functions)?
On Tuesday, 21 December 2021 at 08:11:39 UTC, Anonymouse wrote: I'm not certain I understand, but won't `foreach (i, a; args) { /* ... */ }` in his example do that? As in, if you necessarily must index `args` instead of using a foreach variable, ```d import core.stdc.stdio : putc, stdout; void print(T...)(string prompt, T args) { foreach (i, a; args) { alias A = typeof(args[i]); static if (is(A : string)) { for (int j = 0; j < args[i].length; j++) { putc(args[i][j], stdout); } } else { // handle your other types print("", A.stringof); } } } void main() { print("Prompt (ignored)", "Hello", " world!\n", 123); } ``` No it will not. I will try to explain it the best way I can. When I say I want to index args, I mean that I want to index and choose which argument to use rather than use them continuously one after another inside a `foreach`. For example check the following call: `print("Hello %s!%c", "world", '\n');` In that case I want to first print print from "H" up to (but not include) "%s". Then I want to print the first argument. After that, I want to print the '!' character and then I want to print the second argument. So I need a way to keep track which argument was the last one I printed and manually choose which argument to use. So `foreach` will not do in that case because I don't want to continuously use the arguments one after another. Is is more clear now? "writef" exists in phobos so I'm pretty sure that there is a way to do that.
Re: How to properly use variadic templates (functions)?
On Tuesday, 21 December 2021 at 06:44:36 UTC, rempas wrote: This will not do for me because I want to do formatted output and I need the index. But thanks a lot for tying to help! I'm not certain I understand, but won't `foreach (i, a; args) { /* ... */ }` in his example do that? As in, if you necessarily must index `args` instead of using a foreach variable, ```d import core.stdc.stdio : putc, stdout; void print(T...)(string prompt, T args) { foreach (i, a; args) { alias A = typeof(args[i]); static if (is(A : string)) { for (int j = 0; j < args[i].length; j++) { putc(args[i][j], stdout); } } else { // handle your other types print("", A.stringof); } } } void main() { print("Prompt (ignored)", "Hello", " world!\n", 123); } ```
Re: How to properly use variadic templates (functions)?
On Monday, 20 December 2021 at 22:02:02 UTC, russhy wrote: Here how i'd do, but i'm not sure how to keep track of the index of the arguments, i forgot.. ```D import core.stdc.stdio: putc, stdout; void print(T...)(string prompt, T args) { foreach (a; args) { alias A = typeof(a); static if (is(A : string)) { for (int j = 0; j < a.length; j++) { putc(a[j], stdout); } } else { // handle your other types print("", A.stringof); } } } void main() { print("Prompt (ignored)", "Hello", " world!\n", 123); } ``` This will not do for me because I want to do formatted output and I need the index. But thanks a lot for tying to help!
Re: How to properly use variadic templates (functions)?
On Monday, 20 December 2021 at 21:49:59 UTC, Adam D Ruppe wrote: still use foreach(arg; args) and skip that index variable. I know I can use foreach ("static foreach" more specifically) but I need to be able to get the index to choose a specific argument because I want to do formatting (that's why I said "printf")
Re: How to properly use variadic templates (functions)?
Here how i'd do, but i'm not sure how to keep track of the index of the arguments, i forgot.. ```D import core.stdc.stdio: putc, stdout; void print(T...)(string prompt, T args) { foreach (a; args) { alias A = typeof(a); static if (is(A : string)) { for (int j = 0; j < a.length; j++) { putc(a[j], stdout); } } else { // handle your other types print("", A.stringof); } } } void main() { print("Prompt (ignored)", "Hello", " world!\n", 123); } ```
Re: How to properly use variadic templates (functions)?
On Monday, 20 December 2021 at 21:26:45 UTC, rempas wrote: // Suppose all 'args' are of type "string" for this example still use foreach(arg; args) and skip that index variable.
How to properly use variadic templates (functions)?
I'm trying to implement "printf" and I'm getting an error. The smallest possible code to demonstrate the error is: ``` import core.stdc.stdio; void print(T...)(string prompt, T args) { // Suppose all 'args' are of type "string" for this example ulong carg = 0; for (ulong i = 0; i < args[carg].length; i++) { putc(args[carg][i], stdout); } } void main() { print("Prompt (ignored)", "Hello", " world!\n"); } ``` The error output I'm getting is: ``` test.d(6): Error: variable `carg` cannot be read at compile time test.d(7): Error: variable `carg` cannot be read at compile time test.d(12): Error: template instance `test.print!(string, string)` error instantiating ``` There is another error in my original code. Let's see the following line: `u64 str_len = strlen(args[carg]); //u64 = ulong` Now this should also give me the error that the variable "carg" cannot be read at compile time (which it probably does as it gives me an error when trying to use "str_len" inside a "for loop") but instead it gives me the following error: ``` Error: function `core.stdc.string.strlen(scope const(char*) s)` is not callable using argument types `(string)` cannot pass argument `_param_1` of type `string` to parameter `scope const(char*) s` ``` Any ideas?
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 18:58:39 UTC, bachmeier wrote: You can see the ["String mixins" section here](http://ddili.org/ders/d.en/mixin.html) for more details. Mixins are generated at compile time, so if you're referring to a string mixin inside a runtime loop, the code will not be generated every time the loop runs. Thanks! Yeah after I commented, I thought a little bit about how they generate code at compile time like you said and understand that what I'm saying doesn't make much sense. Have a nice day my friend!
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 18:23:44 UTC, rempas wrote: On Monday, 20 December 2021 at 18:12:35 UTC, Stanislav Blinov wrote: https://dlang.org/spec/traits.html#identifier Thanks!!! Finally I was able to do it! The code is the following (well not in my final project but it's a demonstration): ``` enum add_char(string c) = `if (stdout_index < STDOUT_BUF_LEN) { stdout_buffer[stdout_index++] =` ~ c ~ `; continue; } else { sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index); stdout_index = 0; stdout_buffer[stdout_index++] =` ~ c ~ `; continue; }`; void main() { mixin(add_char!(__traits(identifier, c))); } ``` I don't know if there is another way to do it but this works for me. Also another thing that I want to ask is if the "mixin" is generated every time inside a loop and if there is a better way to do that? You can see the ["String mixins" section here](http://ddili.org/ders/d.en/mixin.html) for more details. Mixins are generated at compile time, so if you're referring to a string mixin inside a runtime loop, the code will not be generated every time the loop runs.
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 18:12:35 UTC, Stanislav Blinov wrote: https://dlang.org/spec/traits.html#identifier Thanks!!! Finally I was able to do it! The code is the following (well not in my final project but it's a demonstration): ``` enum add_char(string c) = `if (stdout_index < STDOUT_BUF_LEN) { stdout_buffer[stdout_index++] =` ~ c ~ `; continue; } else { sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index); stdout_index = 0; stdout_buffer[stdout_index++] =` ~ c ~ `; continue; }`; void main() { mixin(add_char!(__traits(identifier, c))); } ``` I don't know if there is another way to do it but this works for me. Also another thing that I want to ask is if the "mixin" is generated every time inside a loop and if there is a better way to do that?
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 18:06:32 UTC, rempas wrote: On Monday, 20 December 2021 at 11:58:58 UTC, Tejas wrote: Ehh, it still fails; should've explicitly put the length of the array and the `extern (C)` in `main` ```d module demo; [ ... ] extern(C) /+added this because you used -betterC+/ void main() { while (true) { mixin(add_char!'%'); mixin(add_char!'$'); } } ``` Thanks! A mixin is not necessary, it will do the same thing without it. Well it seem that it actually needs it...
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 18:03:09 UTC, rempas wrote: > Now the problem is that I want it to get the name of so > symbol and add it to a string literal. Let's check this example: enum state(alias name) = `name` ~ ` = 10;`; https://dlang.org/spec/traits.html#identifier
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 11:58:58 UTC, Tejas wrote: Ehh, it still fails; should've explicitly put the length of the array and the `extern (C)` in `main` ```d module demo; [ ... ] extern(C) /+added this because you used -betterC+/ void main() { while (true) { mixin(add_char!'%'); mixin(add_char!'$'); } } ``` Thanks! A mixin is not necessary, it will do the same thing without it.
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 11:30:09 UTC, rumbu wrote: Enums (that's why the string is declarated as enum) are evaluated at compile time, the concatenation op will not end in your code as instruction, so you can do anything outside betterC rules as long you do it at compile time. You are just building some code to use later, the compiler does not generate any instruction for it. In the example above you can press the AST button to see exactly how your code is generated. Wnen you have doubts about a generated string you can always test it with ```pragma msg```. In this case, if you write: ``` pragma(msg, add_char!'%'); ``` you will have in the output exactly what the compiler will generate for your mixin. That's cool! And I was wondering how I can make sting literal concatenation at compile time. Now the problem is that I want it to get the name of so symbol and add it to a string literal. Let's check this example: enum state(alias name) = `name` ~ ` = 10;`; I want this to add the token of that will be used as name in the string. For example, I want `state!val;` to get "expanded" as `val = 10;` rather than `10 = 10;`. So I don't want it to take the value of "val" but the word/token "val" itself. I tried using `alias` instead of `char` for the parameter but it didn't worked. Do you know how I can do that?
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 11:30:09 UTC, rumbu wrote: On Monday, 20 December 2021 at 10:49:20 UTC, rempas wrote: On Monday, 20 December 2021 at 09:30:30 UTC, rumbu wrote: Thanks a lot for the info. When I try to use this code, I'm getting the following error: ``` Error: expression expected, not `%` Error: expression expected, not `%` ``` My fault, I forgot to put some char delimiters. You can find tested code here: https://run.dlang.io/is/KfdED0 So I suppose there is a problem with string concatenation. I couldn't use it anyway because it is inefficient and because I'm using betterC. Do you know any other way that I can concatenate strings that does not depend an the Garbage Collector or the standard library? Enums (that's why the string is declarated as enum) are evaluated at compile time, the concatenation op will not end in your code as instruction, so you can do anything outside betterC rules as long you do it at compile time. You are just building some code to use later, the compiler does not generate any instruction for it. In the example above you can press the AST button to see exactly how your code is generated. Wnen you have doubts about a generated string you can always test it with ```pragma msg```. In this case, if you write: ``` pragma(msg, add_char!'%'); ``` you will have in the output exactly what the compiler will generate for your mixin. Ehh, it still fails; should've explicitly put the length of the array and the `extern (C)` in `main` ```d module demo; //i am just declaring these to have them. size_t stdout_index; enum STDOUT_BUF_LEN = 42; char[STDOUT_BUF_LEN] stdout_buffer; /+indexing an uninitialized dynamic array resulted in out of bounds error even for index == 0+/ alias i32 = int; void sys_write(int i, void* p, int index) {} // enum add_char(char c) = `if (stdout_index < STDOUT_BUF_LEN) { stdout_buffer[stdout_index++] ='` ~ c ~ `'; continue; } else { sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index); stdout_index = 0; stdout_buffer[stdout_index++] ='` ~ c ~ `'; continue; }`; extern(C) /+added this because you used -betterC+/ void main() { while (true) { mixin(add_char!'%'); mixin(add_char!'$'); } } ```
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 10:49:20 UTC, rempas wrote: On Monday, 20 December 2021 at 09:30:30 UTC, rumbu wrote: Thanks a lot for the info. When I try to use this code, I'm getting the following error: ``` Error: expression expected, not `%` Error: expression expected, not `%` ``` My fault, I forgot to put some char delimiters. You can find tested code here: https://run.dlang.io/is/KfdED0 So I suppose there is a problem with string concatenation. I couldn't use it anyway because it is inefficient and because I'm using betterC. Do you know any other way that I can concatenate strings that does not depend an the Garbage Collector or the standard library? Enums (that's why the string is declarated as enum) are evaluated at compile time, the concatenation op will not end in your code as instruction, so you can do anything outside betterC rules as long you do it at compile time. You are just building some code to use later, the compiler does not generate any instruction for it. In the example above you can press the AST button to see exactly how your code is generated. Wnen you have doubts about a generated string you can always test it with ```pragma msg```. In this case, if you write: ``` pragma(msg, add_char!'%'); ``` you will have in the output exactly what the compiler will generate for your mixin.
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 09:30:30 UTC, rumbu wrote: because you cannot have statements directly in a template (the fact that is a mixin template is irelevant), only declarations. If you want to just insert some random code, use strings. You can create a templated enum to store your parametrized string. Please note how your parameter (c) becomes part of the resulting string through concatenation (~): ``` enum add_char(char c) = `if (stdout_index < STDOUT_BUF_LEN) { stdout_buffer[stdout_index++] =` ~ c ~ `; continue; } else { sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index); stdout_index = 0; stdout_buffer[stdout_index++] =` ~ c ~ `; continue; }`; ``` and when you want the code inserted: ``` mixin(add_char!'%'); ``` If you want to be sure that your string is syntactically correct, use token strings (https://dlang.org/spec/lex.html#token_strings) Thanks a lot for the info. When I try to use this code, I'm getting the following error: ``` Error: expression expected, not `%` Error: expression expected, not `%` ``` So I suppose there is a problem with string concatenation. I couldn't use it anyway because it is inefficient and because I'm using betterC. Do you know any other way that I can concatenate strings that does not depend an the Garbage Collector or the standard library?
Re: How to insert code in place with templates/mixins?
On Monday, 20 December 2021 at 08:45:50 UTC, rempas wrote: Here I am having a problem with templates again. No matter how much I read, I can't seem to understand how templates/mixins work. So any ideas why this doesn't work? because you cannot have statements directly in a template (the fact that is a mixin template is irelevant), only declarations. If you want to just insert some random code, use strings. You can create a templated enum to store your parametrized string. Please note how your parameter (c) becomes part of the resulting string through concatenation (~): ``` enum add_char(char c) = `if (stdout_index < STDOUT_BUF_LEN) { stdout_buffer[stdout_index++] =` ~ c ~ `; continue; } else { sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index); stdout_index = 0; stdout_buffer[stdout_index++] =` ~ c ~ `; continue; }`; ``` and when you want the code inserted: ``` mixin(add_char!'%'); ``` If you want to be sure that your string is syntactically correct, use token strings (https://dlang.org/spec/lex.html#token_strings)
How to insert code in place with templates/mixins?
Here I am having a problem with templates again. No matter how much I read, I can't seem to understand how templates/mixins work. So I'm having the following code (just a snippet of the real code): ``` if (c != '%') { if (stdout_index < STDOUT_BUF_LEN) { stdout_buffer[stdout_index++] = c; continue; } else { sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index); stdout_index = 0; stdout_buffer[stdout_index++] = c; continue; } } ``` And I want to create a macro (using the C terms) to make the code inside the first if statement (`if (c != '%')`) into a template that will be able to used and added in place (not as a function as I don't want to function call). I tried to make it both a template and a mixin template and It will not compile, rather it will give my the following error: ``` Error: declaration expected, not `if` Error: declaration expected, not `continue` Error: declaration expected, not `else` Error: basic type expected, not `0` Error: found `0` when expecting `;` Error: no identifier for declarator `stdout_buffer[stdout_index++]` Error: declaration expected, not `=` Error: declaration expected, not `continue` Error: unrecognized declaration ``` It should be clear what I tried to still I will post what I tried in case someone is curious to see: ``` mixin template add_char() { if (stdout_index < STDOUT_BUF_LEN) { stdout_buffer[stdout_index++] = c; continue; } else { sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index); stdout_index = 0; stdout_buffer[stdout_index++] = c; continue; } } ``` So any ideas why this doesn't work?
Re: Can anyone provide an example of how D templates are overridable by global symbols?
On Thursday, 9 December 2021 at 20:53:52 UTC, Siarhei Siamashka wrote: 2. How would one construct a simple example of a template symbol getting successfully overridden by a global symbol? Here's my unsuccessful attempt: ```D module template_f; T f(T)(T a, T b) { return a + b; } ``` ```D module nontemplate_f; int f(int a, int b) { return a - b; } ``` ```D import std.stdio; import template_f; import nontemplate_f; void main() { f(2, 1).writeln; } ``` ```text $ gdc-10.3.0 test.d test.d:8:4: error: nontemplate_f.f at nontemplate_f.d:3:5 conflicts with template_f.f!int.f at template_f.d:3:3 8 | f(2, 1).writeln; |^ ``` This is prohibited at the compilation stage and doesn't even reach the linker. I guess, something a bit more elaborate needs to be done to simulate a global symbol from a rogue object file overriding a template from phobos in the resulting compiled binary. The question is how to achieve this.
Can anyone provide an example of how D templates are overridable by global symbols?
A quote of Iain Buclaw from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102765 about GDC behaviour: D semantics for template symbols is that they must be overridable - even by normal global symbols. So in version 11.1, the default linkage for templates was switched over to weak, and with that, you can't safely inline them without violating ODR. My (most likely wrong) interpretation of this is that the D language standard somehow makes it impossible to make template inlining decisions at the compilation stage and this job has to be delegated to the linker. And as a result, the use of LTO becomes required for generating fast binaries. Another implication is that fast incremental rebuilds of optimized binaries are likely highly problematic. So I have two questions: 1. What is the exact wording of the D language standard on this matter? 2. How would one construct a simple example of a template symbol getting successfully overridden by a global symbol? Thanks!
Re: C++ bindings: const(T) dropped in return types of templates ?
On Thursday, 9 December 2021 at 07:58:46 UTC, frame wrote: On Thursday, 9 December 2021 at 07:41:32 UTC, frame wrote: On Monday, 6 December 2021 at 20:31:47 UTC, Jan wrote: So am I missing something, or did the compiler somehow forget about the const-ness? Sounds like a bug to me, eg this one: https://issues.dlang.org/show_bug.cgi?id=20685 But this is no show stopper, you can always force the mangling with the pragma directive. https://dlang.org/spec/pragma.html#mangle Oh it's a known bug for over a year already :( It is a bit of a show stopper for me, since the mangled name that I have isn't always correct (CastXML uses Clang and that seems to pick different calling conventions sometimes, than what MSVC would do, so the mangled names that I get are not guaranteed to be correct). Well, I'll work around it for now, thanks for the answer.
Re: C++ bindings: const(T) dropped in return types of templates ?
On Thursday, 9 December 2021 at 07:41:32 UTC, frame wrote: On Monday, 6 December 2021 at 20:31:47 UTC, Jan wrote: So am I missing something, or did the compiler somehow forget about the const-ness? Sounds like a bug to me, eg this one: https://issues.dlang.org/show_bug.cgi?id=20685 But this is no show stopper, you can always force the mangling with the pragma directive. https://dlang.org/spec/pragma.html#mangle
Re: C++ bindings: const(T) dropped in return types of templates ?
On Monday, 6 December 2021 at 20:31:47 UTC, Jan wrote: So am I missing something, or did the compiler somehow forget about the const-ness? Sounds like a bug to me, eg this one: https://issues.dlang.org/show_bug.cgi?id=20685
C++ bindings: const(T) dropped in return types of templates ?
I am trying to auto-generate bindings for C++ code in D. I've come across something that looks like a bug in DMD to me, but since I'm such a newbie in D maybe I am missing something. My C++ class looks like this: ```cpp template struct Vec3Template { static const Vec3Template ZeroVector(); }; ``` And my D binding code looks like this: ```cpp extern(C++) struct Vec3Template(TYPE) { static const(Vec3Template!(TYPE)) ZeroVector(); } alias Vec3 = Vec3Template!(float); ``` However, when I try to use Vec3.ZeroVector() I am getting a linker error about unresolved symbols. It works with other functions, the error is specific to this function. Now it complains that it can't find this one: `?ZeroVector@?$Vec3Template@M@@SA?AU1@XZ` However, I am using castXml to extract my C++ information, and that says that the mangled name should be: `?ZeroVector@?$Vec3Template@M@@SA?BU1@XZ` Running both names through undname.exe, an MSVC tool that generates the undecorated function name from the mangled name, it says that the latter function definition should be: `public: static struct Vec3Template const __cdecl Vec3Template::ZeroVector(void)` Whereas the former definition would be: `public: static struct Vec3Template __cdecl Vec3Template::ZeroVector(void)` So the one that D tries to link against is missing the `const`. However, unless I misunderstood how to apply const to a type in D, you can see that I did wrap the type in const(). (I also tried immutable, but that's not allowed for extern C++ code). So am I missing something, or did the compiler somehow forget about the const-ness? I'm currently using DMD64 D Compiler v2.098.0-dirty
Re: Regular Templates May Be `mixin`d?
On Sunday, 3 October 2021 at 03:34:19 UTC, surlymoor wrote: Lord, I'm careless. Thanks. So the difference between a `mixin template` and a regular one is that the former may only be used with a `mixin` statement? Yes, exactly.
Re: Regular Templates May Be `mixin`d?
On Sunday, 3 October 2021 at 03:04:29 UTC, Paul Backus wrote: On Sunday, 3 October 2021 at 02:52:20 UTC, surlymoor wrote: This compiles and works. I checked the spec, and I don't see anything; probably missed it, however; mentioning the fact that regular templates may be used with `mixin`. Is this expected? Yes, this is intentional and expected. From the spec: A TemplateMixin takes an arbitrary set of declarations from the body of a TemplateDeclaration and inserts them into the current context. Source: https://dlang.org/spec/template-mixin.html Notice that it is specified to work with any template declaration, not just one declared as a `mixin template`. Lord, I'm careless. Thanks. So the difference between a `mixin template` and a regular one is that the former may only be used with a `mixin` statement?
Re: Regular Templates May Be `mixin`d?
On Sunday, 3 October 2021 at 02:52:20 UTC, surlymoor wrote: This compiles and works. I checked the spec, and I don't see anything; probably missed it, however; mentioning the fact that regular templates may be used with `mixin`. Is this expected? Yes, this is intentional and expected. From the spec: A TemplateMixin takes an arbitrary set of declarations from the body of a TemplateDeclaration and inserts them into the current context. Source: https://dlang.org/spec/template-mixin.html Notice that it is specified to work with any template declaration, not just one declared as a `mixin template`.
Regular Templates May Be `mixin`d?
```d // Modified sixth example from https://dlang.org/spec/template-mixin.html int y = 3; template Foo() { int abc() { return y; } } void main() { int y = 8; mixin Foo; // local y is picked up, not global y assert(abc() == 8); } ``` This compiles and works. I checked the spec, and I don't see anything; probably missed it, however; mentioning the fact that regular templates may be used with `mixin`. Is this expected?
Re: Templates for instantiating derived class
On 9/20/21 6:16 PM, rjkilpatrick wrote: Essentially, I would like to write a template that calls the constructor of the parent class or the constructor of the inherited class, depending on its type. ... Some kind of `return new this(...)` would be good, but that's not possible. I think it has to be done with templates, but I'm not sure how to do this. Any help would be greatly appreciated. What you want is to change that operator into a virtual function. Yes, you still have to write the overrides, but you could if you want use a mixin. Adam's solution works, but only uses the static type. ```d class Super { private int _a; this(){} this(int a) { _a = a; } Super performAdd(int rhs) const { return new Super(_a + rhs); } alias opBinary(string op : "+") = performAdd; } class Derived : Super { this(){} this(int a) { _a = a + 1; } override Derived performAdd(int rhs) { return new Derived(_a + rhs); } } void main() { import std : writeln; Super foo = new Super(1); Super foo2 = foo + 1; // Works fine as calls `Super` constructor Derived bar = new Derived(2); Derived bar2 = bar + 1; // works now Super b2 = bar; Derived d2 = cast(Derived)(b2 + 1); // ok, *and* calls Derive's version of performAdd assert(d2 !is null && d2._a == bar2._a); } ```
Re: Templates for instantiating derived class
On Monday, 20 September 2021 at 22:16:47 UTC, rjkilpatrick wrote: auto opBinary(string op)(int rhs) const if (op == "+") { return new Super(_a + rhs); // Creates of type Super even when called from derived class } Make this auto opBinary(string op, this This)(int rhs) . return new This(_a + rhs); } The template this param is the static type it is called on. https://dlang.org/spec/template.html#template_this_parameter Note though that this is the static type. If you do Super thing = new Derived(); thing + 5; it will still return Super since that's the type it was called through. If you want it to actually return derived, you'll have to add a virtual factory function: class Super { protected Super factory() { return new Super(); } } class Derived : Super { override Derived factory() { return new Derived(); } } Then you can call obj.factory to get the right dynamic type. (forward args as needed etc.) Some kind of `return new this(...)` would be good, but that's not possible. You can do `return new typeof(this)(...);` fyi but it is again the static type of this, which will be whatever it is where it is defined. This is a useful trick if you were to make that factory function a mixin template or something though.
Templates for instantiating derived class
Essentially, I would like to write a template that calls the constructor of the parent class or the constructor of the inherited class, depending on its type. ```d #!/usr/bin/env dub /+ dub.sdl: name "mwe" +/ class Super { private int _a; this(){} this(int a) { _a = a; } auto opBinary(string op)(int rhs) const if (op == "+") { return new Super(_a + rhs); // Creates of type Super even when called from derived class } } class Derived : Super { this(){} this(int a) { _a = a + 1; } } void main() { import std : writeln; Super foo = new Super(1); Super foo2 = foo + 1; // Works fine as calls `Super` constructor Derived bar = new Derived(2); Derived bar2 = bar + 1; // Cannot implicitly cast `Super` to `Derived` } ``` Some kind of `return new this(...)` would be good, but that's not possible. I think it has to be done with templates, but I'm not sure how to do this. Any help would be greatly appreciated.
Re: vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?
On 8/31/21 8:40 PM, someone wrote: On Tuesday, 31 August 2021 at 14:06:32 UTC, Steven Schveighoffer wrote: The generation of code to output the page depends on the diet file format (i.e. code islands are designated by the leading `-`). However, vibe-d does not require using the diet template system. Does that means I can still get the code islands resolved on a, say, plain-XHTML file ? Or does that means that I should output HTML/XHTML from my own functions instead ? Vibe just provides an output range for use in diet. You can use anything, including just writing the data yourself, or using an alternative template system. Given how templating systems work (and how D allows strings to be used as code using mixins), it's likely pretty trivial to write a simple templating system to do this. All you need is an escape protocol that is unlikely to appear in HTML, and you can probably get away with a 10 line function that doesn't need to actually parse the HTML. Probably. Bit I am not a huge fan of modifying libraries for minor functionality fixes (unless is really really necessary). For whatever reasons I already have custom nginx builds etc etc so I do not want to keep tracking and fixing more software -in the end is a pain-in-the-ass. You aren't modifying anything. Vibe-d provides default access to diet-ng, but you have no obligation to use it. Just use the output range (`HTTPServerResponse.bodyWriter`) and hook up your preferred templating system. I think you are misunderstanding the architecture of vibe. There is no need to replace anything inside vibe to use a different templating system, it does not depend on diet at all, just provides default access. The views directory isn't exactly special either (though there may be code in dub that deals with looking at modification times), nor is the extension `.dt`. Most of the diet compiler is dealing with transforming the pug format into HTML, and proper string interpolation. The code island stuff is quite trivial (just copied as-is). Oh, and I realized I forgot about string interpolation. You definitely want a way to change D expressions into string output. You can still do this with code-islands, but a good template system would handle the boilerplate for you. Which leads me to -- diet really should be split into 2 parts, one that handles the pug parsing and compiling, and one that handles proper string interpolation. Then you could leverage that second part. -Steve
Re: vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?
On Tuesday, 31 August 2021 at 07:40:10 UTC, bauss wrote: You might be interested in https://yuraiweb.org/ Even though it's a work in progress then you should be able to get by just fine with the basics for now. Thanks for the tip bauss :) ! I am exploring it right now. Main problem is the lack of documentation: https://yuraiweb.org/docs/specifications/basics ... every section is empty. My two cents-so-far: https://yuraiweb.org/ Functionality DietYurai ... Total Score*9(11)/2020/20 * A higher score is better. Methinks things like this are downs, its like insulting the intelligence of their potential customers. They are advertising software not kitchen appliances for gramma. At least they are reminding me that higher scores are better ... thanks for the tip you yurai developers !
Re: vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?
On Tuesday, 31 August 2021 at 14:06:32 UTC, Steven Schveighoffer wrote: The generation of code to output the page depends on the diet file format (i.e. code islands are designated by the leading `-`). However, vibe-d does not require using the diet template system. Does that means I can still get the code islands resolved on a, say, plain-XHTML file ? Or does that means that I should output HTML/XHTML from my own functions instead ? There are others which probably do what you want (search on code.dlang.org), but I'm a huge fan of diet templates (I actually prefer writing non-template html that way), so I don't have any experience with others. https://yuraiweb.org/ as pointed by another user seems something I probably want to give it a try -it still relies on vibe.d but switched to plain HTML with its own code-islands more-or-less a-la ASP.net ... although it is still a work-in-progress. Given how templating systems work (and how D allows strings to be used as code using mixins), it's likely pretty trivial to write a simple templating system to do this. All you need is an escape protocol that is unlikely to appear in HTML, and you can probably get away with a 10 line function that doesn't need to actually parse the HTML. Probably. Bit I am not a huge fan of modifying libraries for minor functionality fixes (unless is really really necessary). For whatever reasons I already have custom nginx builds etc etc so I do not want to keep tracking and fixing more software -in the end is a pain-in-the-ass. However, I think vibe.d perhaps ought to provide a switch/flag to enable/disable DIET constructs on source files (views) resolving its code islands. Or more straightforward, if the requested file already has another extension other than the one used by DIET files just resolve the code-islands and be with it. No client-side code changes -business as usual. Or use another directory other than /views/ for bare files without DIET syntax. Just thinking ... what do you think ? -Steve
Re: vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?
On 8/30/21 8:09 PM, someone wrote: Regarding vibe.d I think I'll give it a try (maybe placing it behind nginx at first) since I do really got a good first-impression ... kudos to the developers/maintainers :) I like the idea of having D at my disposal within a web page, actually, it is a terrific feature to say the least. What I do not like (even a bit) are the pseudo-HTML DIET templates. I can understand they can make life easy for some, but I am not the guy having any trouble writing well-good-structured HTML/XHTML/XML/etc to begin with, nor I am the kind of guy grunting because I will be forced to write closing tags and the like. That being said, my specific question is: Can I use vibe.d *without* DIET templates manually writing say, XHTML 1.1 pages, *while having D* at my disposal with the - prefixes I have seen so far ? The generation of code to output the page depends on the diet file format (i.e. code islands are designated by the leading `-`). However, vibe-d does not require using the diet template system. There are others which probably do what you want (search on code.dlang.org), but I'm a huge fan of diet templates (I actually prefer writing non-template html that way), so I don't have any experience with others. Given how templating systems work (and how D allows strings to be used as code using mixins), it's likely pretty trivial to write a simple templating system to do this. All you need is an escape protocol that is unlikely to appear in HTML, and you can probably get away with a 10 line function that doesn't need to actually parse the HTML. -Steve
Re: vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?
On Tuesday, 31 August 2021 at 00:09:14 UTC, someone wrote: Regarding vibe.d I think I'll give it a try (maybe placing it behind nginx at first) since I do really got a good first-impression ... kudos to the developers/maintainers :) I like the idea of having D at my disposal within a web page, actually, it is a terrific feature to say the least. What I do not like (even a bit) are the pseudo-HTML DIET templates. I can understand they can make life easy for some, but I am not the guy having any trouble writing well-good-structured HTML/XHTML/XML/etc to begin with, nor I am the kind of guy grunting because I will be forced to write closing tags and the like. That being said, my specific question is: Can I use vibe.d *without* DIET templates manually writing say, XHTML 1.1 pages, *while having D* at my disposal with the - prefixes I have seen so far ? I mean, I am almost sure I can write D functions returning text and making my web page on-the-fly, but this is not what I have in mind, I would like to have an actual text file for a web page with the aforementioned - prefixes to actually hook D code leveraging the pre-compiled feature of DIET templates. You might be interested in https://yuraiweb.org/ Even though it's a work in progress then you should be able to get by just fine with the basics for now.
Re: vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?
On Tuesday, 31 August 2021 at 00:09:14 UTC, someone wrote: Can I use vibe.d *without* DIET templates manually writing say, XHTML 1.1 pages, *while having D* at my disposal with the - prefixes I have seen so far ? I don't know much about vibe.d (I have my own D web stuff) but just for fun I wanted to try passing my dom.d through the ctfe engine to do the embedded code thing. 50ish lines for the basic extractor i slapped together in 20 mins. --- import arsd.dom; string toD(string s) { return `append(` ~ "`" ~ s ~ "`" ~ `);`; } template loadTemplateMixin(string doc) { string helper() { Document document = new Document; document.parseSawAspCode = (string) => true; document.parseStrict(doc); string code; void expand(Element element) { if(auto asp = cast(AspCode) element) { if(asp.source.length > 3 && asp.source[1] == '=') code ~= `append(` ~ asp.source[2 .. $-1] ~ `);`; else code ~= asp.source[1 .. $-1]; } else if(auto tn = cast(TextNode) element) { code ~= toD(tn.toString()); } else if(auto sn = cast(SpecialElement) element) { code ~= toD(sn.toString()); } else { code ~= toD("<" ~ element.tagName); foreach(k, v; element.attributes) { code ~= toD(" "); code ~= toD(k.htmlEntitiesEncode); code ~= toD("=\""); code ~= toD(v.htmlEntitiesEncode); code ~= toD("\""); } code ~= toD(">"); foreach(child; element.children) expand(child); code ~= toD(""); } } expand(document.root); return code; } enum loadTemplateMixin = helper(); } // USAGE HERE // this could be in a file import("file.html") too btw enum doc = ` foocssid="main"><%= my_string[0 .. 5] %> foo foo foo <% foreach(item; strings) append(item); %> `; void main() { string html; // and it can see these variables in the <% %> blocks string my_string = "hello world"; string[] strings = ["omg", "wtf", "lol"]; void append(string s) { html ~= s; } mixin(loadTemplateMixin!doc); import std.stdio; writeln(html); } --- Not exactly the fastest compile though but I could prolly optimize that if i spent a lil more time on it. Now that it yields a string though you can return that to vibe using whatever method it uses. Also note that you get a compile error on malformed input xhtml too.
vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?
Regarding vibe.d I think I'll give it a try (maybe placing it behind nginx at first) since I do really got a good first-impression ... kudos to the developers/maintainers :) I like the idea of having D at my disposal within a web page, actually, it is a terrific feature to say the least. What I do not like (even a bit) are the pseudo-HTML DIET templates. I can understand they can make life easy for some, but I am not the guy having any trouble writing well-good-structured HTML/XHTML/XML/etc to begin with, nor I am the kind of guy grunting because I will be forced to write closing tags and the like. That being said, my specific question is: Can I use vibe.d *without* DIET templates manually writing say, XHTML 1.1 pages, *while having D* at my disposal with the - prefixes I have seen so far ? I mean, I am almost sure I can write D functions returning text and making my web page on-the-fly, but this is not what I have in mind, I would like to have an actual text file for a web page with the aforementioned - prefixes to actually hook D code leveraging the pre-compiled feature of DIET templates.
Re: equivalent of std.functional.partial for templates?
On Wednesday, 11 August 2021 at 14:08:59 UTC, Paul Backus wrote: [snip] Should have read further--this does not work with template functions due to [issue 1807.][1] My mistake. [1]: https://issues.dlang.org/show_bug.cgi?id=1807 Looks like that strengthens the case for moving forward with DIP1023 (or something more general).
Re: equivalent of std.functional.partial for templates?
On Wednesday, 11 August 2021 at 14:08:59 UTC, Paul Backus wrote: On Wednesday, 11 August 2021 at 14:03:50 UTC, Paul Backus wrote: On Wednesday, 11 August 2021 at 14:00:33 UTC, Steven Schveighoffer wrote: I have a template function like this: ```d auto foo(T, Args...)(Args args) {...} ``` If I try to bind the T only, and produce a partial template function which can accept any number of parameters, but has T already specified, I get an error, because instantiating `foo!T` means Args is length 0. https://phobos.dpldocs.info/std.meta.ApplyLeft.html Should have read further--this does not work with template functions due to [issue 1807.][1] My mistake. [1]: https://issues.dlang.org/show_bug.cgi?id=1807 So first, I though ApplyLeft would work, but I convinced myself it was focused on applying the template to arguments individually, but that's just the example used. ApplyLeft is exactly what I'm looking for, but as you said (and as my example shows), it doesn't work in this case. It would be nice to have something that would work (or make ApplyLeft work via a compiler change). Thanks for the nudge! -Steve
Re: equivalent of std.functional.partial for templates?
On Wednesday, 11 August 2021 at 14:03:50 UTC, Paul Backus wrote: On Wednesday, 11 August 2021 at 14:00:33 UTC, Steven Schveighoffer wrote: I have a template function like this: ```d auto foo(T, Args...)(Args args) {...} ``` If I try to bind the T only, and produce a partial template function which can accept any number of parameters, but has T already specified, I get an error, because instantiating `foo!T` means Args is length 0. https://phobos.dpldocs.info/std.meta.ApplyLeft.html Should have read further--this does not work with template functions due to [issue 1807.][1] My mistake. [1]: https://issues.dlang.org/show_bug.cgi?id=1807
Re: equivalent of std.functional.partial for templates?
On Wednesday, 11 August 2021 at 14:00:33 UTC, Steven Schveighoffer wrote: I have a template function like this: ```d auto foo(T, Args...)(Args args) {...} ``` If I try to bind the T only, and produce a partial template function which can accept any number of parameters, but has T already specified, I get an error, because instantiating `foo!T` means Args is length 0. https://phobos.dpldocs.info/std.meta.ApplyLeft.html
equivalent of std.functional.partial for templates?
I have a template function like this: ```d auto foo(T, Args...)(Args args) {...} ``` If I try to bind the T only, and produce a partial template function which can accept any number of parameters, but has T already specified, I get an error, because instantiating `foo!T` means Args is length 0. I was surprised not to see something in std.meta that could create this for me. In `std.functional` there is `partial` (which bizarrely only allows one parameter to be specified), but I don't see an equivalent for template parameters. For functions, it seems IFTI can't see through to infer the template parameters of the alias, but you can have a function wrapper: ```d template bindFirst(alias F, Args...) { // this doesn't work // alias bindFirst(Args2...) = F!(Args, Args2); // but this does auto bindFirst(Args2...)(Args2 args2) { return F!(Args)(args2); } } alias bf = bindFirst!(foo, int); bf("hello", 5); // ok ``` It would be nice if the alias worked, but I don't know what's involved to make IFTI work there. I know I can alter foo to be a template within a template. Perhaps that's the right answer. However, this doesn't help for functions already written that I can't alter. Any ideas on how to solve this? I know my function solution is not very flexible... -Steve
Re: nested templates using Complex! with slices, ... confused, I am!
On Monday, 9 August 2021 at 18:44:34 UTC, Paul Backus wrote: On Monday, 9 August 2021 at 18:35:56 UTC, james.p.leblanc wrote: ```d T[] foo_temp(Complex!T[])(T x, T y){ auto r = [x, x]; auto i = [y, y]; auto z = [ Complex!T(x, y), Complex!T(x,y) ]; return z; } ``` void main(){ auto yd = foo_double(1.1, 2.2); writeln(yd); ... } But, no ... I am WRONG! I get the message: qqq.d(18): Error: identifier expected for template value parameter I think what you want is: ```d Complex!T[] foo_temp(T)(T x, T y) { auto r = [x, x]; auto i = [y, y]; auto z = [ Complex!T(x, y), Complex!T(x,y) ]; return z; } ``` This is what I get when I take one of the non-template versions and replace `float` or `double` with `T`. H.S & Paul, Wow, thanks for the quick replies! It all seems so simple now ... but I just could not see it! I had been completely (and confidently, unfortunately) misunderstanding the syntax of that left most column. Thanks again, James