Re: Output Range Problem? How to make it work?
On Monday, 11 October 2021 at 00:19:44 UTC, apz28 wrote: /* Getting this error onlineapp.d(34): Error: none of the overloads of `toString` are callable using argument types `(Buffer)`, candidates are: onlineapp.d(19):`onlineapp.Foo.toString()` onlineapp.d(26):`onlineapp.Foo.toString(const(char)[] fmt)` onlineapp.d(22):`toString(Writer, Char)(return ref Writer sink)` */ The signature of your `toString` method should match one of the examples in [the documentation][1]: ```d void toString(Writer, Char)(ref Writer w, const ref FormatSpec!Char fmt) void toString(Writer)(ref Writer w) string toString(); ``` Here is an example that works: ```d import std.range: put; import std.array: appender; import std.format: formattedWrite; struct Foo { void toString(Writer)(ref Writer writer) { put(writer, "Foo"); } } void main() { auto buffer = appender!string; Foo foo; formattedWrite(buffer, "%s", foo); assert(buffer[] == "Foo"); } ``` Link: https://run.dlang.io/is/dZLRuo [1]: https://phobos.dpldocs.info/std.format.write.html
Output Range Problem? How to make it work?
import std.range.primitives: isOutputRange; @safe: struct Buffer { @safe: void put(char c) {} void put(scope const(char)[] s) {} } struct Foo { @safe: string toString() {return null;} ref Writer toString(Writer, Char)(return ref Writer sink) if (isOutputRange!(Writer, Char) && isSomeChar!Char) {return sink;} string toString(const(char)[] fmt) {return null;} } void main() { Buffer buffer; Foo foo; foo.toString(buffer); } /* Getting this error onlineapp.d(34): Error: none of the overloads of `toString` are callable using argument types `(Buffer)`, candidates are: onlineapp.d(19):`onlineapp.Foo.toString()` onlineapp.d(26):`onlineapp.Foo.toString(const(char)[] fmt)` onlineapp.d(22):`toString(Writer, Char)(return ref Writer sink)` */
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 14:00:37 UTC, Elmar wrote: On Sunday, 10 October 2021 at 13:56:06 UTC, rempas wrote: Actually I know about BetterC and how to call C functions from D and visa versa. I would also disagree that "BetterC" is almost no improvement over C as about 90% of the language is there!! C++ classes are also supported Nice :-) , you're right. I need to be more optimistic here. Happy coding. Thanks a lot! Happy coding to you too!
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote: The language subset "BetterC" is required for calling D functions from C though. This is false. You can use any D features when calling it from C, you just need to provide an init and term function that is called from C that runtime initialize and terminate for the full experience. BetterC helper librarys like Tanya or Tango do exist. I don't know tanya, but Tango has absolutely nothing to do with betterC. It is a set of classes that use the full runtime.
Re: What is the proper way to outline static-if-conditions ?
On Sunday, 10 October 2021 at 15:15:51 UTC, drug wrote: It would be nice if one could use pattern-matching for it in D. Is this possible? As I know it's impossible, but you can use a regular template: ... If anyone is interested in pattern matching, someone provides a package "dpmatch" which uses PEG (some parsing grammer which is implemented in D) to achieve Haskel-style pattern matching, yet for sum-type definitions only. And they use GC + interfaces. Hence it cannot be used with BetterC. Sumtypes can also be created with the `sumtype` package which uses D's delegate literals for pattern matching.
Re: What is the proper way to outline static-if-conditions ?
On Sunday, 10 October 2021 at 15:15:51 UTC, drug wrote: As I know it's impossible, but you can use a regular template: ```d template isPointedStaticArray(T) { static if (isPointer!T) enum isPointedStaticArray = isStaticArray!(PointerTarget!T); else enum isPointedStaticArray = false; } ``` https://run.dlang.io/is/lR7feP this compiles from 2.086.1 and above That's indeed close to pattern matching and is probably the best answer :-) .
Re: What is the proper way to outline static-if-conditions ?
On 10.10.2021 18:01, Elmar wrote: Well, I just wondered why your code would compile and mine wouldn't. The `version(all)` variant will not compile on my computer with `rdmd` because `PointerTarget` only allows pointers. It depends on compiler version. This variant is compiled on version 2.092.1 and above But the 2nd one will compile. The `is()` expression catches the compilation error which is nice. This is sufficient: ```d enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, size_t N); ``` It would be nice if one could use pattern-matching for it in D. Is this possible? ```d enum isPointedStaticArray(X : P*, P) = .isStaticArray!(PointerTarget!X); enum isPointedStaticArray(X : else) = false; ``` As I know it's impossible, but you can use a regular template: ```d template isPointedStaticArray(T) { static if (isPointer!T) enum isPointedStaticArray = isStaticArray!(PointerTarget!T); else enum isPointedStaticArray = false; } ``` https://run.dlang.io/is/lR7feP this compiles from 2.086.1 and above
Re: What is the proper way to outline static-if-conditions ?
On Sunday, 10 October 2021 at 15:01:17 UTC, Elmar wrote: ```d enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, size_t N); ``` ```d enum isPointedStaticArray(X : P*, P) = .isStaticArray!(PointerTarget!X); ``` `isStaticArray` is a good example that makes me ask how to outline an `is()` expression without losing the error catching semantics of the inlined `is()` expression.
Re: What is the proper way to outline static-if-conditions ?
On Sunday, 10 October 2021 at 14:36:50 UTC, Elmar wrote: On Sunday, 10 October 2021 at 14:08:13 UTC, drug wrote: You just need to check if T is a pointer: ```D import std; alias DA = int[]; alias SA = int[3]; alias PSA = SA*; alias PDA = DA*; version(all) enum isPointedStaticArray(T) = isPointer!T && isStaticArray!(PointerTarget!T); else enum isPointedStaticArray(T) = isPointer!T && is(PointerTarget!T : P[N], P, size_t N); // this way you can get array length static assert(!isPointedStaticArray!DA); static assert(!isPointedStaticArray!SA); static assert(!isPointedStaticArray!PDA); static assert( isPointedStaticArray!PSA); void main() { } ``` https://run.dlang.io/is/qKdx1D Also you can use another way to detect static array - it can be useful if you need to get its length Wow, this is a fine solution. I gonna use it, thank you :-) . Well, I just wondered why your code would compile and mine wouldn't. The `version(all)` variant will not compile on my computer with `rdmd` because `PointerTarget` only allows pointers. But the 2nd one will compile. The `is()` expression catches the compilation error which is nice. This is sufficient: ```d enum isPointedStaticArray(T) = is(PointerTarget!T : P[N], P, size_t N); ``` It would be nice if one could use pattern-matching for it in D. Is this possible? ```d enum isPointedStaticArray(X : P*, P) = .isStaticArray!(PointerTarget!X); enum isPointedStaticArray(X : else) = false; ```
Re: Traits in a template enum
On Sunday, 10 October 2021 at 12:56:30 UTC, Some Guy wrote: But I did not understand what you meant by "enums hold values, not types". Aren't types values at compile time? Types can be template arguments, if that's what you mean, but they aren't values.
Re: What is the proper way to outline static-if-conditions ?
On Sunday, 10 October 2021 at 14:08:13 UTC, drug wrote: You just need to check if T is a pointer: ```D import std; alias DA = int[]; alias SA = int[3]; alias PSA = SA*; alias PDA = DA*; version(all) enum isPointedStaticArray(T) = isPointer!T && isStaticArray!(PointerTarget!T); else enum isPointedStaticArray(T) = isPointer!T && is(PointerTarget!T : P[N], P, size_t N); // this way you can get array length static assert(!isPointedStaticArray!DA); static assert(!isPointedStaticArray!SA); static assert(!isPointedStaticArray!PDA); static assert( isPointedStaticArray!PSA); void main() { } ``` https://run.dlang.io/is/qKdx1D Also you can use another way to detect static array - it can be useful if you need to get its length Wow, this is a fine solution. I gonna use it, thank you :-) .
Re: What is the proper way to outline static-if-conditions ?
You just need to check if T is a pointer: ```D import std; alias DA = int[]; alias SA = int[3]; alias PSA = SA*; alias PDA = DA*; version(all) enum isPointedStaticArray(T) = isPointer!T && isStaticArray!(PointerTarget!T); else enum isPointedStaticArray(T) = isPointer!T && is(PointerTarget!T : P[N], P, size_t N); // this way you can get array length static assert(!isPointedStaticArray!DA); static assert(!isPointedStaticArray!SA); static assert(!isPointedStaticArray!PDA); static assert( isPointedStaticArray!PSA); void main() { } ``` https://run.dlang.io/is/qKdx1D Also you can use another way to detect static array - it can be useful if you need to get its length
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:56:06 UTC, rempas wrote: Actually I know about BetterC and how to call C functions from D and visa versa. I would also disagree that "BetterC" is almost no improvement over C as about 90% of the language is there!! C++ classes are also supported Nice :-) , you're right. I need to be more optimistic here. Happy coding.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote: The language subset "BetterC" is required for calling D functions from C though. Unfortunately, the runtime features of BetterC are limited and some of C's language features aren't availabe like C99 variable-length-arrays. "BetterC" is like programming in C with little more comfort but phobos is unusable which makes BetterC almost no improvement over C. BetterC helper librarys like Tanya or Tango do exist. Oh well, I could also be wrong with BetterC support of Tanya and Tango but both are alterantives to Phobos.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:52:57 UTC, Elmar wrote: Hopefully it will :-) . D has some good C support. You can call any C function from `D` by declaring it `extern(C) `. The language subset "BetterC" is required for calling D functions from C though. Unfortunately, the runtime features of BetterC are limited and some of C's language features aren't availabe like C99 variable-length-arrays. "BetterC" is like programming in C with little more comfort but phobos is unusable which makes BetterC almost no improvement over C. BetterC helper librarys like Tanya or Tango do exist. In that case it can indeed be better for you to convert the program's entry point into D code. This is unfortunate because it prevents C code bases from using D. There is a tool [C++ Conversion Wizard](https://rainers.github.io/visuald/visuald/CppConversion.html) which could be able to convert C++ and C to D but I don't know how good it is and whether it's usable for free on a GNU/Linux derivative OS. It's only half-automatic. Actually I know about BetterC and how to call C functions from D and visa versa. I would also disagree that "BetterC" is almost no improvement over C as about 90% of the language is there!! C++ classes are also supported
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 13:10:27 UTC, rempas wrote: Thanks, I'm converting a library from C to D so I have to fix all the other bugs first to see If it's working but probably it will. Have an amazing day my friend! Hopefully it will :-) . D has some good C support. You can call any C function from `D` by declaring it `extern(C) `. The language subset "BetterC" is required for calling D functions from C though. Unfortunately, the runtime features of BetterC are limited and some of C's language features aren't availabe like C99 variable-length-arrays. "BetterC" is like programming in C with little more comfort but phobos is unusable which makes BetterC almost no improvement over C. BetterC helper librarys like Tanya or Tango do exist. In that case it can indeed be better for you to convert the program's entry point into D code. This is unfortunate because it prevents C code bases from using D. There is a tool [C++ Conversion Wizard](https://rainers.github.io/visuald/visuald/CppConversion.html) which could be able to convert C++ and C to D but I don't know how good it is and whether it's usable for free on a GNU/Linux derivative OS. It's only half-automatic.
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 11:26:18 UTC, Elmar wrote: Hello rempas. This is the way: ```d import core.stdc.stdlib : malloc, free; extern(C) void* function(ulong) mallocPointer = &malloc; extern(C) void function(void*) freePointer = &free; ``` `function` in the type is already a function pointer. Not immediately obvious though: You also must annotate the type with `extern(C)` otherwise it will not work. Thanks, I'm converting a library from C to D so I have to fix all the other bugs first to see If it's working but probably it will. Have an amazing day my friend!
Re: What is a "comma expression"?
On Sunday, 10 October 2021 at 12:19:39 UTC, Adam D Ruppe wrote: On Sunday, 10 October 2021 at 12:01:33 UTC, rempas wrote: [...] The comma expression in C is a combination of two things but in the context of another thing. Well that's not very good, but like there's statements and expressions. Statements do something but do not have a value. So `if() {}` and `return` and `for() {}` are statements, because they don't have a value you can assign to a variable. [...] Thanks a lot for the detailed explanation! Have a nice day!
Re: What is a "comma expression"?
On Sunday, 10 October 2021 at 12:13:47 UTC, Elmar wrote: Hello rempas. The comma-operator `,` is like `;` but results in an expression value, not a statement like `;` would. The left side of `,` is executed like a statement and the value of the right side of `,` is returned. Comma-expressions are merely used to pack additional instructions into places where only expressions are allowed. [...] Thanks, that's the second time you are helping me today!
Re: What is the proper way to outline static-if-conditions ?
PS: the title is a misnomer. `is(T : P*, P) && isStaticArray!P` doesn't either compile when inlined because `P` is not defined when not matched.
What is the proper way to outline static-if-conditions ?
Hey D people. Currently in my project I have worked on a unified type interface for all arrays which requires fixed-size arrays to be stored as pointer (in correspondence to dynamic and associative arrays) and allow them being allocated with any selected allocator. There can be code like this: ```d enum isPointedStaticArray(T) = (is(T : P*, P) && .isStaticArray!P); //... static if (.isPointedStaticArray!T) { // ... } ``` It won't compile when the argument of `isPointedStaticArray()` is NO pointer. The compiler complains, about **`P` being undefined**. What is the best workaround for this? It's crazy. I can reverse the problem that it only fails if the argument IS a pointer: ```d enum isPointedStaticArray(T) = (){ enum condition = `is(`~T.stringof~` : P*, P) && .isStaticArray!P`; static if (__traits(compiles, mixin(condition)) ) return mixin(condition); // "P already defined" error else return false; }(); ``` Types defined in `__traits(compiles, ...)` are emitted to the outside?! Okay, this is my current workaround: ```d enum isPointedStaticArray(T) = (){ static if (is(T : P*, P)) return .isStaticArray!(P); else return false; }(); // ... static if (isPointedStaticArray!T) { } ``` for outlining an expression `is(...) && ...` Is there a simpler way in D to do this? If there only would be a `&&&` short circuit operator which doesn't compile the right side if the left side wouldn't compile to true. Did someone already had the idea of a `static-try-catch` which catches compilation errors?
Re: Traits in a template enum
On Sunday, 10 October 2021 at 12:48:49 UTC, Adam D Ruppe wrote: On Sunday, 10 October 2021 at 12:39:17 UTC, Some Guy wrote: I have this enum to get the type enums hold values, not types. try alias instead Thanks! `alias typeOfMember(T, string member) = typeof(__traits(getMember, T, member));` works. But I did not understand what you meant by "enums hold values, not types". Aren't types values at compile time?
Re: Traits in a template enum
On Sunday, 10 October 2021 at 12:39:17 UTC, Some Guy wrote: I have this enum to get the type enums hold values, not types. try alias instead
Re: Traits in a template enum
It actually looks like I'm having problems wherever I try to pass that enum as a template parameter.
Traits in a template enum
I have this enum to get the type of a member field in a struct: `enum typeOfMember(T, string member) = typeof(__traits(getMember, T, member));` I'm having problems when I try to used it though. For example: ```D writeln(typeOfMember!(T, member).stringof); // Doesn't work: Error: initializer must be an expression, not `int[]` writeln(typeof(__traits(getMember, T, member)).stringof); // Expand the enum, it works. ``` What is the problem here? I'm using the LDC 1.27.1.
Re: What is a "comma expression"?
On Sunday, 10 October 2021 at 12:01:33 UTC, rempas wrote: return *ret = v, 1; The comma expression in C is a combination of two things but in the context of another thing. Well that's not very good, but like there's statements and expressions. Statements do something but do not have a value. So `if() {}` and `return` and `for() {}` are statements, because they don't have a value you can assign to a variable. Expressions do something but DO have a value and thus you can assign it to a variable. a = if (true) { a } ; // not permitted because if is a statement a = 5 + 4; // OK, 5+4 is an expression and thus has a value This is a slight simplification but generally true. You'll notice in some languages the if assign does work; in those languages you have an if expression rather than an if statement. The language grammar has rules for where statements are allowed and where expressions are allowed and you can't mix and match (unless the grammar has two rules, one allowing each type). Anyway, the C comma expression is a combination of two other expressions where the first one is evaluated, but its value discarded, then the second part becomes the value of the whole expression. a = 1, 2; // the 1 is discarded, so a == 2 It is actually the same as writing out: 1; // evaluate this then discard it a = 2; // eval this and actually keep the value The difference being that it is allowed in an expression context. So that `return *ret = v, 1;` Could just be written *ret = v; // this is eval'ed and value discarded return 1; // second part value is kept And idk why they didn't just do that here. But the C thing is most commonly seen in a for loop: for(a = 0, b = 0; a < 5; a++, b++) {} because the grammar only allows an expression in each piece of the for loop, so you can't separate the two steps by semicolons like you do in different contexts. Can someone explain what comma expressions are and why they don't work in D (or if the only doesn't work as returned values from a function)? D considers it a bit obscure and special-case to use the comma for. There was talk a while ago about making the comma do something else instead, but this never materialized. But you can always write it out longer form, perhaps wrapping it in a function. // what I would do here: *ret = v; return 1; // or if you absolutely had to have it in an expression context: return (){ *ret = v; return 1; }(); The nested function there explicitly does what the comma operator does and is allowed in expression context as well.
Re: What is a "comma expression"?
On Sunday, 10 October 2021 at 12:01:33 UTC, rempas wrote: This is the first time I'm finding something like that. I'm having the following code in C: ``` if (0 == (i >> 7)) { if (len < 1) return -1; v = i; return *ret = v, 1; } ``` This is part of a function that returns an `int`. When I'm running this in C, it works. However in D, I'm getting the following error message: ``` Error: Using the result of a comma expression is not allowed ``` Can someone explain what comma expressions are and why they don't work in D (or if the only doesn't work as returned values from a function)? Hello rempas. The comma-operator `,` is like `;` but results in an expression value, not a statement like `;` would. The left side of `,` is executed like a statement and the value of the right side of `,` is returned. Comma-expressions are merely used to pack additional instructions into places where only expressions are allowed. ```d if (x = y, myNiceFunction(), yay(x), x > 5) { // ... } ``` or ```d if (hasFancyFunkyStuff) x = z, fancy(x), funkyUpdate(z); // too lazy for braces ``` Many consider the `,` operator to be a design-flaw because it makes expressions difficult to read and can be easily abused because the above should actually be: ```d x = y; myNiceFunction(); yay(x); if (x > 5) { // ... } ``` In `D` you can still write the second example of code but not the first example of code. The designers of D thought they could make it less painful by just forbidding comma-expressions to be used as expression value and only as statement. This is because then comma-expressions can still be used in `for`-loops: ```d for (x = y, z = a; x < z; x++, z--) { ; } ``` In conclusion, your C snippet should actually look like: ```c if (0 == (i >> 7)) { if (len < 1) return -1; *ret = v = i; return 1; } ``` The previous snippet even could mislead readers to think that it would return a tuple of two elements which it doesn't.
What is a "comma expression"?
This is the first time I'm finding something like that. I'm having the following code in C: ``` if (0 == (i >> 7)) { if (len < 1) return -1; v = i; return *ret = v, 1; } ``` This is part of a function that returns an `int`. When I'm running this in C, it works. However in D, I'm getting the following error message: ``` Error: Using the result of a comma expression is not allowed ``` Can someone explain what comma expressions are and why they don't work in D (or if the only doesn't work as returned values from a function)?
Re: How to do a function pointer to "malloc" and "free"?
On Sunday, 10 October 2021 at 10:44:15 UTC, rempas wrote: I'm having the following C code: ``` static void* (*ppmalloc)(size_t) = malloc; static void (*ppfree)(void*) = free; ``` I want to covert this code in D so I try to do the following: ``` static void* function(size_t)*ppmalloc = malloc; static void function(void*)*ppfree = free; ``` If I do that, I'm getting the following error message: ``` Error: function `core.stdc.stdlib.malloc(ulong size)` is not callable using argument types `()` ``` I'm also trying to do the same using "pureMalloc" and "pureFree" instead but this time I'm getting the following error: ``` cannot implicitly convert expression `pureMalloc()(size_t size)` of type `void` to `extern (C) void* function(ulong)*` ``` Any ideas? Hello rempas. This is the way: ```d import core.stdc.stdlib : malloc, free; extern(C) void* function(ulong) mallocPointer = &malloc; extern(C) void function(void*) freePointer = &free; ``` `function` in the type is already a function pointer. Not immediately obvious though: You also must annotate the type with `extern(C)` otherwise it will not work.
How to do a function pointer to "malloc" and "free"?
I'm having the following C code: ``` static void* (*ppmalloc)(size_t) = malloc; static void (*ppfree)(void*) = free; ``` I want to covert this code in D so I try to do the following: ``` static void* function(size_t)*ppmalloc = malloc; static void function(void*)*ppfree = free; ``` If I do that, I'm getting the following error message: ``` Error: function `core.stdc.stdlib.malloc(ulong size)` is not callable using argument types `()` ``` I'm also trying to do the same using "pureMalloc" and "pureFree" instead but this time I'm getting the following error: ``` cannot implicitly convert expression `pureMalloc()(size_t size)` of type `void` to `extern (C) void* function(ulong)*` ``` Any ideas?
Re: How to "stringnify"?
On Sunday, 10 October 2021 at 08:54:55 UTC, evilrat wrote: That's probably depends on what you are trying to achieve. If you want to write code-like string that looks like a code you can use token strings https://dlang.org/spec/lex.html#token_strings ```d string code = q{ float sqr(float x) { return x * x; } }; ``` For other symbols there is .stringof property (beware, it's behavior is not part of the spec) https://dlang.org/spec/property.html#stringof ```d class MyClass() { static this() { registerSmth(MyClass.stringof); // pass "MyClass" string } } ``` And there is stuff for metaprogramming such like this in std.traits https://dlang.org/phobos/std_traits.html#ParameterIdentifierTuple ".stringof" will probably do the job! If not I will check "token_strings". Thanks a lot!
Re: How to "stringnify"?
On Sunday, 10 October 2021 at 08:48:21 UTC, Imperatorn wrote: For simple stuff you have .stringof Thanks!
Re: How to "stringnify"?
On Sunday, 10 October 2021 at 08:28:30 UTC, rempas wrote: Is there a way to "stringnify" in Dlang? In C we would do something like the following: `#define STRINGIFY(x) #x` What's the equivalent in D? That's probably depends on what you are trying to achieve. If you want to write code-like string that looks like a code you can use token strings https://dlang.org/spec/lex.html#token_strings ```d string code = q{ float sqr(float x) { return x * x; } }; ``` For other symbols there is .stringof property (beware, it's behavior is not part of the spec) https://dlang.org/spec/property.html#stringof ```d class MyClass() { static this() { registerSmth(MyClass.stringof); // pass "MyClass" string } } ``` And there is stuff for metaprogramming such like this in std.traits https://dlang.org/phobos/std_traits.html#ParameterIdentifierTuple
Re: How to "stringnify"?
On Sunday, 10 October 2021 at 08:28:30 UTC, rempas wrote: Is there a way to "stringnify" in Dlang? In C we would do something like the following: `#define STRINGIFY(x) #x` What's the equivalent in D? For simple stuff you have .stringof
How to "stringnify"?
Is there a way to "stringnify" in Dlang? In C we would do something like the following: `#define STRINGIFY(x) #x` What's the equivalent in D?