Re: Why is BOM required to use unicode in tokens?

2020-09-14 Thread H. S. Teoh via Digitalmars-d-learn
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?

2020-09-14 Thread Paul Backus via Digitalmars-d-learn
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?

2020-09-14 Thread James Blachly via Digitalmars-d-learn
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

2020-09-14 Thread Mathias LANG via Digitalmars-d-learn

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

2020-09-14 Thread 60rntogo via Digitalmars-d-learn

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

2020-09-14 Thread k2aj via Digitalmars-d-learn

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

2020-09-14 Thread Fitz via Digitalmars-d-learn

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

2020-09-14 Thread Adam D. Ruppe via Digitalmars-d-learn

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

2020-09-14 Thread Fitz via Digitalmars-d-learn
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

2020-09-14 Thread 9il via Digitalmars-d-learn

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

2020-09-14 Thread 60rntogo via Digitalmars-d-learn

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

2020-09-14 Thread 60rntogo via Digitalmars-d-learn
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

2020-09-14 Thread Andrej Mitrovic via Digitalmars-d-learn

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?

2020-09-14 Thread Steven Schveighoffer via Digitalmars-d-learn

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

2020-09-14 Thread Christoph via Digitalmars-d-learn

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

2020-09-14 Thread Seb via Digitalmars-d-learn
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

2020-09-14 Thread Andrej Mitrovic via Digitalmars-d-learn

-
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?

2020-09-14 Thread Simen Kjærås via Digitalmars-d-learn
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