Re: impure

2024-04-08 Thread Dom DiSc via Digitalmars-d-learn

On Monday, 8 April 2024 at 07:03:40 UTC, Alexandru Ermicioi wrote:

On Sunday, 24 March 2024 at 07:41:41 UTC, Dom DiSc wrote:
I'm creating a library that is completely pure, but it doesn't 
compile with pure: at the top because of one impure unittest 
(which uses random to  test some things only probabilistic)!


So do I really need to declare every function pure 
individually because of a test?!?


Can we please have a @impure attribute?
And by the way also @throws and @gc?
That would make live so much easier...


Try `debug unittest {...}`?


Cool. This seems to work. That's a nice workaroud for tests. Yay!


Re: impure

2024-04-08 Thread Dom DiSc via Digitalmars-d-learn

On Sunday, 7 April 2024 at 23:32:24 UTC, MrJay wrote:
A better way to apply a attribute to an entire file is to use 
an explicit scope you can still apply this to basically the 
entire file but leave the tests out of it.


Better than an explicit impure (or pure=false) attribute?
I don't think so. It heavily uglyfies the file, as single items 
without a specific attribute are interspersed in the file. So the 
scope need to end before and start again after the affected 
function or test.


An it stops working at all if e.g. one test is impure and another 
test is @gc, because then the scopes overlap and can no more be 
contained in each other.


Really, having the counter-attributes would improve the language.


Re: impure

2024-04-05 Thread Dom DiSc via Digitalmars-d-learn

On Sunday, 24 March 2024 at 09:16:20 UTC, Jonathan M Davis wrote:
So, yes, you've run into a problem that it would be nice to 
have a better fix for, but even if we could negate attributes 
in general, there are good reasons to prefer to avoid 
mass-applying attributes.


I don't see it as "mass-applying attributes" rather than changing 
the default to something more sane, so that I have to apply 
*less* attributes to any single function.


If the addition of new keywords (like "throws", "@gc" and 
"impure") is a problem, why not doing it like @nogc(false) or 
@nogc=false (likewise for nothrow and pure)?


Re: real.sizeof

2024-02-05 Thread Dom DiSc via Digitalmars-d-learn

On Monday, 5 February 2024 at 17:28:38 UTC, Iain Buclaw wrote:


Padding.

x86 ABI prefers things to be aligned, so on x86 it's 12 bytes, 
x86_64 16 bytes.  In both cases you don't get any extra 
precision over the 80-bits that x87 gives you.


This is exactly what I mean. The ABI may pad it, but sizeof 
should still give the number of bytes that are really used (not 
counting the gaps).

Or is there a way to change the alignment of basic types?

In my code I wanted do decide if the processor uses 
double-extended or quadruple as real depending on the sizeof.
But now I learned I cannot rely on this. Fortunately there is 
mant_dig, which gives the correct info.


At least in an array of real I would expect no padding, like in 
an array of bool (except for odd length).


Re: struct initializer

2023-12-01 Thread Dom DiSc via Digitalmars-d-learn

On Thursday, 30 November 2023 at 12:15:04 UTC, Dennis wrote:
The syntax was inherited from C. The 'special place' is called 
initialization, and it's special because the target type of the 
initializer is known in advance


This is no different from `S fun(){ return { 5, 2 }; }` It 
creates a new instance of a struct, and the type is known in 
advance (it's the return type). So it's not an expression. But 
this place of initialization is not allowed. Therefor I think 
calling  `S s = { 5, 2 };` 'special' is justified.




Re: struct initializer

2023-12-01 Thread Dom DiSc via Digitalmars-d-learn

On Thursday, 30 November 2023 at 14:10:35 UTC, zjh wrote:

On Wednesday, 29 November 2023 at 16:38:36 UTC, Dom DiSc wrote:

```d

struct S { int a; int b; }
S2 fun3() { return S2( 5, 2 ); }

```

Here,`S2( 5, 2 );` violeit `DRY` principle.


Yes. I think if we have the brackets form, it should be allowed 
here:


```d
S Fun(){ return { 5, 2 }; }
```

This IS an initialization and the type is known. Requiring the 
repetition of the type is also here annoying.
So it is not a syntax reserved for initialization, but only for 
initialization with equals operator. I think this is inconsequent.
Either allow it for all initializations, or get rid of it, like 
DIP 1031 suggested.




Re: struct initializer

2023-11-29 Thread Dom DiSc via Digitalmars-d-learn

On Wednesday, 29 November 2023 at 16:48:09 UTC, Paul Backus wrote:

You can use this syntax without an explicit constructor:

struct S3 { int a; int b; }

S3 fun() { return S3(5, 2); }

The language spec calls this a struct literal


Ok, so we have

```d
struct S { int a; int b; }

S s = S(5, 3); // works
s = S(6, 2); // works
S fun() { return S(5, 2); } // works
int fun2(S s2);
fun2(S(4,4)); // works
```

but

```d
struct S { int a; int b; }

S s = { 5, 3 }; // works
s = { 6, 2 }; // doesn't work
S fun() { return { 5, 2 }; } // doesn't work
int fun2(S s2);
fun2(S(4,4)); // doesn't work
```

So, why supporting the (somewhat strange looking) version with 
curly backets at all?
It only works in one special place, so is simply overhead to 
remember.
Again a superfluous way to do the same - but only under specific 
circumstances.


I think a syntax should work either always or never.


Re: struct initializer

2023-11-29 Thread Dom DiSc via Digitalmars-d-learn

Sorry, I meant

```d
fun2({4, 4}); // doesn't work
```




struct initializer

2023-11-29 Thread Dom DiSc via Digitalmars-d-learn

```d
struct S { int a; int b; }

S s = { 5, 2 }; // works fine

S fun() { return { 5, 2 }; } // doesn't work :-(

S fun2() { S s = { 5, 2 }; return s; } // works but is ugly

struct S2 { int a; int b; this(int c, int d) { a=c; b=d; } }

S2 fun3() { return S2( 5, 2 ); } // works but requires explicit 
constructor

```

Is there a reason why the short form is not possible?
It's clearly an initialization of a new instance of a struct, and 
the requested type is unambigous (the return type of the 
function).


Re: interface inference

2023-11-28 Thread Dom DiSc via Digitalmars-d-learn

On Tuesday, 28 November 2023 at 11:01:14 UTC, Antonio wrote:

```d
I aOrB(bool check){
  if(check)
return new A();
  else
return new B();
}
```

**Is it the expected behaviour for ternary conditional?**


Here the compiler knows what type to return (from the function 
signature).
But the ternary operator doesn't know this, so its arguments need 
to be of the same type (or implicitly convert to a common type).


Re: D: Convert/parse uint integer to string. (@nogc)

2023-11-28 Thread Dom DiSc via Digitalmars-d-learn

On Tuesday, 28 November 2023 at 08:51:21 UTC, Mark Davies wrote:

On Friday, 24 November 2023 at 09:35:00 UTC, BoQsc wrote:
```
import std.stdio;

char[10] longToString(long n) @nogc
```


For a 'long' 10 characters is likely to be not enough (long max 
is 9223372036854775808 which has 19 chars, and you should reserve 
additional one for the sign and one for the terminating null), so 
I would at least recommend using char[21].


with char[10] your function becomes a big hole in your security, 
as it can easily be misused to write 10 bytes of freely 
selectable garbage behind your allocated memory.


But as you want to avoid the gc, security might not be a goal for 
you, so continue living in the 1970's.


Re: How does D’s ‘import’ work?

2023-06-03 Thread Dom DiSc via Digitalmars-d-learn

On Thursday, 1 June 2023 at 03:47:00 UTC, Cecil Ward wrote:
I have another question if I may, what do we do about getting 
makefiles right given that we have imports ?


You can replace your whole makefile by calling the compiler with 
-I (not always, but if you don't do funny things in your 
makefile).
- This ability of the D compiler was just recently discovered 
(after -I was implemented for other reasons), but it relies on 
the fact that we have imports.


Re: static immutable that has no initialiser - should this raise an error?

2023-05-31 Thread Dom DiSc via Digitalmars-d-learn

On Tuesday, 30 May 2023 at 04:11:00 UTC, Cecil Ward wrote:

static immutable T foo;

T bar() {
return foo;
}

Should we get an error from the D compiler here as the 
initialiser has been forgotten? What do you think ?

No.
There are no un-initialized values in D.
It gets its default value, if no explicit value is given.
That's intended, not an error.
If you need an un-initialized value, set it =void.
Of course, for immutable values that makes no sense at all.
But I think, this already gives you an error.



Re: Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-31 Thread Dom DiSc via Digitalmars-d-learn

On Wednesday, 31 May 2023 at 03:29:33 UTC, Cecil Ward wrote:
I have to admit that I don’t really understand immutable. I 
have an idea that it could mean that an object has an address 
in ROM, so its value will never change. Maybe const doesn’t 
give you such a strong guarantee, disallows ‘you’ from 
modifying it but others might do so, but who knows.
There are two perspectives: that of the value handed to a 
function and that of the function taking the value.
"immutable" (or "mutable") is a property of the value, "const" is 
a property of the function.
If the function can work with mutable values, but in fact doesn't 
mutate them itself, it could also work with immutable values. The 
fact that others could modify your "const" value doesn't matter 
for immutable values, because they of course can't be modified by 
others. For the function it doesn't matter, because it only 
guarantees not to modify it itself, don't care about what other 
can or can't do.



Without a guarantee as strong as the first idea I can’t really
understand how const can work properly. "You treat it as const
so do not modify it, but it might not be eternally fixed and
unchanging" that doesn’t seem to have enough value to me.

Why? What guarantee are you missing?
Your function can work with mutable data, so you don't care if it 
can be modified also by others.
Now it happens that you doesn't modify the data. So why shouldn't 
you be able to work on data that guarantees that it also will not 
be changed by others? You don't care for such modification anyway.


The meaning of "immutable" is: I cannot be modified. Not by you 
and not by anybody else. It's a property of a value.
The meaning of "mutable" is: I can be modified by anybody. Work 
with me only if that is ok for you. It's a property of a value.
The meaning of "const" is: I don't care if others modify the data 
or not, I won't modify it myself. It's a property of a function.




Re: Concepts like c++20 with specialized overload resolution.

2023-05-28 Thread Dom DiSc via Digitalmars-d-learn

On Saturday, 27 May 2023 at 19:16:18 UTC, vushu wrote:
It depends. This example is quite small and a `static if` is 
sufficient, if you have a lot of cases it would make sense to 
split thing up into overloaded functions.


Even with a lot of cases you can simply call in each static if a 
(private) subfunction. I would always prefer this over overloads 
because it gets you a much cleaner API (I consider the constraint 
to be part of the function signature, which therefore can get 
very long and produces a lot of overloads that each only differ 
in the constraints). Also it becomes more and more obfuscated for 
which cases there is an overload and for which not.

A good (?!?) example of how bad this can get is the "to" template.



Re: Proper way to handle "alias this" deprecation for classes

2023-05-17 Thread Dom DiSc via Digitalmars-d-learn

On Friday, 12 May 2023 at 15:00:48 UTC, Salih Dincer wrote:


```d
struct Fraction {
int num, den;

this(int n, int d)
{
num = n;
den = d;
}

// Cast Expression : convert float value of fraction
auto opCast(T : float)() const
{
return cast(float)(num) / cast(float)(den);
}
}
```


If you want auto-conversion, you should be more explicit:
```d
float opCast() { }
```
because if you return "auto" it is not the highest-prio fit and 
therefore not chosen.
If you have multiple choices, you still don't need to use "auto". 
Instead you can return T:

```d
T opCast(T)() if(isFloatingPoint!T)
{
   return cast(T)num / cast(T)den; // float, double or real
}
```
Kind of ironic, but especially "auto" does NOT fit automatically 
:-)


Re: learning D as your first language but having difficulty in making or logic building in order to make software

2023-04-12 Thread Dom DiSc via Digitalmars-d-learn

On Tuesday, 11 April 2023 at 14:13:17 UTC, slectr wrote:
I want  to make software like krita inkscape and my own 
language using D


Although i previosly learned C and C++ i left it in the middle 
and for some reasons i dont want to learn those so i searched 
for alternatives and found D but there are not a lot of 
resources like cookbooks and videos as compared to C or C++ 
does anybody know any resources for making complex software in 
D for some practise


? Of course there are cookbooks - one even has explicitly that 
title!

Have a look on forum.dlang.org under Resources/Books.



Re: How to use @safe when a C library integration needed

2023-01-23 Thread Dom DiSc via Digitalmars-d-learn

On Monday, 23 January 2023 at 16:36:21 UTC, Leonardo wrote:

Hello. How to use @safe when a C library integration needed?

Everything need a system function...


```d
@safe fn()
{
   // lot of safe stuff

   () @trusted {
   // in this block[*] @system function like extern C can be 
called.

   // you need to make sure the API is used correct
   @assert(/*C_Fun is safe to be used with param1*/);
   @assert(/*C_Fun is safe to be used with param2*/);
   C_Fun(param1, param2);
   }();

   // more safe stuff

}
```

[*] in fact, this is a lambda function that is directly called, 
because real trusted blocks are not allowed (yet).


Re: Is there a way to enforce UFCS?

2023-01-05 Thread Dom DiSc via Digitalmars-d-learn

On Wednesday, 4 January 2023 at 14:21:46 UTC, bauss wrote:

```d
class Foo {
  int bar;

  void setBar(Foo foo, int value) {
foo.bar = value;
  }
}

void main() {
  foo.setBar(100); // Not UFCS - just method call to the class
  foo.setBar = 100; // Not UFCS - simply a setter function call 
(equal to the above)

  setBar(foo, 100); // Error
}
```


I think this is really another usecase for @property: we should 
forbid the function call syntax for them (so one needs to use 
them like a variable).
This is useful to enable library authors to enforce this, so that 
if a property is replaced by a variable (e.g. during 
refactoring), it's not a braking change for the users of the 
library.
Else it could be that setters or getters are directly called, 
which would not compile anymore with a variable (that doesn't 
have getters or setters).


@properties are intended to be used like variables - the only 
differences (and the reason why they exist) is the read or write 
protection they provide, and that they may be calculated on the 
fly (not stored in memory at all). That they are realized with a 
construct that looks similar to (a pair of) functions should be 
completely transparent for the user of a library.


Properties are not functions. If you want a function, use a 
function. If @properties would be the same as functions, they are 
superfluous garbage. Either make something useful out of them or 
remove them.




Re: Fix template parameter

2022-08-10 Thread Dom Disc via Digitalmars-d-learn

On Tuesday, 9 August 2022 at 22:58:16 UTC, Paul Backus wrote:

On Tuesday, 9 August 2022 at 22:36:23 UTC, Dom Disc wrote:

On Tuesday, 9 August 2022 at 22:32:23 UTC, Dom Disc wrote:

On Tuesday, 9 August 2022 at 21:16:22 UTC, Paul Backus wrote:
Yes, this syntax allows anything that implicitly converts to 
`BigInt`;


Oh, or do you mean I will get two different instances of the 
template, if I call it with two different types with implicit 
conversion?
That would make it even worse than the non-templated 
declaration!


Yes, exactly.


Ok, then I consider this is a bug in Phobos that should be 
corrected.


All instances of

```D
foo(T : fixedType)(T x) { }
```
should be replaced by

```D
foo(fixedType x) { }
```



Re: Fix template parameter

2022-08-09 Thread Dom Disc via Digitalmars-d-learn

On Tuesday, 9 August 2022 at 22:32:23 UTC, Dom Disc wrote:

On Tuesday, 9 August 2022 at 21:16:22 UTC, Paul Backus wrote:
Yes, this syntax allows anything that implicitly converts to 
`BigInt`;


Oh, or do you mean I will get two different instances of the 
template, if I call it with two different types with implicit 
conversion?

That would make it even worse than the non-templated declaration!


Re: Fix template parameter

2022-08-09 Thread Dom Disc via Digitalmars-d-learn

On Tuesday, 9 August 2022 at 21:16:22 UTC, Paul Backus wrote:
Yes, this syntax allows anything that implicitly converts to 
`BigInt`; for example:


```d
import std.bigint;

void fun(T : BigInt)(T t)
{
pragma(msg, "Instantiated with T = `" ~ T.stringof ~ "`");
}

struct S
{
BigInt n;
alias n this;
}

void main()
{
S s;
fun(s); // Instantiated with T = `S`
}


Aha. But isn't that also true for the other declaration?

```d
void fun(BigInt t) { }
```

will also accept anything that implicitly converts to BigInt, no?
So I still don't see the big difference.
Except that is is a template - for what ever that may be useful 
if it doesn't take more than one type.
Relying on something as subtle as this difference does have a 
code-smell for me.


Re: Fix template parameter

2022-08-08 Thread Dom Disc via Digitalmars-d-learn

On Monday, 8 August 2022 at 12:46:48 UTC, bauss wrote:

On Monday, 8 August 2022 at 12:02:02 UTC, Dom Disc wrote:


```D
pure @nogc @safe BigInt opAssign(T : BigInt)(T x);
```


This will only be included in the object file if used.


```D
pure @nogc @safe BigInt opAssign(BigInt x);
```


This will always be in the object file.


Ah, ok. But shouldn't the linker throw it out of an executable, 
if it is not used?
I mean, even the most dump linker should be able to do this basic 
optimization...


Fix template parameter

2022-08-08 Thread Dom Disc via Digitalmars-d-learn

Hello.
I found in the documentation functions declared like this:

```D
pure @nogc @safe BigInt opAssign(T : BigInt)(T x);
```

What is the difference to declaring it like:

```D
pure @nogc @safe BigInt opAssign(BigInt x);
```

To me the first declaration seems to be unnecessarily bloated, so 
I ask myself: does it provide any kind of advantage? I can't see 
it.




Re: How do I initialize a templated constructor?

2022-08-08 Thread Dom Disc via Digitalmars-d-learn

And then you can instantiate it with

```D
auto val = TestArray!10(ubyte(60)); // if you want type to be 
ubyte

```




Re: How do I initialize a templated constructor?

2022-08-08 Thread Dom Disc via Digitalmars-d-learn

On Monday, 8 August 2022 at 06:58:42 UTC, bauss wrote:

On Monday, 8 August 2022 at 05:38:31 UTC, rempas wrote:

In the following struct (as an example, not real code):

```
struct TestArray(ulong element_n) {
  int[element_n] elements;

  this(string type)(ulong number) {
pragma(msg, "The type is: " ~ typeof(type).stringof);
  }
}
```


You cannot do this.


But if you only want to know the type of the parameter, you can 
do this:


```D
struct TestArray(ulong element_n) {
  int[element_n] elements;

  this(type)(type number)
  {
pragma(msg, "The type is: " ~ type.stringof);
  }
}
```



Re: Verbosity in D

2022-08-07 Thread Dom Disc via Digitalmars-d-learn

On Monday, 8 August 2022 at 00:40:11 UTC, TTK Ciar wrote:
On the other hand, I've noticed that D's idiomatic brevity can 
be diluted by the extremely verbose function names used in the 
standard library.


For long function names you can define short aliases, for syntax 
you can't. So having short and efficient language constructs is 
by far more important than short function names.
Especially a standard-library is much better off having 
descriptive and unique names - which sort of requires them to be 
long.


Re: Arbitrary precision decimal numbers

2022-08-06 Thread Dom Disc via Digitalmars-d-learn

On Saturday, 6 August 2022 at 11:25:28 UTC, Dom Disc wrote:

I once did a completely inline implementation of xlcmplx


Sorry, one function is NOT inline:

```C
class xlcmplx
{
	uint32 Decimal(char* s, uint32 max) const; // string 
representation

}
```
But you should forget about that, because D has much better 
methods to create a string. In fact good enough that also this 
function could have been inline... but in D the whole concept of 
headers is superfluous, so who cares.




Re: Arbitrary precision decimal numbers

2022-08-06 Thread Dom Disc via Digitalmars-d-learn

On Friday, 5 August 2022 at 14:25:39 UTC, Ruby The Roobster wrote:
I'm currently working on an arbitrarily precise division 
algortihm based off of the done-by-hand standard algorithm, but 
I need to get it to work for complex numbers, [which it's just 
not](https://forum.dlang.org/post/czidpbdywsohstyvi...@forum.dlang.org).


I once did a completely inline implementation of xlcmplx based on 
an arbitrary precision float (in this context called xlfloat) in 
C++.

You only need to exchange xlfloat with your floatingpoint type:

```C
class xlcmplx
{
xlfloat Re, Im;
public:
	friend inline void swap(xlcmplx& a, xlcmplx& b) { swap(a.Re, 
b.Re); swap(a.Im, b.Im); }


	xlcmplx(const xlfloat& re =0, const xlfloat& im =0) : Re(re), 
Im(im) { }

xlcmplx(const xlcmplx& c) : Re(c.Re), Im(c.Im) { }
// two special "constructors":
	friend inline xlcmplx i(const xlfloat& x =1) { return 
xlcmplx(0,x); } // make pure imaginary number
	friend inline xlcmplx polar(const xlfloat& arg, const xlfloat& 
norm =1) { return (!norm || !arg) ? norm : 
xlcmplx(cos(arg),sin(arg)) *= norm; }


	uint32 Decimal(char* s, uint32 max) const; // string 
representation


	inline xlcmplx& operator=(const xlcmplx& c) { if(this != ) Re 
= c.Re, Im = c.Im; return *this; }
	inline xlcmplx& operator=(const xlfloat& f) { Re = f, Im = 0; 
return *this; }


inline xlcmplx& operator+() { return *this; } // dummy operator
inline xlcmplx operator-() const { return xlcmplx(-Re, -Im); }
	inline xlcmplx& operator+=(const xlcmplx& c) { Re += c.Re; Im += 
c.Im; return *this; }
	inline xlcmplx& operator+=(const xlfloat& f) { Re += f; return 
*this; }
	inline xlcmplx& operator-=(const xlcmplx& c) { Re -= c.Re; Im -= 
c.Im; return *this; }
	inline xlcmplx& operator-=(const xlfloat& f) { Re -= f; return 
*this; }
	inline xlcmplx& operator*=(const xlcmplx& c) { xlfloat t = Re; t 
*= c.Re; t -= Im*c.Im; Im *= c.Re; Im += Re*c.Im; Re = t; return 
*this; }
	inline xlcmplx& operator*=(const xlfloat& f) { Re *= f; Im *= f; 
return *this; }
	inline xlcmplx& operator/=(const xlcmplx& c) { return *this *= 
inv(c); }
	inline xlcmplx& operator/=(const xlfloat& f) { Re /= f; Im /= f; 
return *this; }


	inline bool operator==(const xlcmplx& c) const { return Im == 
c.Im && Re == c.Re; }
	inline bool operator==(const xlfloat& f) const { return !Im && 
Re == f; }
	inline bool operator!=(const xlcmplx& c) const { return Im != 
c.Im || Re != c.Re; }
	inline bool operator!=(const xlfloat& f) const { return !!Im || 
Re != f; }


	friend inline const xlfloat& real(const xlcmplx& c) { return 
c.Re; }
	friend inline const xlfloat& imag(const xlcmplx& c) { return 
c.Im; }
	friend inline xlfloat norm(const xlcmplx& c) { return c.Im ? 
c.Re ? sqr(quad(c.Re)+quad(c.Im)) : abs(c.Im) : abs(c.Re); }
	friend inline xlfloat arg(const xlcmplx& c) { return atan2(c.Re, 
c.Im); } // an angle in [0..2*pi[


friend inline xlcmplx conj(xlcmplx c) { c.Im.neg(); return c; }
	friend inline xlcmplx inv(const xlcmplx& c) { xlfloat t = 
quad(c.Re); t += quad(c.Im); return conj(c) /= t; }
	friend inline xlcmplx quad(const xlcmplx& c) { return 
xlcmplx(quad(c.Re)-quad(c.Im),(c.Re*c.Im)<<1); }
	friend inline xlcmplx exp(const xlcmplx& c) { return c.Im ? 
xlcmplx(cos(c.Im), sin(c.Im)) *= exp(c.Re) : exp(c.Re); }
	friend inline xlcmplx sin(const xlcmplx& c) { return c.Im ? c.Re 
? xlcmplx(sin(c.Re)*cosh(c.Im), cos(c.Re)*sinh(c.Im)) : 
i(sinh(c.Im)) : sin(c.Re); }
	friend inline xlcmplx cos(const xlcmplx& c) { return c.Im ? c.Re 
? xlcmplx(cos(c.Re)*cosh(c.Im), sin(c.Re)*sinh(c.Im)) : 
cosh(c.Im) : cos(c.Re); }
	friend inline xlcmplx ln(const xlcmplx& c) { return 
xlcmplx(ln(norm(c)), arg(c)); } // main value - multiples of 
2*pi*i added are also valid results

};

inline bool operator==(const xlfloat& f, const xlcmplx& c) { 
return c == f; }
inline bool operator!=(const xlfloat& f, const xlcmplx& c) { 
return c != f; }


inline xlcmplx operator+(xlcmplx a, const xlcmplx& b) { return a 
+= b; }
inline xlcmplx operator+(xlcmplx a, const xlfloat& b) { return a 
+= b; }
inline xlcmplx operator+(const xlfloat& a, xlcmplx b) { return b 
+= a; }
inline xlcmplx operator-(xlcmplx a, const xlcmplx& b) { return a 
-= b; }
inline xlcmplx operator-(xlcmplx a, const xlfloat& b) { return a 
-= b; }
inline xlcmplx operator-(const xlfloat& a, const xlcmplx& b) { 
return -b += a; }
inline xlcmplx operator*(xlcmplx a, const xlfloat& b) { return a 
*= b; }
inline xlcmplx operator*(xlcmplx a, const xlcmplx& b) { return a 
*= b; }
inline xlcmplx operator*(const xlfloat& a, xlcmplx b) { return b 
*= a; }
inline xlcmplx operator/(xlcmplx a, const xlcmplx& b) { return a 
/= b; }
inline xlcmplx operator/(xlcmplx a, const xlfloat& b) { return a 
/= b; }
inline xlcmplx operator/(const xlfloat& a, const xlcmplx& b) { 
return xlcmplx(a) /= b; }


inline xlcmplx pow(const xlcmplx& c, const int exp) { return 
polar(arg(c)*exp, pow(norm(c), exp)); }
inline xlcmplx pow(const xlcmplx& c, const 

Re: Compiler switch for integer comparison/promotion to catch a simple error

2022-05-30 Thread Dom Disc via Digitalmars-d-learn

On Sunday, 29 May 2022 at 01:35:23 UTC, frame wrote:

Is there a compiler switch to catch this kind of error?

```d
ulong v = 1;
writeln(v > -1);
```

IMHO the compiler should bail a warning if it sees a logic 
comparison between signed and unsigned / different integer 
sizes. There is 50% chance that a implicit conversion was not 
intended.


We have a solution for this problem in bugzilla:
https://issues.dlang.org/show_bug.cgi?id=259

This would allow for the above compare to simply work with all 
integer types signed or unsigned and produce always the correct 
result.


It was rejected because it would break old code that rely on this 
misbehaviour (and even worse: the behaviour would be different 
from what C does, oh my god!!)


Re: What are (were) the most difficult parts of D?

2022-05-17 Thread Dom Disc via Digitalmars-d-learn

On Tuesday, 17 May 2022 at 06:28:10 UTC, cc wrote:
having had this leave a pretty bad taste in my mouth, I now 
avoid the GC whenever possible, even when I don't have to.


Bad idea. You should only avoid GC if your profiling shows that 
it is bad in a specific piece of code (e.g. some inner loop 
that's called millions of times - the real bottlenecks). This 
frees you from the mental load of thinking about memory 
allocation at all unless it becomes necessary, which it will 
actually be only in very, very few places.
Better invest your precious time to really DO profiling and find 
out where the bottlenecks are!


Maybe a run-and-done program can get along just fine allocating 
everything to the GC.  But maybe I'll need to modularize it 
some day in the future and call it from another program with 
far more intensive requirements that doesn't want superfluous 
data being added to the GC every frame.


Yes - and when you modularize your program, keep in mind that a 
module should avoid allocating anything large or often on its own 
at all. It should better work on memory given to it. So you 
remain able to decide on the calling side if you allocate by GC 
(default) or (if something turns out to be a bottleneck) manually 
allocate memory.


Far better to just keep your house clean every day than let the 
trash pile up and wait for the maid to come, IMO.  Inevitably 
it's going to be her day off when you have guests coming over.


There's always gc.collect, which calls the maid to do her job, 
even if she is on vacation. Do so whenever you think you may have 
piled on a lot of trash and are out of house (have the time 
available that a collection may take). This way you can be sure 
there is never too much trash, so the GC is very unlikely to ever 
disturb you when there is no time for long collection cycles.




Re: Question on shapes

2022-05-17 Thread Dom Disc via Digitalmars-d-learn

On Tuesday, 17 May 2022 at 09:30:12 UTC, forkit wrote:

On Tuesday, 17 May 2022 at 04:37:58 UTC, Ali Çehreli wrote:




In you OOP example, I am curious why you chose Shape to be an 
interface, rather than a base class.


You can inherit from multiple interfaces, but only from one base 
class.
So if you need multiple inheritance, better use interfaces. 
Especially at the first level of objects I would almost always 
use only interfaces, no classes. I consider this better design.


Re: Why do immutable variables need reference counting?

2022-04-12 Thread Dom DiSc via Digitalmars-d-learn

On Monday, 11 April 2022 at 22:10:07 UTC, Ali Çehreli wrote:
1) I will not mutate data through this reference. For example, 
a parameter that is pointer to const achieves that:


  void foo (const(int)[] arr);

2) This variable is const:

  const i = 42;

Well, there is the confusion: There is no "reference" in the 
second case at all!

I think this second case should not be allowed. Use

   immutable i = 42;

instead. The meaning is identical, but we could remove the burden 
of two different meanings from const if it is not allowed. const 
should only be allowed in function declarations. A variable must 
be declared either mutable or immutable. It's only functions that 
may guarantee not to modify a parameter or the objects they 
belong to, and so are allowed to work on both mutable and 
immutable objects.




Re: abs and minimum values

2021-10-30 Thread Dom DiSc via Digitalmars-d-learn

On Friday, 29 October 2021 at 14:20:09 UTC, Ali Çehreli wrote:

Unsigned!T abs(T)(const(T) x) if(isIntegral!T)
{
   static if(isSigned!T) if(x < 0) return cast(Unsigned!T)-x;
   return x;
}

void main() {
  int a = -5;
  int b = -4;
  writeln(a + abs(b)); // -5 + 4 == -1? (No!)
}

The program prints uint.max.


This should be no surprise. You need to know what the resulting 
type of int + uint should be. And it is .. uint!  which is 
one of the stupit integer-promotion rules inherited from C. I 
just don't understand how "promoting" something by dropping some 
important information (the sign) and on the fly also destroying 
the absolute value can ever be a good choice. I always thought it 
should be the other way round.
The way it is is like "promoting" int + float to int (by 
discarding the fraction part and possibly too high exponents). 
And those two types are also of same size, so this is not an 
argument.
Promotion should always be in a direction where it at least 
sometimes can be correct.


Re: abs and minimum values

2021-10-29 Thread Dom DiSc via Digitalmars-d-learn

On Friday, 29 October 2021 at 08:33:07 UTC, Imperatorn wrote:

Imo abs should never be able to return a negative value


Yes, but phobos defines it to return a signed type, so 
theoretical it can return negative values. And they won't change 
that.


I really think it should return an unsigned type, but that's a 
"breaking change".

Bullshit policy!


Re: abs and minimum values

2021-10-29 Thread Dom DiSc via Digitalmars-d-learn

On Thursday, 28 October 2021 at 21:26:04 UTC, kyle wrote:


Okay I checked the phobos docs and it does say "Limitations
Does not work correctly for signed intergal types and value 
Num.min." Should have looked there first, I know. Still seems 
pretty silly.


I recommend to implement your own abs function this way (was not 
accepted for phobos, as it now does NOT return the same type as 
the argument, which was considered a "breaking change" :-( ):

```D
/// get the absolute value of x as unsigned type. always 
succeeds, even for T.min

Unsigned!T abs(T)(const(T) x) if(isIntegral!T)
{
   static if(isSigned!T) if(x < 0) return cast(Unsigned!T)-x;
   return x;
}
```