Re: Why is BOM required to use unicode in tokens?
On Mon, Sep 14, 2020 at 09:49:13PM -0400, James Blachly via Digitalmars-d-learn wrote: > I wish to write a function including ∂x and ∂y (these are trivial to > type with appropriate keyboard shortcuts - alt+d on Mac), but without > a unicode byte order mark at the beginning of the file, the lexer > rejects the tokens. > > It is not apparently easy to insert such marks (AFAICT no common tool > does this specifically), while other languages work fine (i.e., accept > unicode in their source) without it. > > Is there a downside to at least presuming UTF-8? Tested it locally, with and without BOM; the lexer rejects ∂ as a valid token. I suspect the reason has nothing to do with BOMs, but with the fact that ∂ is not classified as an alphanumeric (see std.uni.isAlpha, which returns false for ∂). The following code, which contains Cyrillic letters, compiles just fine without BOM (std.uni.isAlpha('Ш') returns true): void main() { int Ш = 1; writeln(Ш); } As the docs for std.uni.isAlpha states, it tests for general Unicode category 'Alphabetic'. Probably identifiers are restricted to characters of this category plus the numerics and '_' (and maybe one or two others, perhaps '$'? Don't remember now). T -- People say I'm indecisive, but I'm not sure about that. -- YHL, CONLANG
Re: Why is BOM required to use unicode in tokens?
On Tuesday, 15 September 2020 at 01:49:13 UTC, James Blachly wrote: I wish to write a function including ∂x and ∂y (these are trivial to type with appropriate keyboard shortcuts - alt+d on Mac), but without a unicode byte order mark at the beginning of the file, the lexer rejects the tokens. It is not apparently easy to insert such marks (AFAICT no common tool does this specifically), while other languages work fine (i.e., accept unicode in their source) without it. Is there a downside to at least presuming UTF-8? According to the spec [1] this should Just Work. I'd recommend filing a bug. [1] https://dlang.org/spec/lex.html#source_text
Why is BOM required to use unicode in tokens?
I wish to write a function including ∂x and ∂y (these are trivial to type with appropriate keyboard shortcuts - alt+d on Mac), but without a unicode byte order mark at the beginning of the file, the lexer rejects the tokens. It is not apparently easy to insert such marks (AFAICT no common tool does this specifically), while other languages work fine (i.e., accept unicode in their source) without it. Is there a downside to at least presuming UTF-8?
Re: default arguments for const ref parameters in extern C++ functions
On Monday, 14 September 2020 at 18:58:44 UTC, 60rntogo wrote: On Monday, 14 September 2020 at 17:11:59 UTC, k2aj wrote: AFAIK the only way to have default ref arguments is to use a global variable: --- extern(C++) struct Foo { int x; } immutable foo1 = Foo(1); extern(C++) void fun(const ref Foo foo = foo1); --- Thanks. This appears to work, but feels like a hack. I can live with that, but I'm still wondering if there is a more idiomatic way of solving the problem. D doesn't let rvalues bind to const ref (well, `in` will do that, but it's D-only). What was described as "global variable", is more of a "manifest constant lvalue". A (static) immutable variable with an initializer will always be CTFE-d and available at compile time, so in this case it is *exactly* what you need. Also note that a default parameter doesn't affect the mangling / ABI, because it works exclusively on the caller side. Thus, you could just remove the default argument and your `extern(C++)` binding would work just fine. But if you want to provide the same API, `[static] immutable` + initializer is the way to go.
Re: default arguments for const ref parameters in extern C++ functions
On Monday, 14 September 2020 at 17:11:59 UTC, k2aj wrote: AFAIK the only way to have default ref arguments is to use a global variable: --- extern(C++) struct Foo { int x; } immutable foo1 = Foo(1); extern(C++) void fun(const ref Foo foo = foo1); --- Thanks. This appears to work, but feels like a hack. I can live with that, but I'm still wondering if there is a more idiomatic way of solving the problem.
Re: default arguments for const ref parameters in extern C++ functions
On Monday, 14 September 2020 at 12:44:34 UTC, 60rntogo wrote: I'm trying to use a C++ library that has a function declared like this: --- struct Foo { int x; }; void fun(const Foo& foo = Foo(1)); --- I have translated this to a D declaration: --- struct Foo { int x; } extern(C++) void fun(const ref Foo foo = Foo(1)); --- This yields an error: "Foo(1) is not an lvalue and cannot be modified". I suppose this makes sense with how D references work, but I have no control over how the C++ function is declared. What can I do with this? AFAIK the only way to have default ref arguments is to use a global variable: --- extern(C++) struct Foo { int x; } immutable foo1 = Foo(1); extern(C++) void fun(const ref Foo foo = foo1); ---
Re: Newbie question: Return a locally allocated variable
On Monday, 14 September 2020 at 16:44:14 UTC, Adam D. Ruppe wrote: This is a common mistake with people coming from C++. A D class is more like a Java class - it is automatically a reference. So your class Bob here in D would actually be represented as `Bob*` in C++. Thus when you define `Bob*` in D, that's like a `Bob**` in C++... a pointer to a pointer. Thus you're getting the address on the stack of the local, not at all what you want. Your factory should really just be: Bob bobFactory() { return new Bob; } Then to compare addresses, do: writeln(cast(void*) bob); // convert the reference itself to a pointer thank you! I was driving myself mad. makes sense now.
Re: Newbie question: Return a locally allocated variable
On Monday, 14 September 2020 at 16:29:11 UTC, Fitz wrote: I expect the following code below to create 10 items with 10 different addresses, instead they all have the same address? You are taking the address of the local variable holding reference, not the reference itself. class Bob { } Bob *bobFactory() { Bob bob = new Bob; Bob *pBob = return pBob; } This is a common mistake with people coming from C++. A D class is more like a Java class - it is automatically a reference. So your class Bob here in D would actually be represented as `Bob*` in C++. Thus when you define `Bob*` in D, that's like a `Bob**` in C++... a pointer to a pointer. Thus you're getting the address on the stack of the local, not at all what you want. Your factory should really just be: Bob bobFactory() { return new Bob; } Then to compare addresses, do: writeln(cast(void*) bob); // convert the reference itself to a pointer
Newbie question: Return a locally allocated variable
I expect the following code below to create 10 items with 10 different addresses, instead they all have the same address? import std.stdio; class Bob { } void main() { for (auto i = 0; i < 10; i++) { auto pBob = bobFactory(); writefln("bob @ %x\n", pBob); } } Bob *bobFactory() { Bob bob = new Bob; Bob *pBob = return pBob; }
Re: Red-Black Gauss-seidel with mir
On Monday, 14 September 2020 at 09:50:16 UTC, Christoph wrote: Hi Ilya, On Sunday, 13 September 2020 at 19:29:31 UTC, 9il wrote: [...] I have tested it with dmd and ldc and called them just with $ dub build --compiler=ldc(dmd) with no more configurations in the dub.json file. [...] On Monday, 14 September 2020 at 09:50:16 UTC, Christoph wrote: For a release performance, it should be run in release mode ``` dub build --build=release --compiler=ldc2 ``` I expect it will speed up the slow version a few times. Also, the slow version has a few times more memory access then the fast version and Python. The improvement would look more like the C code and require inner loops. Your fast version looks good too me. If it is correct, it is very good.
Re: default arguments for const ref parameters in extern C++ functions
On Monday, 14 September 2020 at 12:44:34 UTC, 60rntogo wrote: --- struct Foo { int x; } extern(C++) void fun(const ref Foo foo = Foo(1)); --- I suppose this should have been: --- extern(C++): struct Foo { int x; } void fun(const ref Foo foo = Foo(1)); --- Not that it changes the question in any way.
default arguments for const ref parameters in extern C++ functions
I'm trying to use a C++ library that has a function declared like this: --- struct Foo { int x; }; void fun(const Foo& foo = Foo(1)); --- I have translated this to a D declaration: --- struct Foo { int x; } extern(C++) void fun(const ref Foo foo = Foo(1)); --- This yields an error: "Foo(1) is not an lvalue and cannot be modified". I suppose this makes sense with how D references work, but I have no control over how the C++ function is declared. What can I do with this?
Re: A function to split a range into several ranges of different chunks
On Monday, 14 September 2020 at 09:08:01 UTC, Seb wrote: You likely want to get involved / raise your support here: https://github.com/dlang/phobos/pull/7600 Oh this is great, thank you!
Re: Get enum value name as string at compile time?
On 9/14/20 2:25 AM, Simen Kjærås wrote: On Monday, 14 September 2020 at 03:48:51 UTC, Steven Schveighoffer wrote: Consider the enum: enum Foo { a, b } Foo.a.stringof => "a" enum x = Foo.a; x.stringof => "cast(Foo)0" Is there another way I can take an enum value that's known at compile time (but not the actual identifier), and get the name of it? I know I can use a switch, or to!string. But I was hoping this was easy for the compiler to figure out some way without involving CTFE. It is a bit weird that x.stringof doesn't simply return the name like Foo.a.stringof does. Anyways, this works: template enumName(alias a) { import std.meta : staticIndexOf, staticMap; alias T = typeof(a); enum getValue(string name) = __traits(getMember, T, name); alias enumValues = staticMap!(getValue, __traits(allMembers, T)); enum enumName = __traits(allMembers, T)[staticIndexOf!(a, enumValues)]; } enum Foo { a = 2, b = 19 } enum x = Foo.a; pragma(msg, enumName!x); // "a" Thanks. I never considered doing something like that. Not sure I like that better than the CTFE version. I just punted and used to!string in my code anyway. A CTFE linear search in a compile-time array probably wouldn't be too bad, especially when the list of elements is not long. Again, we could use that ... DIP to make things a lot less complex. -Steve
Re: Red-Black Gauss-seidel with mir
Hi Ilya, On Sunday, 13 September 2020 at 19:29:31 UTC, 9il wrote: More details are required. What compiler and command line has been used? I have tested it with dmd and ldc and called them just with $ dub build --compiler=ldc(dmd) with no more configurations in the dub.json file. I have compared them with a 100 x 100 example problem and the version with the for-loops from above takes around 1.8s compiled with ldc and 0.8s compiled with dmd. The slow version from below takes with the same problem around 18s(dmd) and 12s (ldc) on my maschine. The driver function for my Gaussseidel method looks like this: ``` /++ This is a Gauss Seidel Red Black implementation it solves AU = F, with A being a poisson matrix like this 1 1 1 1 .. 1 1 4 1 0 .. 1 1 1 4 1 .. 1 . . . 0..1 4 1 . 1 .. 1 1 1 1 so the borders of U remain unchanged Params: U = slice of dimension Dim F = slice of dimension Dim h = the distance between the grid points Returns: U +/ Slice!(T*, Dim) GS_RB(T, size_t Dim, size_t max_iter = 10_000_000, size_t norm_iter = 1_000, double eps = 1e-8) (in Slice!(T*, Dim) F, Slice!(T*, Dim) U, in T h) if (1 <= Dim && Dim <= 3 && isFloatingPoint!T) { const T h2 = h * h; foreach (it; 1 .. max_iter + 1) { if (it % norm_iter == 0) { const auto norm = compute_residual!(T, Dim)(F, U, h).nrmL2; if (norm <= eps) { break; } } // rote Halbiteration sweep!(T, Dim, Color.red)(F, U, h2); // schwarze Halbiteration sweep!(T, Dim, Color.black)(F, U, h2); } return U; } ``` And the full slow version looks like this: ``` void sweep(T, size_t Dim : 2, Color color) (in Slice!(T*, 2) F, Slice!(T*, 2) U, T h2) { const auto m = F.shape[0]; const auto n = F.shape[1]; static if (color == Color.red) { U[1 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] = U[0 .. m - 2, 1 .. n - 1].strided!(0, 1)(2, 2); U[1 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] += U[2 .. m, 1 .. n - 1].strided!(0, 1)(2, 2); U[1 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] += U[1 .. m - 1, 0 .. n - 2].strided!(0, 1)(2, 2); U[1 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] += U[1 .. m - 1, 2 .. n].strided!(0, 1)(2, 2); U[1 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] -= F[1 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2) * h2; U[1 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] /= cast(T) 4.0; U[2 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] = U[1 .. m - 2, 2 .. n - 1].strided!(0, 1)(2, 2); U[2 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] += U[3 .. m, 2 .. n - 1].strided!(0, 1)(2, 2); U[2 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] += U[2 .. m - 1, 1 .. n - 2].strided!(0, 1)(2, 2); U[2 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] += U[2 .. m - 1, 3 .. n].strided!(0, 1)(2, 2); U[2 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] -= F[2 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2) * h2; U[2 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] /= cast(T) 4.0; } else static if (color == Color.black) { U[1 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] = U[0 .. m - 2, 2 .. n - 1].strided!(0, 1)(2, 2) / 4.0; U[1 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] += U[2 .. m, 2 .. n - 1].strided!(0, 1)(2, 2) / 4.0; U[1 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] += U[1 .. m - 1, 1 .. n - 2].strided!(0, 1)(2, 2) / 4.0; U[1 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] += U[1 .. m - 1, 3 .. n].strided!(0, 1)(2, 2) / 4.0; U[1 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2)[] -= F[1 .. m - 1, 2 .. n - 1].strided!(0, 1)(2, 2) * h2 / 4.0; U[2 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] = U[1 .. m - 2, 1 .. n - 1].strided!(0, 1)(2, 2) / 4.0; U[2 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] += U[3 .. m, 1 .. n - 1].strided!(0, 1)(2, 2) / 4.0; U[2 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] += U[2 .. m - 1, 0 .. n - 2].strided!(0, 1)(2, 2) / 4.0; U[2 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] += U[2 .. m - 1, 2 .. n].strided!(0, 1)(2, 2) / 4.0; U[2 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2)[] -= F[2 .. m - 1, 1 .. n - 1].strided!(0, 1)(2, 2) * h2 / 4.0; } else { static assert(false, color.stringof ~ "invalid color"); } } ``` Thank you very much for your time. Christoph
Re: A function to split a range into several ranges of different chunks
On Monday, 14 September 2020 at 07:49:31 UTC, Andrej Mitrovic wrote: - import std.range; import std.stdio; void main () { auto range = sequence!((a, n) => n); // works, but the chunks are all the same length auto rngs = range.chunks(4); writeln(rngs[0]); writeln(rngs[1]); writeln(rngs[2]); // want this auto ranges = range.???(3, 4, 5); writeln(ranges[0] == [1, 2, 3]); writeln(ranges[1] == [4, 5, 6, 7]); writeln(ranges[2] == [8, 9, 10, 11, 12]); } - Do you know of a simple way to do this? It's essentially similar to chunks, except the chunks themselves would not be of the same length. You can think of a good name for '???' here. Maybe this is already possible by combining functionality in std.range - but I came up short. You likely want to get involved / raise your support here: https://github.com/dlang/phobos/pull/7600
A function to split a range into several ranges of different chunks
- import std.range; import std.stdio; void main () { auto range = sequence!((a, n) => n); // works, but the chunks are all the same length auto rngs = range.chunks(4); writeln(rngs[0]); writeln(rngs[1]); writeln(rngs[2]); // want this auto ranges = range.???(3, 4, 5); writeln(ranges[0] == [1, 2, 3]); writeln(ranges[1] == [4, 5, 6, 7]); writeln(ranges[2] == [8, 9, 10, 11, 12]); } - Do you know of a simple way to do this? It's essentially similar to chunks, except the chunks themselves would not be of the same length. You can think of a good name for '???' here. Maybe this is already possible by combining functionality in std.range - but I came up short.
Re: Get enum value name as string at compile time?
On Monday, 14 September 2020 at 03:48:51 UTC, Steven Schveighoffer wrote: Consider the enum: enum Foo { a, b } Foo.a.stringof => "a" enum x = Foo.a; x.stringof => "cast(Foo)0" Is there another way I can take an enum value that's known at compile time (but not the actual identifier), and get the name of it? I know I can use a switch, or to!string. But I was hoping this was easy for the compiler to figure out some way without involving CTFE. It is a bit weird that x.stringof doesn't simply return the name like Foo.a.stringof does. Anyways, this works: template enumName(alias a) { import std.meta : staticIndexOf, staticMap; alias T = typeof(a); enum getValue(string name) = __traits(getMember, T, name); alias enumValues = staticMap!(getValue, __traits(allMembers, T)); enum enumName = __traits(allMembers, T)[staticIndexOf!(a, enumValues)]; } enum Foo { a = 2, b = 19 } enum x = Foo.a; pragma(msg, enumName!x); // "a" -- Simen