Re: Inconsistency between `AllMembers` and `hasMember`

2018-11-18 Thread bauss via Digitalmars-d-learn
On Sunday, 18 November 2018 at 02:37:13 UTC, Stanislav Blinov 
wrote:

On Sunday, 18 November 2018 at 00:51:51 UTC, drug wrote:

On 18.11.2018 1:26, Adam D. Ruppe wrote:


That's because the compiler passes it a hidden pointer to 
refer to the context outside. The compiler could perhaps be 
smarter about it, and see if those methods actually refer to 
the context, but it seems to simply say if the method is 
there, it might refer to it and it adds the context pointer 
(note that S.sizeof increases too) and a magic constructor to 
set it.
Well, if "this" means hidden pointer then it never should be 
returned by AllMembers at all, isn't it?


It's only "hidden" in that there's no symbol to access it. But 
you can still access it via .tupleof, and it still of course 
affects the ABI (i.e. S.sizeof is always at least pointer size 
when S is nested).
If you want to iterate fields, .tupleof is a better way to do 
it. As for that hidden pointer, you can just test with 
__traits(isNested, S) whether that's present, and just don't 
look at the last field.


But in that case shouldn't you be able to tell whether it has it 
or not through hasMember?


Re: Inconsistency between `AllMembers` and `hasMember`

2018-11-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 18 November 2018 at 09:10:57 UTC, bauss wrote:
On Sunday, 18 November 2018 at 02:37:13 UTC, Stanislav Blinov 
wrote:



It's only "hidden" in that there's no symbol to access it...


But in that case shouldn't you be able to tell whether it has 
it or not through hasMember?


Yah, a case for inconsistency could be made here. IMHO it should 
just have some reserved name like __context.


Re: Inconsistency between `AllMembers` and `hasMember`

2018-11-18 Thread drug via Digitalmars-d-learn

On 18.11.2018 5:37, Stanislav Blinov wrote:


It's only "hidden" in that there's no symbol to access it. But you can 
still access it via .tupleof, and it still of course affects the ABI 
(i.e. S.sizeof is always at least pointer size when S is nested).
If you want to iterate fields, .tupleof is a better way to do it. As for 
that hidden pointer, you can just test with __traits(isNested, S) 
whether that's present, and just don't look at the last field.


But what is the reason for someone to use this pointer even via 
.tupleof? I still think AllMember shouldn't return it at all. Of course 
I can filter it using isNested or just comparing with "this" leteral 
during iteration. But it complicates things I believe.


P.S. using isNested seems to be more portable solution than comparing 
with leteral but is this pointer always the last element in AllMember 
trait result?


Re: Inconsistency between `AllMembers` and `hasMember`

2018-11-18 Thread Stanislav Blinov via Digitalmars-d-learn

Reported:

https://issues.dlang.org/show_bug.cgi?id=19410


Re: How do you debug @safe @nogc code? Can't figure out how to print.

2018-11-18 Thread aliak via Digitalmars-d-learn
On Saturday, 17 November 2018 at 21:56:23 UTC, Neia Neutuladh 
wrote:

On Sat, 17 Nov 2018 21:16:13 +, aliak wrote:
Could do. But it's not scalable. I'd have to comment out all 
the unittests that call the template function with a T that 
allocates inside the @nogc template (if I understood you 
correctly that it)


I meant something like:

void debugln(T...)(T args) @nogc
{
  import std.stdio;
  debug(MyProject) writeln(args);
}

You use that function instead of writeln in your 
@nogc-compatible templates:


void callFunc(alias func)()
{
  debugln("about to call function!");
  func();
  debugln("done calling function!");
}

Then I can write:

@nogc:
void foo() { printf("hello world\n"); }
void main() { callFunc!foo(); }


Aha! I misunderstood what you meant. Yes that's actually simpler 
that what I was doing :D Thanks!


Re: Making external types available to mixins

2018-11-18 Thread John Chapman via Digitalmars-d-learn
On Saturday, 17 November 2018 at 21:11:38 UTC, Adam D. Ruppe 
wrote:
On Saturday, 17 November 2018 at 17:58:54 UTC, John Chapman 
wrote:

Has anyone had a similar need and come up with a solution?


You might be able to just pass it the Calendar type, and then 
fetch its parent module and get the ICalendarFactory from there 
(assuming they are defined in the same module).


But generally speaking, passing strings to a mixin that refer 
to something in another module isn't going to work well thanks 
to scoping rules. You are better off passing a symbol of some 
sort.


So there is no actual Calendar type. There's an ICalendarFactory 
type that creates instances of ICalendar (these types are part of 
a third-party API).  "Calendar" is just a key users could use 
when calling a "makeWith" method that would build the 
ICalendar/Factory names, instantiate the factory, call the 
appropriate factory method and return the result. There are 
thousands of such object/factory pairs in the API. Just trying to 
cut out a lot of boilerplate code, but it doesn't seem doable 
this way.


difficulties with const structs and alias this / template functions

2018-11-18 Thread Dennis via Digitalmars-d-learn
I'm making a fixed point numeric type and want it to work 
correctly with const. First problem:


```
const q16 a = 6;
a /= 2;  // compiles! despite `a` being const.
writeln(a);  // still 6
a.toQ32 /= 2;// what's actually happening
```

My q16 type has an implicit conversion to q32 (like how int can 
be converted to long):

```
q32 toQ32() const {
  return q32(...);
}
alias toQ32 this;
```
How do I make it so that a const(q16) will be converted to a 
const(q32) instead of mutable q32?


Second problem:
```
Q log2(Q)(Q num) if (is(Q : q16) || is(Q : q32)) {
import std.traits: Unqual;
Unqual!Q x = num;
// actual code
}
```
When I call this with a const(q16), Q is resolved to const(q16) 
so I have to unqualify Q every time. It works, but feels clumsy. 
Is there an easier way to automatically de-const parameters? 
We're working with small value types here, it should be simple.


If anyone knows any other pitfalls with const, I'd love to know 
them.


Neater enum + version

2018-11-18 Thread Vladimirs Nordholm via Digitalmars-d-learn

Currently I have something like

version (Posix)
{
enum foo = "bar";
}
else
{
enum foo = "baz";
}

Is there anyway to make it "neater"? Maybe something in one line:

enum foo = version (Posix) { "posix" } : { "other" } ;


Re: Neater enum + version

2018-11-18 Thread Neia Neutuladh via Digitalmars-d-learn
On Sun, 18 Nov 2018 17:47:07 +, Vladimirs Nordholm wrote:
> Is there anyway to make it "neater"? Maybe something in one line:
> 
>  enum foo = version (Posix) { "posix" } : { "other" } ;

If you're doing it often:

T ifPosix(T)(T a, T b)
{
  version (Posix) return a; else return b;
}
enum foo = ifPosix("posix", "other");

If it's a one-off thing, though, there's not much you can do.


Re: Neater enum + version

2018-11-18 Thread Vladimirs Nordholm via Digitalmars-d-learn

On Sunday, 18 November 2018 at 17:52:21 UTC, Neia Neutuladh wrote:

On Sun, 18 Nov 2018 17:47:07 +, Vladimirs Nordholm wrote:
Is there anyway to make it "neater"? Maybe something in one 
line:


 enum foo = version (Posix) { "posix" } : { "other" } ;


If you're doing it often:

T ifPosix(T)(T a, T b)
{
  version (Posix) return a; else return b;
}
enum foo = ifPosix("posix", "other");

If it's a one-off thing, though, there's not much you can do.


Ah. Thank you for the example, might use that some other time.

Thanks :)


Re: difficulties with const structs and alias this / template functions

2018-11-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 18 November 2018 at 17:30:18 UTC, Dennis wrote:
I'm making a fixed point numeric type and want it to work 
correctly with const. First problem:


```
const q16 a = 6;
a /= 2;  // compiles! despite `a` being const.


Ouch. That's actually kind of nasty.


writeln(a);  // still 6
a.toQ32 /= 2;// what's actually happening
```

My q16 type has an implicit conversion to q32 (like how int can 
be converted to long):

```
q32 toQ32() const {
  return q32(...);
}
alias toQ32 this;
```
How do I make it so that a const(q16) will be converted to a 
const(q32) instead of mutable q32?


Like this:

// implement separate methods for mutable/const/immutable
q32 toQ32() {
return q32(x);
}

const(q32) toQ32() const {
return q32(x);
}

immutable(q32) toQ32() immutable {
return q32(x);
}

Or like this:

// implement all three in one method, using the `this 
template` feature

auto toQ32(this T)() {
static if (is(T == immutable))
return immutable(q32)(x);
else static if (is(T == const))
return const(q32)(x);
else
return q32(x);
}



Second problem:
```
Q log2(Q)(Q num) if (is(Q : q16) || is(Q : q32)) {
import std.traits: Unqual;
Unqual!Q x = num;
// actual code
}
```
When I call this with a const(q16), Q is resolved to const(q16) 
so I have to unqualify Q every time. It works, but feels 
clumsy. Is there an easier way to automatically de-const 
parameters? We're working with small value types here, it 
should be simple.


Define different overloads for Q and const Q. Or this:

Q log2(Q)(inout Q num) if (is(Q : q16) || is(Q : q32)) { /* ... 
*/ }


Being able to jam mutable/const/immutable implementation in one 
function like that should tell you that you shouldn't mutate the 
argument. Then, the necessity to Unqual will go away on it's own 
;)


Re: Neater enum + version

2018-11-18 Thread Jacob Carlborg via Digitalmars-d-learn

On 2018-11-18 18:52, Neia Neutuladh wrote:

On Sun, 18 Nov 2018 17:47:07 +, Vladimirs Nordholm wrote:

Is there anyway to make it "neater"? Maybe something in one line:

  enum foo = version (Posix) { "posix" } : { "other" } ;


If you're doing it often:

T ifPosix(T)(T a, T b)
{
   version (Posix) return a; else return b;
}
enum foo = ifPosix("posix", "other");

If it's a one-off thing, though, there's not much you can do.


This can be generalized by passing in the version identifier as a string 
and do a string mixin.


--
/Jacob Carlborg


Re: difficulties with const structs and alias this / template functions

2018-11-18 Thread Dennis via Digitalmars-d-learn
On Sunday, 18 November 2018 at 18:17:54 UTC, Stanislav Blinov 
wrote:
// implement separate methods for 
mutable/const/immutable


Thanks. I should have tried that, but I assumed it wouldn't work 
since you can't overload on return-type only. However, the const 
/ non-const makes it allowed.



Or like this:

// implement all three in one method, using the `this 
template` feature


That's new to me, interesting.


Define different overloads for Q and const Q. Or this:

Q log2(Q)(inout Q num) if (is(Q : q16) || is(Q : q32)) { /* ... 
*/ }


Being able to jam mutable/const/immutable implementation in one 
function like that should tell you that you shouldn't mutate 
the argument. Then, the necessity to Unqual will go away on 
it's own ;)


Different overloads sounds like a lot of boilerplate.
inout still results in "cannot modify `inout` expression `input`"
My goal is to be able to write straightforward and correct 
signatures for fixed point functions that receive mutable copies 
of whatever they are fed. This isn't even limited to my custom 
types:


```
T f0(T)(T x, T y) {return x += y;}
int  f1(int  x, int  y) {return x += y;}
long f1(long x, long y) {return x += y;}

void main()
{
import std.stdio;
writeln(f0(const(int)(3), const(long)(4))); // can't modify 
const

writeln(f1(const(int)(3), const(long)(4))); // fine
}
```
The explicit overloads of f1 work fine, but the generic f0 does 
not. I could just use the f1 strategy of explicitly making 
overloads, but then adding a q64 or q128 type would mean having 
to double the existing boilerplate everywhere. I would like to 
have a `isFixedPoint` template and generic functions that take 
any isFixedPoint!Q, but it seems I have to manually enforce 
"don't forget to unqual Q first!".




Re: difficulties with const structs and alias this / template functions

2018-11-18 Thread Rubn via Digitalmars-d-learn

On Sunday, 18 November 2018 at 17:30:18 UTC, Dennis wrote:
I'm making a fixed point numeric type and want it to work 
correctly with const. First problem:


```
const q16 a = 6;
a /= 2;  // compiles! despite `a` being const.
writeln(a);  // still 6
a.toQ32 /= 2;// what's actually happening
```

My q16 type has an implicit conversion to q32 (like how int can 
be converted to long):

```
q32 toQ32() const {
  return q32(...);
}
alias toQ32 this;
```
How do I make it so that a const(q16) will be converted to a 
const(q32) instead of mutable q32?


Second problem:
```
Q log2(Q)(Q num) if (is(Q : q16) || is(Q : q32)) {
import std.traits: Unqual;
Unqual!Q x = num;
// actual code
}
```
When I call this with a const(q16), Q is resolved to const(q16) 
so I have to unqualify Q every time. It works, but feels 
clumsy. Is there an easier way to automatically de-const 
parameters? We're working with small value types here, it 
should be simple.


If anyone knows any other pitfalls with const, I'd love to know 
them.


Yah most people tend to avoid const for this reason. It only 
really works for basic types, if you have a "const int" you can 
convert it to an "int" by copy. But if you have a type like 
Vector!(const int) that won't work, you can't even convert 
Vector!int to Vector!(const int) easily for example.



```
Q log2(Q)(Q num) if (is(Q : q16) || is(Q : q32)) {
import std.traits: Unqual;
Unqual!Q x = num;
// actual code
}
```


This is pretty much the only way, you can just add

alias V = Unqual!Q;

then use V in your function instead of Unqual!Q everywhere.


Re: difficulties with const structs and alias this / template functions

2018-11-18 Thread Dennis via Digitalmars-d-learn

On Sunday, 18 November 2018 at 22:30:52 UTC, Rubn wrote:
Yah most people tend to avoid const for this reason. It only 
really works for basic types, if you have a "const int" you can 
convert it to an "int" by copy. But if you have a type like 
Vector!(const int) that won't work, you can't even convert 
Vector!int to Vector!(const int) easily for example.


That's unfortunate. I can relate better to Jonathan's article [1] 
now. But I'll still try to make it working with const since other 
people might want to use it.


I'm also trying to make it work with immutable, and from BigInt 
[2] I learned that constructors need to be `pure` for creating 
immutable objects. (I don't know why.)


Are there any other gotchas? I didn't add an immutable variant 
for toQ32 like Stanislav suggested, but creating an immutable q32 
from a q16 still seems to work fine.


[1] http://jmdavisprog.com/articles/why-const-sucks.html
[2] https://issues.dlang.org/show_bug.cgi?id=17330


Re: opDispatch doesn't play nice with inheritance

2018-11-18 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, November 17, 2018 11:09:51 PM MST Carl Sturtivant via 
Digitalmars-d-learn wrote:
> On Thursday, 15 November 2018 at 19:01:45 UTC, Ali Çehreli wrote:
> > On 11/15/2018 09:14 AM, Carl Sturtivant wrote:
> > > opDispatch is special in that it allows for functions to be
> >
> > added to a
> >
> > > class or struct when undefined overtly but used elsewhere but
> >
> > it seems
> >
> > > those functions sadly are final.
> > >
> > > Can anything useful be done to remedy the situation?
> >
> > For the compiler to be able to make all opDispatch
> > instantiations virtual, it would have to first see all calls
> > that generate opDispatch instantiations. (Impossible in the
> > presence of separate compilation.)
> >
> > Only then the compiler would know how large the vtbl of the
> > base class should be and what member functions of the derived
> > class are overrides of those virtual functions.
>
> I suppose it's such administrative difficulties that led to D
> defining anything that might conceivably be overridden to be
> virtual, whether or not actually overridden.

The issue with templated functions is that you don't have the full list of
instantiations when the base class is compiled, whereas as I understand it,
the issue with virtual-by-default is more of an issue of choosing code
correctness by default over efficiency by default.

You can get some fun, subtle bugs in C++ when you call non-virtual functions
in circumstances where they were overridden and used as if they were
virtual. So, by making all public and protected class member functions
virtual by default and not allowing non-virtual functions to be overridden,
it prevents a whole class of bugs. It _does_ have some performance downsides
in that it easily leads to functions being virtual when they don't need to
be, which can be gotten around with some extra effort, but it's effectively
favoring correctness by default over efficiency. And for a lot of programs,
it's a great tradeoff, especially when the whole point of classes in D is to
use inheritance and polymorphism, and the cases where you don't need it, you
use a struct. For the rest, final can be used to devirtualize a function as
long as it's not overriding a function.

To avoid bugs in the same way that we currently do without having virtual be
the default, we probably would have had to make it illegal to override any
class functions unless they were explicitly virtual, which would have
created a different set of problems. And whether that would be better or
worse is a matter of debate. In the end, it's a matter of tradeoffs, and
which is better is likely to depend on how your applications benefit from
and use the feature. If most of your class functions are used
polymorphically, then having to mark them as virtual or having to put
virtual: at the top of your class would get really annoying, whereas if you
typically have only a few virtual functions and then lots of non-virtual
property functions (like the AAA guys apparently like to do), then having to
mark things with final to devirtualize them is very annoying. There's no
pleasing everyone. Either way, allowing overriding non-virtual functions
like C++ does would just be begging for bugs.

- Jonathan M Davis






Re: difficulties with const structs and alias this / template functions

2018-11-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 18 November 2018 at 20:10:52 UTC, Dennis wrote:
On Sunday, 18 November 2018 at 18:17:54 UTC, Stanislav Blinov 
wrote:


Q log2(Q)(inout Q num) if (is(Q : q16) || is(Q : q32)) { /* 
... */ }


Being able to jam mutable/const/immutable implementation in 
one function like that should tell you that you shouldn't 
mutate the argument. Then, the necessity to Unqual will go 
away on it's own ;)


Different overloads sounds like a lot of boilerplate.
inout still results in "cannot modify `inout` expression 
`input`"


You just dismissed that second to last sentence, did you? :)

My goal is to be able to write straightforward and correct 
signatures for fixed point functions that receive mutable 
copies of whatever they are fed. This isn't even limited to my 
custom types:


```
T f0(T)(T x, T y) {return x += y;}
int  f1(int  x, int  y) {return x += y;}
long f1(long x, long y) {return x += y;}
```
The explicit overloads of f1 work fine, but the generic f0 does 
not.


```
T f0(T)(inout T x, inout T y) { return x + y; }
```

;)

But if you really really want to mutate the argument, then 
handling different mutability for T is the only way:


```
T f0(T)(T x, T y) {
import std.traits : isMutable;
static if (isMutable!T) return x += y;
else return x + y;
}
```

I know it's a bit painful though. In fact, Phobos also suffers 
from it. In std.numeric:


T gcd(T)(T a, T b)
if (isIntegral!T)
{
static if (is(T == const) || is(T == immutable))
{
return gcd!(Unqual!T)(a, b);
}
// ...
}

Not only that looks ugly, but (with DMD) it makes gcd a doulbe 
function call :D


Re: difficulties with const structs and alias this / template functions

2018-11-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 19 November 2018 at 00:50:28 UTC, Dennis wrote:

I'm also trying to make it work with immutable, and from BigInt 
[2] I learned that constructors need to be `pure` for creating 
immutable objects. (I don't know why.)


That's only for types with indirections (pointers), since `pure` 
guarantees that you do not mutate any global state.


For value types, they work just fine:

struct q16 {
uint x;

this(uint x) { this.x = x; }
this(uint x) const { this.x = x; }
this(uint x) immutable { this.x = x; }

// or again, all three packed together:

this(this T)(uint x) { this.x = x; }
}

Are there any other gotchas? I didn't add an immutable variant 
for toQ32 like Stanislav suggested, but creating an immutable 
q32 from a q16 still seems to work fine.


Yup, that's because, like Rubn said, copying value types is 
trivial. Where it all comes to bite you is when you start having 
pointers, because you can't copy a const(T)* into a T*.




Re: difficulties with const structs and alias this / template functions

2018-11-18 Thread Dennis via Digitalmars-d-learn
On Monday, 19 November 2018 at 01:13:29 UTC, Stanislav Blinov 
wrote:

You just dismissed that second to last sentence, did you? :)


I don't know what you mean with it. It's not that I'm trying to 
be sneaky or lazy really trying to modify the const parameter 
when I should treat it properly. And as the author I'm fine with 
Unqualing everything if that's needed, my concern is when another 
person using my type tries to write his own function:


```
q16 pow(q16 base, int exponent) {
  q16 result = 1;
  foreach(i; 0..exponent) result *= base;
  return result;
}

const q16 x = 3;
writeln(pow(x, 3)); //works!
```

He then wants to make it more generic, so he rewrites:

```
Q pow(Q base, int exponent) if (isFixedPoint!Q) {
  Q result = 1;
  foreach(i; 0..exponent) result *= base;
  return result;
}
```

And initially it seems to work, but as soon as it is used with 
const it breaks as `result` can't be mutated anymore. I'd like to 
set the example of writing proper generic functions, and if there 
is something simpler than importing Unqual I'd prefer that over 
my current solution. If there isn't, I'll just need to write a 
"don't forget to Unqual const" comment.



```
T f0(T)(inout T x, inout T y) { return x + y; }
```

;)


What does inout do here? If the return type is also inout(T) I 
know that the return type gets the same qualifiers as inout 
parameters. But in this example, the return value is still T.


I know it's a bit painful though. In fact, Phobos also suffers 
from it. In std.numeric:


Yuck!



Re: difficulties with const structs and alias this / template functions

2018-11-18 Thread Dennis via Digitalmars-d-learn
On Monday, 19 November 2018 at 01:24:02 UTC, Stanislav Blinov 
wrote:
Yup, that's because, like Rubn said, copying value types is 
trivial. Where it all comes to bite you is when you start 
having pointers, because you can't copy a const(T)* into a T*.


I'm not using reference types, but still:

```
struct S {
int a;
this(int a) {
this.a = a;
}
}

void main()
{
immutable S d = 3;
}

```

onlineapp.d(10): Error: mutable method onlineapp.S.this is not 
callable using a immutable object
onlineapp.d(10):Consider adding const or inout to 
onlineapp.S.this


const still leaves the first error, inout works though I don't 
know what it does.

Adding pure also works.


Re: difficulties with const structs and alias this / template functions

2018-11-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 19 November 2018 at 02:03:18 UTC, Dennis wrote:
On Monday, 19 November 2018 at 01:13:29 UTC, Stanislav Blinov 
wrote:

You just dismissed that second to last sentence, did you? :)


I don't know what you mean with it. It's not that I'm trying to 
be sneaky or lazy really trying to modify the const parameter 
when I should treat it properly. And as the author I'm fine 
with Unqualing everything if that's needed, my concern is when 
another person using my type tries to write his own function:


```
q16 pow(q16 base, int exponent) {
  q16 result = 1;
  foreach(i; 0..exponent) result *= base;
  return result;
}

const q16 x = 3;
writeln(pow(x, 3)); //works!
```

He then wants to make it more generic, so he rewrites:

```
Q pow(Q base, int exponent) if (isFixedPoint!Q) {
  Q result = 1;
  foreach(i; 0..exponent) result *= base;
  return result;
}
```

And initially it seems to work, but as soon as it is used with 
const it breaks as `result` can't be mutated anymore.


Yes, but that's not the problem with your type. It's a problem 
with the user not realizing that const is a type qualifier.


I'd like to set the example of writing proper generic 
functions, and if there is something simpler than importing 
Unqual I'd prefer that over my current solution. If there 
isn't, I'll just need to write a "don't forget to Unqual const" 
comment.



```
T f0(T)(inout T x, inout T y) { return x + y; }
```

;)


What does inout do here?


You're right, it's not needed there at all.

If the return type is also inout(T) I know that the return type 
gets the same qualifiers as inout parameters. But in this 
example, the return value is still T.


Because, as before, value types are all copyable between 
mutable/const/immutable. So even if `return x + y` would yield a 
`const T`, you can still instantiate a T from it.




Re: difficulties with const structs and alias this / template functions

2018-11-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 19 November 2018 at 02:08:14 UTC, Dennis wrote:
On Monday, 19 November 2018 at 01:24:02 UTC, Stanislav Blinov 
wrote:
Yup, that's because, like Rubn said, copying value types is 
trivial. Where it all comes to bite you is when you start 
having pointers, because you can't copy a const(T)* into a T*.


I'm not using reference types, but still:

```
struct S {
int a;
this(int a) {
this.a = a;
}
}

void main()
{
immutable S d = 3;
}

```

onlineapp.d(10): Error: mutable method onlineapp.S.this is not 
callable using a immutable object
onlineapp.d(10):Consider adding const or inout to 
onlineapp.S.this


const still leaves the first error...


You're skimming the examples ;)

struct S {
int a;
this(int a) { this.a = a; }
this(int a) const { this.a = a; }
this(int a) immutable { this.a = a; }
}

or

struct S {
int a;
this(this T)(int a) { this.a = a; }
}


...inout works though I don't know what it does.


Recall that member functions (including constructors) are just 
functions in disguise:


struct S {
this(int a) inout { /* ... */ }
}

what that boils down to, conceptually, is:

void _compiler_made_it_a_struct_S_constructor(ref inout S this, 
int a);


In other words, an `inout` method makes the "this" reference an 
`inout`. Same goes for const, immutable, etc.


D vs perl6

2018-11-18 Thread dangbinghoo via Digitalmars-d-learn

hi,

What if D compared with the latest perl6? well, I know that perl6 
is a VM targeted language. so which has the greater 
modeling-power? And perl6 seems is selling for Concurrency[1], 
but I think D will do this far better than a VM targeted 
language, right?


with the pre-released version of perl6 publicity, perl6 will be a 
powerful language with features like "lazy and eager list 
evaluation", but after learned D, look back to perl6, I found 
very few things that means "powerful".


So, can you experts give a more comprehensive compare with perl6 
and D?  speed? modeling-power? concurrency? package-management 
dub vs CPAN? ...


Thanks!

[1]: https://www.evanmiller.org/why-im-learning-perl-6.html