Re: C++'s this() equivalent?

2023-06-15 Thread zjh via Digitalmars-d-learn

On Friday, 16 June 2023 at 01:54:22 UTC, Jonathan M Davis wrote:

```d
doSomething();
scope(exit) undoSomething();
```


Thank you for your `wonderful summary`. It's worth saving the 
link.




Re: C++'s this() equivalent?

2023-06-15 Thread zjh via Digitalmars-d-learn

On Friday, 16 June 2023 at 01:45:35 UTC, CM wrote:

```d
auto m = Man();
assert(m.name == defaultName);
```

Do note that one cannot simultaneously have a constructor and a 
static opCall, even if their parameters differ.



Thank you for your reply. This should be enough, as this type of 
RAII is basically a `temporary struct`.




Re: C++'s this() equivalent?

2023-06-15 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, June 15, 2023 7:54:22 PM MDT Jonathan M Davis via Digitalmars-d-
learn wrote:
> On Thursday, June 15, 2023 7:18:25 PM MDT zjh via Digitalmars-d-learn wrote:
> > On Friday, 16 June 2023 at 01:00:05 UTC, Steven Schveighoffer
> >
> > wrote:
> > > B b = B.make(); // call factory function
> > >
> > > -Steve
> >
> > Thank you for your tip.
> > If could simplify it a bit more, it would be even better. It's
> > really uncomfortable without `this()`.
>
> The reasons for it have to do with how D in general is set up to require
> that the value of all types be known at compile-time.

This should say that it's set up to require that the _default_ value of all
types be known at compile-time.

- Jonathan M Davis





Re: Dynamic length string array at compile time?

2023-06-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/15/23 9:59 PM, Mark Fisher wrote:

Hi,
So what if I wanted to build the strings within my library but have the 
client append their own data, for example if I want to have declarative 
extensions? Could this be done by using a mixin template to create the 
strings in the client?


Well, as long as it's not *compile time*, but runtime, you can 
definitely do it. Just use shared static constructors.


As far as I know, there's no way to have the compiler build a 
compile-time list of all compiled modules to be used to build such a 
thing. You might be able to do it as a pre-build step.


One thing you could do is have a convention where some "master" module 
that knows all of the important modules to includes passes it to some 
mixin to instantiate.


-Steve


Re: Dynamic length string array at compile time?

2023-06-15 Thread Mark Fisher via Digitalmars-d-learn
On Wednesday, 7 June 2023 at 00:18:54 UTC, Steven Schveighoffer 
wrote:


So for instance, you can do:

```d
immutable string[] strs = mod1.makeStrings() ~ 
mod2.makeStrings() ~ ...;

```

In a centralized place.

-Steve


Hi,
So what if I wanted to build the strings within my library but 
have the client append their own data, for example if I want to 
have declarative extensions? Could this be done by using a mixin 
template to create the strings in the client?


Re: C++'s this() equivalent?

2023-06-15 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, June 15, 2023 7:18:25 PM MDT zjh via Digitalmars-d-learn wrote:
> On Friday, 16 June 2023 at 01:00:05 UTC, Steven Schveighoffer
>
> wrote:
> > B b = B.make(); // call factory function
> >
> > -Steve
>
> Thank you for your tip.
> If could simplify it a bit more, it would be even better. It's
> really uncomfortable without `this()`.

The reasons for it have to do with how D in general is set up to require
that the value of all types be known at compile-time. Types in general use
default initialization rather than default construction. The language then
depends on this for a variety of things. For instance, when you construct a
an array (dynamic or static), it fills in all of the values in the array by
bit-blitting the init value of the element type onto the elements.
Similarly, when you expand the length of a dynamic array, it bit-blits the
init value of the element type onto the new elements. Other language
features such as in and out on function parameters rely on the init value as
well.

For all of that to work, the type's init value must be known at
compile-time, which means that default construction is off the table. For
most things, this is just fine and is quite beneficial. However, it does
make certain things (like RAII) more annoying than they are in C++.

That being said, as has been pointed out, the simple workaround if you want
RAII is to use a factory function. It's a bit of extra typing, since you
have to call a function instead of simply declaring the variable, but the
factory function then works like the constructor would have in C++, and the
destructor does the clean-up like it would have in C++. It just comes with
the downsides of the extra typing and the fact that it's possible to have
variables of that type that did not go through the factory function, because
they were default-initialized with the init value rather than constructed
via the factory function.

To work around that, you can @disable this so that the type doesn't have an
init value, but then it can't be used in any context where the init value
would be required, which can become very annoying.

Unlike structs, classes can have default constructors, but that's because
they sit on the heap, and technically, when you refer to a class type,
you're almost always referring to a class reference rather than to the
object itself. And the class reference has an init value of null, so it can
be used in all of the places where an init value is required, whereas a
class object is never actually used in such a situation.

For RAII, as an alternative to using a factory function on a struct, you can
use a class and then use https://dlang.org/phobos/std_typecons.html#scoped
to ensure that it gets destroyed when it leaves scope.

There are also scope statements for ensuring that something is run when you
exit the scope, but it isn't really RAII, since you'd still have to call the
initialization portion of things separately. E.G.

doSomething();
scope(exit) undoSomething();

It just makes it easier to ensure that what you want to run when the scope
is exited is always run.

So, there are several ways that you could go about trying to get behavior
similar to RAII in C++ even if you can't actually have RAII. Probably the
best method though is to just use a factory function on a struct. Yes, it's
more annoying than proper RAII, but it's a side effect of other benefits
that D gives that C++ does not.

- Jonathan M Davis





Re: C++'s this() equivalent?

2023-06-15 Thread CM via Digitalmars-d-learn

On Friday, 16 June 2023 at 01:18:25 UTC, zjh wrote:
On Friday, 16 June 2023 at 01:00:05 UTC, Steven Schveighoffer 
wrote:

B b = B.make(); // call factory function

-Steve



Thank you for your tip.
If could simplify it a bit more, it would be even better. It's 
really uncomfortable without `this()`.


One could define a static opCall in his aggregate. It's still a 
factory function, but one might prefer the syntax a bit more.


```d
immutable defaultName = "John";

struct Man {
  static auto opCall() {
typeof(this) this_;
this_.name = defaultName;
return this_;
  }

  string name;
}

auto m = Man();
assert(m.name == defaultName);
```

Do note that one cannot simultaneously have a constructor and a 
static opCall, even if their parameters differ.


Re: C++'s this() equivalent?

2023-06-15 Thread zjh via Digitalmars-d-learn
On Friday, 16 June 2023 at 01:00:05 UTC, Steven Schveighoffer 
wrote:

B b = B.make(); // call factory function

-Steve



Thank you for your tip.
If could simplify it a bit more, it would be even better. It's 
really uncomfortable without `this()`.


Re: C++'s this() equivalent?

2023-06-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/15/23 8:52 PM, zjh wrote:

On Friday, 16 June 2023 at 00:35:48 UTC, Steven Schveighoffer wrote:


Instead, you can use factory functions to initialize.



How can `factory functions` be used to achieve effects similar to `'RAII'`?
Thank you.



B b;

becomes

B b = B.make(); // call factory function

All my uses of RAII depend on copy construction and destruction. 
Construction is easy enough because I have to explicitly declare it anyway.


-Steve


Re: C++'s this() equivalent?

2023-06-15 Thread zjh via Digitalmars-d-learn
On Friday, 16 June 2023 at 00:35:48 UTC, Steven Schveighoffer 
wrote:



Instead, you can use factory functions to initialize.


-Steve

How can `factory functions` be used to achieve effects similar to 
`'RAII'`?

Thank you.



Re: C++'s this() equivalent?

2023-06-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/15/23 8:45 PM, zjh wrote:

On Friday, 16 June 2023 at 00:35:48 UTC, Steven Schveighoffer wrote:

But there is no way in D to have e.g.:

```d
B b; // runs a constructor
```




As a `C++` user, it is very terrible to simplify `RAII` without such a 
method. Why must `this()` be disabled? Can't there be a constructor? In 
a constructor, you can complete `some work`. Without it, how can you 
simplify `RAII`?.




D was not originally designed with RAII. That was added later (D1 
structs did not have ctors or dtors).


The benefit of *not* having parameterless constructors is that default 
construction is always defined *and* available at compile time.


What is wrong with using a parameter constructor or factory function? 
What is the feature you are trying to build that you can with C++, but 
not with D?


I'm not saying I agree with the limitation, just want to know more.

-Steve


Re: C++'s this() equivalent?

2023-06-15 Thread zjh via Digitalmars-d-learn
On Friday, 16 June 2023 at 00:35:48 UTC, Steven Schveighoffer 
wrote:

But there is no way in D to have e.g.:

```d
B b; // runs a constructor
```

-Steve



As a `C++` user, it is very terrible to simplify `RAII` without 
such a method. Why must `this()` be disabled? Can't there be a 
constructor? In a constructor, you can complete `some work`. 
Without it, how can you simplify `RAII`?.




Re: C++'s this() equivalent?

2023-06-15 Thread zjh via Digitalmars-d-learn

On Thursday, 15 June 2023 at 21:48:10 UTC, Ali Çehreli wrote:

I have difficulty understanding the question. I think the 
nested structs, extern(C), static members, etc. confuse me. I 
am assuming they are not related to this question.






Ali



I used the `class` to call the` constructor/destructor 
(destroy)`, but after they leave the scope, they do not call 
the`destructor (destroy)`.
`Nested class` is because I want to directly use members of 
`external struct`, but in reality, I cannot access them directly. 
Therefore, I only have to use ` static members`,.

`extern(C)` is to use `BetterC`,.

The purpose is mainly to complete `RAII`, completing one part of 
the work after entering the scope and another part of the work 
after leaving the scope.




Re: C++'s this() equivalent?

2023-06-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/15/23 8:31 PM, zjh wrote:

Because disabled `this()`, the behavior of `this(int i)`is inconsistent 
and cannot achieve similar `RAII` as `C++`. What should I do?




You cannot have parameter-less constructors in D structs. However, 
destruction works the same.


Instead, you can use factory functions to initialize.

But there is no way in D to have e.g.:

```d
B b; // runs a constructor
```

-Steve


Re: C++'s this() equivalent?

2023-06-15 Thread zjh via Digitalmars-d-learn

On Thursday, 15 June 2023 at 21:48:10 UTC, Ali Çehreli wrote:


And this is by design: In D, we rename the type and be done 
with it. In C++, one needs to rename a number of functions as 
well.


Ali



```d
static int e=40;
struct B{
int m;
this(int i){
printf("%i",e);m=i;
}
~this(){
e=m;
printf("%i",e);
}
//After leaving the scope, restore the original value
}
// definition,
// usage
void f(){
B b=e;e=6;
}//e Restore to 40.
```
But I want like follow, but due to the `disable this()`,I can't:
```d
void f(){
B b;e=6;
}
```
Because disabled `this()`, the behavior of `this(int i)`is 
inconsistent and cannot achieve similar `RAII` as `C++`. What 
should I do?




Para que sirve o que son las variables "immutable"?

2023-06-15 Thread Danico via Digitalmars-d-learn
Tengo una duda y es que en la documentacion de std.json hay un 
ejemplo de codigo que por identidicador ponen "immutable", nose 
para que sirve o de que trata. :( alguien me diga porfis :)


Re: C++'s this() equivalent?

2023-06-15 Thread Ali Çehreli via Digitalmars-d-learn

On 6/15/23 08:15, zjh wrote:

> I want `B` to become the following version similar to 'C++'. What should
> I do?

I have difficulty understanding the question. I think the nested 
structs, extern(C), static members, etc. confuse me. I am assuming they 
are not related to this question.


> ```cpp
> struct B{
>  int m;
>  B(){

Do you want to be able to use the name of the user-defined type to mean 
"constructor", "destructor", etc?


If so, no, it's not possible without preprocessing the text potentially 
with a C preprocessor.


And this is by design: In D, we rename the type and be done with it. In 
C++, one needs to rename a number of functions as well.


Ali



Re: Calling C functions that modify a string

2023-06-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/15/23 2:21 PM, bachmeier wrote:

On Thursday, 15 June 2023 at 15:53:57 UTC, Steven Schveighoffer wrote:

On 6/15/23 10:04 AM, Jonathan M Davis wrote:

On Thursday, June 15, 2023 7:18:06 AM MDT Steven Schveighoffer via
Digitalmars-d-learn wrote:

But in general, if you want a mutable character array that's zero
terminated, you need to make a copy with a zero terminator, but type it
as mutable. I'm surprised there isn't a way to do this easily in the
library.


https://dlang.org/phobos/std_utf.html#toUTFz



Oh nice, so `toUTFz!char` should work. Thanks!



Shouldn't it be `toUTFz!(char*)`? That's what I've been using to pass 
strings to C after someone here recommended it.


Yep. I didn't read so good...

-Steve


Re: Calling C functions that modify a string

2023-06-15 Thread bachmeier via Digitalmars-d-learn
On Thursday, 15 June 2023 at 15:53:57 UTC, Steven Schveighoffer 
wrote:

On 6/15/23 10:04 AM, Jonathan M Davis wrote:
On Thursday, June 15, 2023 7:18:06 AM MDT Steven Schveighoffer 
via

Digitalmars-d-learn wrote:
But in general, if you want a mutable character array that's 
zero
terminated, you need to make a copy with a zero terminator, 
but type it
as mutable. I'm surprised there isn't a way to do this easily 
in the

library.


https://dlang.org/phobos/std_utf.html#toUTFz



Oh nice, so `toUTFz!char` should work. Thanks!

-Steve


Shouldn't it be `toUTFz!(char*)`? That's what I've been using to 
pass strings to C after someone here recommended it.


Re: Calling C functions that modify a string

2023-06-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/15/23 10:04 AM, Jonathan M Davis wrote:

On Thursday, June 15, 2023 7:18:06 AM MDT Steven Schveighoffer via
Digitalmars-d-learn wrote:

But in general, if you want a mutable character array that's zero
terminated, you need to make a copy with a zero terminator, but type it
as mutable. I'm surprised there isn't a way to do this easily in the
library.


https://dlang.org/phobos/std_utf.html#toUTFz



Oh nice, so `toUTFz!char` should work. Thanks!

-Steve



Re: Parser

2023-06-15 Thread Ben Jones via Digitalmars-d-learn

On Wednesday, 14 June 2023 at 09:28:57 UTC, Cecil Ward wrote:
I’m thinking that I might had to end up writing a partial, 
rather rough parser for parts of the D language. Could I get 
some suggestions for help that I might find in the way of 
software components? D has a very powerful regex module, I 
believe.


A couple of pointers for general parsers:

The Pegged library: 
https://github.com/PhilippeSigaud/Pegged/tree/master is pretty 
popular for building general parsers


I have a rough implementation a similar idea here: 
https://github.com/benjones/autoparsed (definitely less polished 
and probably buggier than pegged).  In mine you annotate your 
types with their syntax and can then call parse!MyType on a token 
stream to get a MyType.


C++'s this() equivalent?

2023-06-15 Thread zjh via Digitalmars-d-learn

```d
import core.stdc.stdio;

struct A{
static int e=40;
struct B{
int m;
this(int i){
printf("%i",e);m=i;
}
~this(){
e=m;
printf("%i",e);
}
}
void f(){
B b=e;e=6;
}
void g(){
printf("%i",e);
}
}

extern(C)void main(){
A a;
a.f();
a.g();
}
```
I want `B` to become the following version similar to 'C++'. What 
should I do?

```cpp
struct B{
int m;
B(){
printf("%i",e);m=e;
}
~B(){
e=m;
printf("%i",e);
}
}

```
Thank you.



Re: Calling C functions that modify a string

2023-06-15 Thread Jonathan M Davis via Digitalmars-d-learn
On Thursday, June 15, 2023 7:18:06 AM MDT Steven Schveighoffer via 
Digitalmars-d-learn wrote:
> But in general, if you want a mutable character array that's zero
> terminated, you need to make a copy with a zero terminator, but type it
> as mutable. I'm surprised there isn't a way to do this easily in the
> library.

https://dlang.org/phobos/std_utf.html#toUTFz

- Jonathan M Davis





Re: Calling C functions that modify a string

2023-06-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/15/23 9:18 AM, Steven Schveighoffer wrote:
So interestingly enough, toStringz is pure, and returns an unrelated 
type, so you shouldn't need to cast. However, for some reason, it does 
require a cast. That seems like a bug to me.


Oh wait, a pure function can return immutable data that isn't allocated 
on the heap. Nevermind.


-Steve


Re: Calling C functions that modify a string

2023-06-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/14/23 11:29 PM, Pat Maddox wrote:
Hi there, I want to call a C function that upcases a string. I have 
something working, I just want to check in here to see if there's a 
better approach that I'm missing. I ask because `std.string.toStringZ()` 
returns an `immutable char *`.


As far as I can tell, I have two options:

1. Make the extern definition accept immutable.
2. Cast to `char *`.

I opted for 2 because it seems that 1 would be confusing - the 
definition says immutable, but it mutates the string.


Anyway, is this the D way to mutate a string from C, or is there another 
approach I'm unaware of?


```
extern (C) void upcase(char *);

import std.stdio;
import std.string;

void main() {
   auto s = "hello d";
   auto cs = cast (char *) std.string.toStringz(s);
   upcase(cs);
   writeln(std.string.fromStringz(cs));
}
```


So interestingly enough, toStringz is pure, and returns an unrelated 
type, so you shouldn't need to cast. However, for some reason, it does 
require a cast. That seems like a bug to me.




It also works with:

```
extern (C) void upcase(immutable char *);

import std.stdio;
import std.string;

void main() {
   auto s = "hello d";
   auto cs = std.string.toStringz(s);
   upcase(cs);
   writeln(std.string.fromStringz(cs));
}
```

but it seems that "immutable" is a lie in that case


Yeah, don't do it this way. just matching the type for a C prototype is 
very dangerous, especially if the C function doesn't obey the type 
constraints.


Can I ask if this is a specific case of trying to use a C function to do 
"upper casing", or if this is a general question about C functions and 
modifying strings?


Because we do have upper-casing facilities in both std.ascii and std.uni.

But in general, if you want a mutable character array that's zero 
terminated, you need to make a copy with a zero terminator, but type it 
as mutable. I'm surprised there isn't a way to do this easily in the 
library.


But if you need something that isn't wasteful, I would do something like 
this:


```d
pure char *toMutStringz(const(char)[] str)
{
   char[] result = str ~ "\0";
   return result.ptr;
}
```

-Steve