Re: Can static variables in methods be local for each object?

2021-07-20 Thread bauss via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 15:59:30 UTC, Dukc wrote:

On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:
Is there a way to make myvar local to each instance of `X` 
without making it a variable of `X`? Just curious.


Yes.

```d
import std.stdio;

class X {
int x(int param) {
static int[typeof(this)] myvar;

if (param == 0) return myvar.get(this, 1234);
else return myvar[this] = param;
}

}

void main()
{
X x1 = new X;
X x2 = new X;

x1.x(0).writeln; //1234
x2.x(0).writeln; //1234

x1.x(17).writeln; //17
x2.x(0).writeln; //1234

x1.x(0).writeln; //17
x2.x(0).writeln; //1234
}
```

However, this is definitely not recommended. When you are 
calling a function with any particular object and argument set, 
you want it to do the same thing and return the same result, 
regardless of what's called before. Otherwise you're making 
debugging much more difficult than it needs to be.


This means that `static` variables should generally be used 
only for two things:
1: data that is only set at the beginning of the program, or at 
first use, and then left to the initial value.
2: caching results of expensive computation. Even this is a bit 
controversal, as it's easy to screw up - often it's just better 
to split the function in two, and let the caller to cache the 
results.


In this case, consider passing `myvar` explicitly:

```d
import std.stdio;

class X {
int x(int param, ref int[typeof(this)] myvar) {
if (param == 0) return myvar.get(this, 1234);
else return myvar[this] = param;
}

}

void main()
{
X x1 = new X;
X x2 = new X;
int[X] myvar;

x1.x(17, myvar).writeln; //17
x2.x(0, myvar).writeln; //1234

x1.x(0, myvar).writeln; //17
x2.x(0, myvar).writeln; //1234

myvar = null; //Forget all calls made so far
x1.x(0, myvar).writeln; //1234
x2.x(0, myvar).writeln; //1234
}
```


Wait, that's not too shabby to use the this pointer for a key to 
an AA.


It isn't really a single static variable however, but rather an 
AA that contains the static variables.


Re: How to parse a json node that contains children of different types?

2021-07-20 Thread Bagomot via Digitalmars-d-learn

On Wednesday, 21 July 2021 at 03:00:51 UTC, Mathias LANG wrote:
TL;DR: If you want to use loosely typed data in a strongly 
typed language, you need to come up with a common type. That 
common type is usually either a discriminated union (which a 
JSON object is, essentially) or something that is 
domain-specific.


Hope this helps. I had a quick look at asdf and couldn't see a 
support for tagged union, so you would probably need to provide 
your data structure with a `deserializeFromAsdf` method. If you 
want to do so, look into providing a wrapper to `SumType`, e.g.:


```
struct MyUnion (T...) {
SumType!T data;
alias data this;
SerdeException deserializeFromAsdf(Asdf data) { /* Fill in 
the SumType */ }

```

But I would recommend just using the JSON object if you can.


Thank you! From your answer, I realized that in fact, I would 
rather do the parsing of these arguments myself.


Before using asdf, I tried to do the same with the standard 
std.json. The problem is the same there. I agree that this is 
logical for D.


I was also interested in SumType, I will try to do something with 
it for experience.


Re: How to Fix Weird Build Failure with "-release" but OK with "-debug"?

2021-07-20 Thread Mathias LANG via Digitalmars-d-learn

On Wednesday, 21 July 2021 at 03:25:03 UTC, apz28 wrote:

with below error message:
..\..\pham\db\db_skdatabase.d(140): Error: null dereference in 
function 
_D4pham2db10fbdatabase7FbArray__T13readArrayImplTbZQsMFNfCQCeQCc8database12DbNameColumnZAb
..\..\pham\db\db_skdatabase.d(139): Error: null dereference in 
function 
_D4pham2db10fbdatabase7FbArray__T13readArrayImplTbZQsMFNfCQCeQCc8database12DbNameColumnZAb
Error: null dereference in function 
_D4pham2db10fbdatabase7FbArray__T13readArrayImplTbZQsMFNfCQCeQCc8database12DbNameColumnZAb
..\..\pham\db\db_skdatabase.d(138): Error: null dereference in 
function 
_D4pham2db10fbdatabase7FbArray__T13readArrayImplTbZQsMFNfCQCeQCc8database12DbNameColumnZAb


It seems the compiler is doing extra analysis and seeing that a 
null pointer is being dereferenced. Can you provide the code for 
"pham\db\db_skdatabase.d" at L138 through 140 ?


Re: Not allowed to globally overload operators?

2021-07-20 Thread Tejas via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 18:32:26 UTC, Ali Çehreli wrote:

On 7/19/21 11:20 PM, Tejas wrote:

> trying to create the spaceship operator of C++

Just to make sure, D's opCmp returns an int. That new C++ 
operator was added to provide the same semantics.


Ali


I know. As I already mentioned,  I just wanted the ```<=>``` 
symbol :(


How to Fix Weird Build Failure with "-release" but OK with "-debug"?

2021-07-20 Thread apz28 via Digitalmars-d-learn

VisualD project - Any hint to work around

DMD version:
DMD32 D Compiler v2.096.0-rc.1-dirty
Copyright (C) 1999-2021 by The D Language Foundation, All Rights 
Reserved written by Walter Bright


Failed Build Command line:
dmd -release -m32mscoff -O -inline -dip25 -dip1000 
-preview=fixAliasThis -X -Xf"Win32\Release\db_library.json" -c 
-of"Win32\Release\db_library.obj" 
@Win32\Release\db_library.build.rsp


with below error message:
..\..\pham\db\db_skdatabase.d(140): Error: null dereference in 
function 
_D4pham2db10fbdatabase7FbArray__T13readArrayImplTbZQsMFNfCQCeQCc8database12DbNameColumnZAb
..\..\pham\db\db_skdatabase.d(139): Error: null dereference in 
function 
_D4pham2db10fbdatabase7FbArray__T13readArrayImplTbZQsMFNfCQCeQCc8database12DbNameColumnZAb
Error: null dereference in function 
_D4pham2db10fbdatabase7FbArray__T13readArrayImplTbZQsMFNfCQCeQCc8database12DbNameColumnZAb
..\..\pham\db\db_skdatabase.d(138): Error: null dereference in 
function 
_D4pham2db10fbdatabase7FbArray__T13readArrayImplTbZQsMFNfCQCeQCc8database12DbNameColumnZAb







Re: How to parse a json node that contains children of different types?

2021-07-20 Thread Mathias LANG via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 21:18:12 UTC, Bagomot wrote:


But there is a problem with different types. I understand that 
Object[] is not suitable here, but I don’t know how to do it.


I ask you to help me with this.


IIUC, the `arguments` are command line arguments passed to a Java 
program, and some of those might be passed to the JVM ?


So you probably will end up with something like:
```
struct Arguments{
JVMArgs jvm;
ProgramArgs program;
}
```

Of course, the question is, what's `JVMArgs` ?

Now, as you noticed, you can't represent an array of unrelated 
types in D (which makes sense). So what you can do is create a 
common type for it, by using an `union`.


```
union JVMArg
{
RuleValue ruleValue;
string str;
// Etc...
}
alias JVMArgs = JVMArg[];
```

However, \ might not support it directly, or 
might support it through its own type (you will need a tagged 
union, and not just a simple union, as you need to know the type 
that the library read).


But if you take a step back, I think you might find this solution 
is far from ideal.
Having worked on a JSON library myself, I can tell you they are 
all implemented with a tagged union. And converting a tagged 
union to a tagged union is no improvement.


Instead, I would recommend to just use the JSON directly. If you 
need to pass things around, you might want to deserialize it to a 
common format. For example, assuming your project is a process 
manager for Java program and you want to read a common set of 
arguments from a configuration file, you might want to just 
generate the strings:

```
auto myJSON = parseConfigFile("config.json");
string[] defaultJVMArgs = parseJVMArgs(myJSON);
auto processMonitor = new ProcessMonitor(defaultJVMArgs);
```

TL;DR: If you want to use loosely typed data in a strongly typed 
language, you need to come up with a common type. That common 
type is usually either a discriminated union (which a JSON object 
is, essentially) or something that is domain-specific.


Hope this helps. I had a quick look at asdf and couldn't see a 
support for tagged union, so you would probably need to provide 
your data structure with a `deserializeFromAsdf` method. If you 
want to do so, look into providing a wrapper to `SumType`, e.g.:


```
struct MyUnion (T...) {
SumType!T data;
alias data this;
SerdeException deserializeFromAsdf(Asdf data) { /* Fill in 
the SumType */ }

```

But I would recommend just using the JSON object if you can.


How to parse a json node that contains children of different types?

2021-07-20 Thread Bagomot via Digitalmars-d-learn

I have a json like this:

```json
{
   "arguments":{
  "jvm":[
 {
"rules":[
   {
  "action":"allow",
  "os":{
 "name":"osx"
  }
   }
],
"value":[
   "-XstartOnFirstThread"
]
 },
 "-Djava.library.path=${natives_directory}"
  ]
   }
}
```
Here the "jvm" node is an array that has different data types for 
its elements (json object and string).


I am using [asdf](https://code.dlang.org/packages/asdf) library 
to deserialize json. I am trying to deserialize this json into a 
structure like this:

```d
struct Arguments{
@serdeKeys("jvm")
Object[] jvm;
}
```
But there is a problem with different types. I understand that 
Object[] is not suitable here, but I don’t know how to do it.


I ask you to help me with this.


Re: Not allowed to globally overload operators?

2021-07-20 Thread Ali Çehreli via Digitalmars-d-learn

On 7/20/21 11:49 AM, H. S. Teoh wrote:

> On Tue, Jul 20, 2021 at 11:32:26AM -0700, Ali Çehreli via 
Digitalmars-d-learn wrote:

>> On 7/19/21 11:20 PM, Tejas wrote:
>>
>>> trying to create the spaceship operator of C++
>>
>> Just to make sure, D's opCmp returns an int. That new C++ operator was
>> added to provide the same semantics.
> [...]
>
> FYI, opCmp *may* return float, which may be useful sometimes for
> implementing partial orders (return float.nan when two elements are
> incomparable).

Thanks. For that matter, opCmp can return a UDT (and bool as well as 
demonstarted below) but then the UDT cannot know what to do in its opCmp: :)


import std.stdio;

void main() {
  S a, b;
  auto result = a < b;
  // The operator above is reduced to the following:
  //
  //   a.opCmp(b) < 0;
  //
  // (It would be 'a.opCmp(b) >= 0' if we used the >= operator, etc.)
  //
  // But because the result of opCmp is an O object in this code
  // (let's call it 'o'), the reduction is applied to 'o < 0' as well:
  //
  //   o.opCmp(0);
  //
  // where, O.opCmp will receive a 0 'int' value but will never know
  // operator context we are in. (<, >=, etc.)
}

struct S {
  // Weirdly returns an O.
  O opCmp(const S that) {
return O();
  }
}

struct O {
  bool opCmp(int result) {
// result will always be '0' in the case of reduction because it
// will be the 0 used in code reduction by dmd.

// We might be able to do something here but we don't know the
// operator context. Are we inside <, >=, etc?

// Extra credit: This is similar to being able to return float.nan
// but I can't decipher the semantics at this time. :)
return true;
  }
}

Ali




Re: Not allowed to globally overload operators?

2021-07-20 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 18:49:07 UTC, H. S. Teoh wrote:
On Tue, Jul 20, 2021 at 11:32:26AM -0700, Ali Çehreli via 
Digitalmars-d-learn wrote:

On 7/19/21 11:20 PM, Tejas wrote:

> trying to create the spaceship operator of C++

Just to make sure, D's opCmp returns an int. That new C++ 
operator was added to provide the same semantics.

[...]

FYI, opCmp *may* return float, which may be useful sometimes 
for implementing partial orders (return float.nan when two 
elements are incomparable).


To be precise about it: `opCmp` must return a value that can be 
compared with `0` using `<` and `>`. Any integer or 
floating-point type will satisfy this requirement.


Re: Not allowed to globally overload operators?

2021-07-20 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jul 20, 2021 at 11:32:26AM -0700, Ali Çehreli via Digitalmars-d-learn 
wrote:
> On 7/19/21 11:20 PM, Tejas wrote:
> 
> > trying to create the spaceship operator of C++
> 
> Just to make sure, D's opCmp returns an int. That new C++ operator was
> added to provide the same semantics.
[...]

FYI, opCmp *may* return float, which may be useful sometimes for
implementing partial orders (return float.nan when two elements are
incomparable).


T

-- 
"Outlook not so good." That magic 8-ball knows everything! I'll ask about 
Exchange Server next. -- (Stolen from the net)


Re: Not allowed to globally overload operators?

2021-07-20 Thread Ali Çehreli via Digitalmars-d-learn

On 7/19/21 11:20 PM, Tejas wrote:

> trying to create the spaceship operator of C++

Just to make sure, D's opCmp returns an int. That new C++ operator was 
added to provide the same semantics.


Ali



Re: Can static variables in methods be local for each object?

2021-07-20 Thread Dukc via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:
Is there a way to make myvar local to each instance of `X` 
without making it a variable of `X`? Just curious.


Yes.

```d
import std.stdio;

class X {
int x(int param) {
static int[typeof(this)] myvar;

if (param == 0) return myvar.get(this, 1234);
else return myvar[this] = param;
}

}

void main()
{
X x1 = new X;
X x2 = new X;

x1.x(0).writeln; //1234
x2.x(0).writeln; //1234

x1.x(17).writeln; //17
x2.x(0).writeln; //1234

x1.x(0).writeln; //17
x2.x(0).writeln; //1234
}
```

However, this is definitely not recommended. When you are calling 
a function with any particular object and argument set, you want 
it to do the same thing and return the same result, regardless of 
what's called before. Otherwise you're making debugging much more 
difficult than it needs to be.


This means that `static` variables should generally be used only 
for two things:
1: data that is only set at the beginning of the program, or at 
first use, and then left to the initial value.
2: caching results of expensive computation. Even this is a bit 
controversal, as it's easy to screw up - often it's just better 
to split the function in two, and let the caller to cache the 
results.


In this case, consider passing `myvar` explicitly:

```d
import std.stdio;

class X {
int x(int param, ref int[typeof(this)] myvar) {
if (param == 0) return myvar.get(this, 1234);
else return myvar[this] = param;
}

}

void main()
{
X x1 = new X;
X x2 = new X;
int[X] myvar;

x1.x(17, myvar).writeln; //17
x2.x(0, myvar).writeln; //1234

x1.x(0, myvar).writeln; //17
x2.x(0, myvar).writeln; //1234

myvar = null; //Forget all calls made so far
x1.x(0, myvar).writeln; //1234
x2.x(0, myvar).writeln; //1234
}
```


Re: Can static variables in methods be local for each object?

2021-07-20 Thread bauss via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:

Let's say I have this code:
```d
import std.stdio;

class X {

int x(int param) {
static int myvar = 1234;

if (param == 0) return myvar;
else { myvar = param; return myvar; }
}

}

void main()
{
X x1 = new X;
X x2 = new X;

x1.x(0).writeln;
x2.x(0).writeln;

x1.x(17).writeln;
x2.x(0).writeln;
}
```

Is there a way to make myvar local to each instance of `X` 
without making it a variable of `X`? Just curious.


The only way I can think of is something like this:

```
import std.stdio;

interface X
{
int x(int param);
}

class XImpl(size_t n = 0) : X {
int x(int param) {
static int myvar = 1234;

if (param == 0) return myvar;
else { myvar = param; return myvar; }
}

}

void main()
{
X x1 = new XImpl!1;
X x2 = new XImpl!2;

x1.x(0).writeln;
x2.x(0).writeln;

x1.x(17).writeln;
x2.x(0).writeln;
}
```

Of course it's not entirely what you want but yeah I think that's 
about the closest to a solution that isn't overcomplicated.


Re: Can static variables in methods be local for each object?

2021-07-20 Thread Mark Lagodych via Digitalmars-d-learn

On Tuesday, 20 July 2021 at 09:24:07 UTC, Mark Lagodych wrote:

```d
void main()
{
X x1 = new X;
X x2 = new X;

x1.x(0).writeln;
x2.x(0).writeln;

x1.x(17).writeln;
x2.x(0).writeln;
}
```


Ow, sorry, I forgot to say. It prints:
```
1234
1234
17
17
```



Can static variables in methods be local for each object?

2021-07-20 Thread Mark Lagodych via Digitalmars-d-learn

Let's say I have this code:
```d
import std.stdio;

class X {

int x(int param) {
static int myvar = 1234;

if (param == 0) return myvar;
else { myvar = param; return myvar; }
}

}

void main()
{
X x1 = new X;
X x2 = new X;

x1.x(0).writeln;
x2.x(0).writeln;

x1.x(17).writeln;
x2.x(0).writeln;
}
```

Is there a way to make myvar local to each instance of `X` 
without making it a variable of `X`? Just curious.