Re: Why many programmers don't like GC?

2021-01-14 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Jan 14, 2021 at 12:36:12PM +, claptrap via Digitalmars-d-learn 
wrote:
[...]
> I think you also have to consider that the GC you get with D is not
> state of the art, and if the opinions expressed on the newsgroup are
> accurate, it's not likely to get any better. So while you can find
> examples of high performance applications, AAA games, or whatever that
> use GC, I doubt any of them would be feasible with Ds GC. And given
> the design choices D has made as a language, a high performance GC is
> not really possible.

To be fair, the GC *has* improved over the years.  Just not as quickly
as people would like, but it *has* improved.


> So the GC is actually a poor fit for D as a language. It's like a
> convertible car with a roof that is only safe up to 50 mph, go over
> that and its likely to be torn off. So if you want to drive fast you
> have to put the roof down.

How much D code have you actually written and optimized?  That analogy
is inaccurate.  IME, performance issues caused by the GC are generally
localized, and easy to fix by replacing that small part of the code with
a bit of manual memory management (you *can* rewrite a function not to
use the GC; this isn't the Java straitjacket, y'know!), or standard GC
optimization techniques like reducing GC load in hot loops.  There's
also GC.stop and GC.collect for those times when you want more control
over exactly when collection pauses happen.

I wrote a compute-intensive program once, and after some profiling
revealed the GC being a bottleneck, I:

(1) Refactored one function called from an inner loop to reuse a buffer
instead of allocating a new one each time, thus eliminating a large
amoun of garbage from small allocations;

(2) Used GC.stop and scheduled my own GC.collect with slightly reduced
frequency.

The result was about 40-50% reduction in runtime, which is close to
about a 2x speedup.

Now, you'll argue that had I written this code without a GC in the first
place I wouldn't have needed to do all this.  However:

(a) Because I *had* the GC, I could write this code in about 1/5 of the
time it would've taken me to write it in C++;

(b) The optimization involved only changing a couple of lines of code in
2-3 functions -- a couple of days' work at most -- as opposed to blindly
optimizing *every* single danged line of code, 95% of which wouldn't
even have had any noticeable effect because they *are not the
bottleneck*;

(c) The parts of the code that aren't in the hot path can still freely
take advantage of the GC require minimal effort to write, and be free of
the time-consuming bugs that often creep into code that manually manages
memory.

As I said, it's an ROI question. I *could* have spent 5x the amount of
time and effort to write the perfect, GC-less, macho-hacker-style code,
and get maybe about a 1-2% performance improvement. But why would I?  It
takes 5x less effort to write GC code, and requires only a couple more
days of effort to fix GC-related performance issues, vs. 5x the
development effort to write the entire program GC-less, and who knows
how much longer after that to debug obscure pointer bugs.  Life is too
short to be squandered chasing down the 1000th double-free and the
20,000th dangling pointer in my life.

A lot of naysayers keep repeating GC performance issues as if it's a
black-and-white, all-or-nothing question.  It's not.  You *can* write
high-performance programs even with D's supposedly lousy GC -- just
profile the darned thing, and refactor the hotspots to reduce GC load or
avoid the GC. *In those parts of the code that actually matter*.  You
don't have to do this for the *entire* lousy program.  The non-hot parts
of the code can still GC away like there's no tomorrow, and your
customers would hardly notice a difference.  This isn't Java where you
have no choice but to use the GC everywhere.

Another example: one day I had some spare time, and wrote fastcsv
(http://github.com/quickfur/fastcsv).  It's an order of magnitude faster
than std.csv, *and it uses the evil GC*.  I just applied the same
technique: write it with GC, then profile to find the bottlenecks. The
first round of profiling showed that there tend to be a lot of small
allocations, which create lots of garbage, which means slow collection
cycles.  The solution? Use a linear buffer instead of individual
allocations for field/row data, and use slices where possible instead of
copying the data.  By reducing GC load and minimizing copying, I got
huge boosts in performance -- without throwing out the GC with the
bathwater.  (And note: it's *because* I can rely on the GC that I can
use slices so freely; if I had to use RC or manage this stuff manually,
it'd take 5x longer to write and would involve copying data all over the
place, which means it'd probably lose out in overall performance.)


But then again, it's futile to argue with people who have already made
up their minds about the GC, so meh. Let the bystanders judge for
themselves. I'll shut 

Re: Directory recursive walking

2021-01-14 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Friday, 15 January 2021 at 07:16:21 UTC, Daniel Kozak wrote:
On Fri, Jan 15, 2021 at 8:00 AM dog2002 via Digitalmars-d-learn 
< digitalmars-d-learn@puremagic.com> wrote:



On Friday, 15 January 2021 at 06:33:55 UTC, Paul Backus wrote:
> On Friday, 15 January 2021 at 06:31:18 UTC, Paul Backus 
> wrote:

>>
>> You can save a little bit of memory here by allocating 
>> tempBuffer on the stack:

>>
>> ubyte[512] tempBuffer;
>> _inputFile.rawRead(tempBuffer[]); // note the explicit 
>> []

>
> I made a mistake; this should be:
>
> ubyte[512] tempArray;
> ubyte[] tempBuffer = _inputFile.rawRead(tempArray[]);
>
> ...with the rest the same as your original version.

Thank you so much! It saves a lot of memory!

And one last question: why the application crashes, if I 
allocate 1 MB array?


>ubyte[1024000] tempBuffer;



Because of stack overflow


A compiler parameter can be used to increase the maximum stack 
size

"dflags": ["-L/STACK:15"]

or recursion can be somehow emulated using heap memory. Here is 
my "fake" recursion:

// wins is a range

auto stack = wins.save;
while(!stack.empty){
immutable n = stack.length - 1;
auto window = stack[n];

doSomeThingforEachRecursiveElement(window)

stack.popBack;
if(window.children.length){
foreach (ref child; window.children)
stack.pushBack(child);
}
}
stack.free;


Re: Directory recursive walking

2021-01-14 Thread Daniel Kozak via Digitalmars-d-learn
On Fri, Jan 15, 2021 at 8:20 AM dog2002 via Digitalmars-d-learn <
digitalmars-d-learn@puremagic.com> wrote:

> On Friday, 15 January 2021 at 06:56:36 UTC, dog2002 wrote:
> > On Friday, 15 January 2021 at 06:33:55 UTC, Paul Backus wrote:
> >> On Friday, 15 January 2021 at 06:31:18 UTC, Paul Backus wrote:
> >>>
> >>> You can save a little bit of memory here by allocating
> >>> tempBuffer on the stack:
> >>>
> >>> ubyte[512] tempBuffer;
> >>> _inputFile.rawRead(tempBuffer[]); // note the explicit []
> >>
> >> I made a mistake; this should be:
> >>
> >> ubyte[512] tempArray;
> >> ubyte[] tempBuffer = _inputFile.rawRead(tempArray[]);
> >>
> >> ...with the rest the same as your original version.
> >
> > Thank you so much! It saves a lot of memory!
> >
> > And one last question: why the application crashes, if I
> > allocate 1 MB array?
> >
> >>ubyte[1024000] tempBuffer;
>
> Solved:
>
> ubyte[] tempBuffer = new ubyte[1024000];
>

You can still use ubyte[1024000] tempBuffer; but you have to place it
somewhere outside recursion or use a static
static ubyte[1024000] tempBuffer;


Re: Directory recursive walking

2021-01-14 Thread dog2002 via Digitalmars-d-learn

On Friday, 15 January 2021 at 06:56:36 UTC, dog2002 wrote:

On Friday, 15 January 2021 at 06:33:55 UTC, Paul Backus wrote:

On Friday, 15 January 2021 at 06:31:18 UTC, Paul Backus wrote:


You can save a little bit of memory here by allocating 
tempBuffer on the stack:


ubyte[512] tempBuffer;
_inputFile.rawRead(tempBuffer[]); // note the explicit []


I made a mistake; this should be:

ubyte[512] tempArray;
ubyte[] tempBuffer = _inputFile.rawRead(tempArray[]);

...with the rest the same as your original version.


Thank you so much! It saves a lot of memory!

And one last question: why the application crashes, if I 
allocate 1 MB array?



ubyte[1024000] tempBuffer;


Solved:

ubyte[] tempBuffer = new ubyte[1024000];


Re: Directory recursive walking

2021-01-14 Thread Daniel Kozak via Digitalmars-d-learn
On Fri, Jan 15, 2021 at 8:00 AM dog2002 via Digitalmars-d-learn <
digitalmars-d-learn@puremagic.com> wrote:

> On Friday, 15 January 2021 at 06:33:55 UTC, Paul Backus wrote:
> > On Friday, 15 January 2021 at 06:31:18 UTC, Paul Backus wrote:
> >>
> >> You can save a little bit of memory here by allocating
> >> tempBuffer on the stack:
> >>
> >> ubyte[512] tempBuffer;
> >> _inputFile.rawRead(tempBuffer[]); // note the explicit []
> >
> > I made a mistake; this should be:
> >
> > ubyte[512] tempArray;
> > ubyte[] tempBuffer = _inputFile.rawRead(tempArray[]);
> >
> > ...with the rest the same as your original version.
>
> Thank you so much! It saves a lot of memory!
>
> And one last question: why the application crashes, if I allocate
> 1 MB array?
>
> >ubyte[1024000] tempBuffer;
>

Because of stack overflow


Re: Directory recursive walking

2021-01-14 Thread dog2002 via Digitalmars-d-learn

On Friday, 15 January 2021 at 06:33:55 UTC, Paul Backus wrote:

On Friday, 15 January 2021 at 06:31:18 UTC, Paul Backus wrote:


You can save a little bit of memory here by allocating 
tempBuffer on the stack:


ubyte[512] tempBuffer;
_inputFile.rawRead(tempBuffer[]); // note the explicit []


I made a mistake; this should be:

ubyte[512] tempArray;
ubyte[] tempBuffer = _inputFile.rawRead(tempArray[]);

...with the rest the same as your original version.


Thank you so much! It saves a lot of memory!

And one last question: why the application crashes, if I allocate 
1 MB array?



ubyte[1024000] tempBuffer;


Re: Directory recursive walking

2021-01-14 Thread Paul Backus via Digitalmars-d-learn

On Friday, 15 January 2021 at 06:31:18 UTC, Paul Backus wrote:


You can save a little bit of memory here by allocating 
tempBuffer on the stack:


ubyte[512] tempBuffer;
_inputFile.rawRead(tempBuffer[]); // note the explicit []


I made a mistake; this should be:

ubyte[512] tempArray;
ubyte[] tempBuffer = _inputFile.rawRead(tempArray[]);

...with the rest the same as your original version.


Re: Directory recursive walking

2021-01-14 Thread Paul Backus via Digitalmars-d-learn

On Friday, 15 January 2021 at 06:15:06 UTC, dog2002 wrote:


void func(string inputFile, string outFile, uint chunk_size) {
try {
File _inputFile = File(inputFile, "r");
File _outputFile = File(outFile, "w");

ubyte[] tempBuffer = _inputFile.rawRead(new ubyte[](512));

//doing some operations with the tempBuffer 

_outputFile.rawWrite(tempBuffer);

_inputFile.seek(tempBuffer.length, SEEK_SET);


foreach(_buffer; _inputFile.byChunk(chunk_size)) {
_outputFile.rawWrite(_buffer);
}
_inputFile.close();
_outputFile.close();
}
catch (Throwable) {}

}


You can save a little bit of memory here by allocating tempBuffer 
on the stack:


ubyte[512] tempBuffer;
_inputFile.rawRead(tempBuffer[]); // note the explicit []

// ...

_outputFile.rawWrite(tempBuffer[]);

However, those allocations alone shouldn't be enough to get you 
to 4GB+, so the real issue is probably elsewhere.


Re: Directory recursive walking

2021-01-14 Thread dog2002 via Digitalmars-d-learn

On Thursday, 14 January 2021 at 22:28:19 UTC, Paul Backus wrote:

On Thursday, 14 January 2021 at 20:23:37 UTC, dog2002 wrote:

About 1000 large files.

I want to replace several first bytes in all the files, so I 
just copy the remaining bytes into a new file. Might this be 
the reason for high memory consumption? If so, is there a way 
not to copy the entire file, just delete first bytes and write 
the replaced bytes into the beginning of the file?


I use Windows x64.


What code are you using to copy the bytes? If you're reading 
the whole file into memory at once, that will consume a lot of 
memory.


void func(string inputFile, string outFile, uint chunk_size) {
try {
File _inputFile = File(inputFile, "r");
File _outputFile = File(outFile, "w");

ubyte[] tempBuffer = _inputFile.rawRead(new ubyte[](512));

//doing some operations with the tempBuffer 

_outputFile.rawWrite(tempBuffer);

_inputFile.seek(tempBuffer.length, SEEK_SET);


foreach(_buffer; _inputFile.byChunk(chunk_size)) {
_outputFile.rawWrite(_buffer);
}
_inputFile.close();
_outputFile.close();
}
catch (Throwable) {}

}


Re: Open question: what code pattern you use usually for null safety problem

2021-01-14 Thread ddcovery via Digitalmars-d-learn

On Thursday, 14 January 2021 at 20:35:49 UTC, Dennis wrote:

On Thursday, 14 January 2021 at 18:24:44 UTC, ddcovery wrote:
If it's not a bother, I'd like to know how you usually 
approach it


Usually I don't deal with null because my functions get 
primitive types, slices, or structs. `ref` parameters can be 
used to replace pointers that may not be null.

When something is nullable by design, I usually do this:

```
if (!person) {
return; // early return if possible
}
if (auto f0 = person.father) {
if (auto f1 = f0.father) {
   if (f1.name == "Peter") {
   doSomething();
   }
}
}
```

It doesn't matter whether you're working with a class, pointer, 
or struct with opCast, this works. When access patterns get 
complex the nesting may get very deep.
Only if you can't avoid this I would consider using fancy 
helper functions, otherwise just use an if-statement or the && 
operator.
I agree:  using null safety is a sign of something wrong in the 
design (the need of dealing with nulls)... but if eventually you 
need it, simple **if** or **&&** should be enough.


Curiously, languages like Dart (and its flutter framework) 
performs extensive use of null safety (null is everywhere!!!) and 
it seems that every "modern" language must deal with it.


Any case, I'm learning a lot: thank you Dennis for sharing!!!


Re: Open question: what code pattern you use usually for null safety problem

2021-01-14 Thread ddcovery via Digitalmars-d-learn
On Thursday, 14 January 2021 at 20:23:08 UTC, Steven 
Schveighoffer wrote:


You could kinda automate it like:

struct NullCheck(T)
{
   private T* _val;
   auto opDispatch(string mem)() if (__traits(hasMember, T, 
mem)) {
   alias Ret = typeof(() { return __traits(getMember, 
*_val, mem); }());

   if(_val is null) return NullCheck!(Ret)(null);
   else return NullCheck!(Ret)(__trats(getMember, *_val, 
mem));

   }

   bool opCast(V: bool)() { return _val !is null; }
}

auto nullCheck(T)(T *val) { return AutoNullCheck!T(val);}

// usage
if(nullCheck(person).father.father && person.father.father.name 
== "Peter")


Probably doesn't work for many circumstances, and I'm sure I 
messed something up.


-Steve


I'm seeing "opDispatch" everywhere last days :-). It's really 
powerful!!!


If we define an special T _(){ return _val; } method, then you 
can write


  if( nullCheck(person).father.father.name._ == "Peter")

And renaming

  if( ns(person).father.father.name._ == "Peter" )

And adding some extra check like ** isAssignable!(Ret, 
typeof(null) )** we can add special treatment for not nullable 
types


  if( ns(person).father.father.age._(0) == 92 ){ ... }
  assert( ns(person).father.father.father.age._ == int.init );

If for some strange reason I ever need null safety, I think this 
is the most beautiful solution or at least a great lesson on 
templates.


Thanks a lot for the lesson, Steve



Re: Directory recursive walking

2021-01-14 Thread Paul Backus via Digitalmars-d-learn

On Thursday, 14 January 2021 at 20:23:37 UTC, dog2002 wrote:

About 1000 large files.

I want to replace several first bytes in all the files, so I 
just copy the remaining bytes into a new file. Might this be 
the reason for high memory consumption? If so, is there a way 
not to copy the entire file, just delete first bytes and write 
the replaced bytes into the beginning of the file?


I use Windows x64.


What code are you using to copy the bytes? If you're reading the 
whole file into memory at once, that will consume a lot of memory.


Re: Anything in D to avoid check for null everywhere?

2021-01-14 Thread ddcovery via Digitalmars-d-learn
On Thursday, 14 January 2021 at 21:49:41 UTC, Christian Köstlin 
wrote:

...
Did you have a look at https://code.dlang.org/packages/optional?
Especially 
https://aliak00.github.io/optional/optional/oc/oc.html might go 
in the right direction.



Kind regards,
Christian


Thats nice!!!

I was commenting the need of a MayBe (some/none) monad compatible 
with Ranges (as an alternative to Nullable!T ) in  
https://forum.dlang.org/post/gxapatzfkoigcdhrd...@forum.dlang.org


Thanks a lot Christian.






Re: Open question: what code pattern you use usually for null safety problem

2021-01-14 Thread ddcovery via Digitalmars-d-learn

On Thursday, 14 January 2021 at 19:24:54 UTC, Adam D. Ruppe wrote:

On Thursday, 14 January 2021 at 18:24:44 UTC, ddcovery wrote:
This is only an open question to know what code patterns you 
usually use to solve this situation in D:


I'm almost never in this situation except for reading things 
like xml or json data that may be missing.


Yes, this is the usual situation (Personally, I use "DTO" 
structured objects... that are serialized/unserialized to JSON)




So I just special cased those. My json lib doesn't return null 
per se, it returns var(null) which is allowed to just return 
more harmless nulls. Thus you write 
`person.father.father.name.get!string` and it will be empty if 
anything was null in the chain.


With dom, you can optionSelector("person > father > father > 
name").innerText and again if the selector returned null, all 
its methods also just return empty strings or whatever.


Selectors are a good option to navigate on dom/json, but on 
structured objects too.  The good think with "templates" in D is 
that this "path/selector" can be compiled internally to a 
map/filter combination completly "null" free... I was 
experimenting last days with this and I think that a functional 
orientation (using a MayBe monad implemented as Range ) is the 
best way to begin.




So the library handles these special cases and then I don't 
worry about nested nulls anywhere else since I consider it bad 
style to even be in that situation in the first place.


I agree: it is a bad style. Personally I allways use MayBe monads 
in my "DTO"s (that is the effect of having worked with scala :-).


The only "cons" with Nullable!T (the "standard" D MayBe 
equivalent) is that it is not "compatible" with Range libraries 
(it is not a Range:  you use "apply" instead "map", you have not 
"filter", you can't "chain" a range and Nullable, you can't 
"join" a range of Nullables like a Range of ranges).  This is the 
reason I'm "experimenting" with my own "MayBe" InputRange that 
can be created in the form of "Some" or "None" (it's inmutable 
contrary to what happens with Nullable) and is compatible with 
all std.algorithm (and array) library.







Re: Anything in D to avoid check for null everywhere?

2021-01-14 Thread Christian Köstlin via Digitalmars-d-learn

On 12.01.21 22:37, Jack wrote:
I was looking for a way to avoid null checks everywhere. I was checking 
the Null object pattern, or use something like enforce pattern, or even 
if I could make a new operator and implement something like C#'s .? 
operator, that Java was going to have one but they refused[1] (doesn't 
behave exactly as C#'s actually), Kotlin also got something in this area[2]


What some D ways to avoid those checks?

[1]: 
https://mail.openjdk.java.net/pipermail/coin-dev/2009-March/47.html

[2]: https://kotlinlang.org/docs/reference/null-safety.html#safe-calls

Did you have a look at https://code.dlang.org/packages/optional?
Especially https://aliak00.github.io/optional/optional/oc/oc.html might 
go in the right direction.



Kind regards,
Christian


Re: Open question: what code pattern you use usually for null safety problem

2021-01-14 Thread Dennis via Digitalmars-d-learn

On Thursday, 14 January 2021 at 18:24:44 UTC, ddcovery wrote:
If it's not a bother, I'd like to know how you usually approach 
it


Usually I don't deal with null because my functions get primitive 
types, slices, or structs. `ref` parameters can be used to 
replace pointers that may not be null.

When something is nullable by design, I usually do this:

```
if (!person) {
return; // early return if possible
}
if (auto f0 = person.father) {
if (auto f1 = f0.father) {
   if (f1.name == "Peter") {
   doSomething();
   }
}
}
```

It doesn't matter whether you're working with a class, pointer, 
or struct with opCast, this works. When access patterns get 
complex the nesting may get very deep.
Only if you can't avoid this I would consider using fancy helper 
functions, otherwise just use an if-statement or the && operator.


Re: Why many programmers don't like GC?

2021-01-14 Thread IGotD- via Digitalmars-d-learn

On Thursday, 14 January 2021 at 15:18:28 UTC, ddcovery wrote:


I understand perfectly the D community people that needs to 
work without GC:  **it is not snobbish**:  it is a real need.  
But not only a "need"... sometimes it is basically the way a 
team wants to work:  explicit memory management vs GC.


D already supports manual memory management so that escape hatch 
was always there. My main criticism of D is the inability to 
freely exchange the GC algorithms as one type of GC might not be 
the best fit for everyone. The problem is of course that there is 
no differentiation between raw and fat pointers. With fat 
pointers, the community would have a better opportunities to 
experiment with different GC designs which would lead to a larger 
palette of GC algorithms.


Re: Directory recursive walking

2021-01-14 Thread dog2002 via Digitalmars-d-learn

On Thursday, 14 January 2021 at 16:47:45 UTC, drug wrote:

On 1/14/21 7:06 PM, dog2002 wrote:

On Thursday, 14 January 2021 at 16:01:43 UTC, drug wrote:

On 1/14/21 6:55 PM, drug wrote:


But this method consumes a huge amount of memory (up to 
4 GB and more). Is there a more appropriate way to walk 
directories recursively that does not consume a lot of 
memory?


DirEntry is a struct. First of all I would try this:
```D
foreach(ref entry; dirEntries(path, SpanMode.shallow, false))
```


Does your directory just contain large amount of files?


Yes. I forgot to add it in the original post.


How much files do you have? DirEntry size is 168 bytes only and 
dirEntry is lazy range so I'm curious what is the reason of 
huge memory consumption. Do you use Windows 32 bits between?


About 1000 large files.

I want to replace several first bytes in all the files, so I just 
copy the remaining bytes into a new file. Might this be the 
reason for high memory consumption? If so, is there a way not to 
copy the entire file, just delete first bytes and write the 
replaced bytes into the beginning of the file?


I use Windows x64.


Re: Open question: what code pattern you use usually for null safety problem

2021-01-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/14/21 1:24 PM, ddcovery wrote:
I know there is other threads about null safety and the "possible" ways 
to support this in D and so on.


This is only an open question to know what code patterns you usually use 
to solve this situation in D:


   if(person.father.father.name == "Peter") doSomething();
   if(person.father.age > 80 ) doSomething();

knowing that *person*, or its *father* property can be null

i.e.: the incremental null check solution

if(
   person !is null &&
   person.father !is null &&
   person.father.father !is null &&
   person.father.father.name == "Peter"
)
{
   doSomething();
}

or the "monad" way

[person].
   filter!"a !is null".map!"a.father".
   filter!"a !is null".map!"a.father".
   filter!"a !is null".map!"a.name".
   each!( (name) {
     if(name == "Peter") doSomething();
   });

or, may be, you have some helper function/structs/templates

if( person.d!"father".d!"father".d!"name".get == "Peter" ){
   doSomething()
}
if( person.d!"father".d!"age".get(0) > 80 ){
   doSomething()
}

or an "xml path" like template

if( person.get!"father.father.name" == "Peter" )
if( person.get!"father.father.name.length"(0) == 5 )
if( person.get!"father.father.age"(0) > 80 )


If it's not a bother, I'd like to know how you usually approach it

Thanks!!!




You could kinda automate it like:

struct NullCheck(T)
{
   private T* _val;
   auto opDispatch(string mem)() if (__traits(hasMember, T, mem)) {
   alias Ret = typeof(() { return __traits(getMember, *_val, mem); 
}());

   if(_val is null) return NullCheck!(Ret)(null);
   else return NullCheck!(Ret)(__trats(getMember, *_val, mem));
   }

   bool opCast(V: bool)() { return _val !is null; }
}

auto nullCheck(T)(T *val) { return AutoNullCheck!T(val);}

// usage
if(nullCheck(person).father.father && person.father.father.name == "Peter")

Probably doesn't work for many circumstances, and I'm sure I messed 
something up.


-Steve


Re: Open question: what code pattern you use usually for null safety problem

2021-01-14 Thread mw via Digitalmars-d-learn

On Thursday, 14 January 2021 at 18:24:44 UTC, ddcovery wrote:
I know there is other threads about null safety and the 
"possible" ways to support this in D and so on.


This is only an open question to know what code patterns you 
usually use to solve this situation in D:


  if(person.father.father.name == "Peter") doSomething();
  if(person.father.age > 80 ) doSomething();

knowing that *person*, or its *father* property can be null

i.e.: the incremental null check solution


I just use this most simple one:


if(
  person !is null &&
  person.father !is null &&
  person.father.father !is null &&
  person.father.father.name == "Peter"
)
{
  doSomething();
}


Reason: easy to read and reason about, esp for non-authors of 
this piece of the code.




Re: Open question: what code pattern you use usually for null safety problem

2021-01-14 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 14 January 2021 at 18:24:44 UTC, ddcovery wrote:
This is only an open question to know what code patterns you 
usually use to solve this situation in D:


I'm almost never in this situation except for reading things like 
xml or json data that may be missing.


So I just special cased those. My json lib doesn't return null 
per se, it returns var(null) which is allowed to just return more 
harmless nulls. Thus you write 
`person.father.father.name.get!string` and it will be empty if 
anything was null in the chain.


With dom, you can optionSelector("person > father > father > 
name").innerText and again if the selector returned null, all its 
methods also just return empty strings or whatever.


So the library handles these special cases and then I don't worry 
about nested nulls anywhere else since I consider it bad style to 
even be in that situation in the first place.


Re: Why many programmers don't like GC?

2021-01-14 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 14 January 2021 at 18:10:43 UTC, mw wrote:

Python's `del` isn't guaranteed to free the memory, that's what


Fair point, but I was thinking of the C interop interface. You 
can create your own wrapper (e.g. numpy) and do manual memory 
management, but it isn't something people want to do! It is 
mostly pointless to do that within Python because of the existing 
overhead.  That applies to most high level languages; you can, 
but it is pointless. You only do it for interop...


One can follow the same kind of reasoning for D. It makes no 
sense for people who want to stay high level and do batch 
programming. Which is why this disconnect exists in the 
community... I think.




Re: Static constructor

2021-01-14 Thread SealabJaster via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 11:28:12 UTC, ludo wrote:
Ok, I agree that ends up being a kind of strange singleton. But 
yes it was D v1 code. Do we agree that the following 
multi-threaded singleton pattern is the proper way as of today.


It looks fine to me. The D wiki has the following example which 
prevents the need for entering the synchronized block more than 
once per thread: https://wiki.dlang.org/Low-Lock_Singleton_Pattern


I should note that the example doesn't specify the value as 
shared, which technically isn't the correct thing to do, but 
`shared` itself can be a bit of an annoyance. However, you do 
need to ensure that your static variable is either shared or 
__gshared, otherwise it becomes thread-local.


If I understand, as of today an AA init depends on a runtime 
function for historical reasons. A bit weird for an array 
indeed perfectly known at compile time, but someday some  core 
language contributor will have a look at it, I guess.


Maybe in 5 years' time we'll get an uneventful discussion on it 
where it'd take 2 years to come to a conclusion before another 
year for it to actually be implemented.


If I understand well, this will accomplish the goal quoted with 
no further comestics needed! Only one keyword over explicitely 
using object mutex. Am I right?


I believe so. I've never used OpenAL so it may have additional 
restrictions with multithreading, but from a simple "This 
function is only ever executed on one thread at a time", your 
above suggestions should work.


Apologies for the late reply.



Open question: what code pattern you use usually for null safety problem

2021-01-14 Thread ddcovery via Digitalmars-d-learn
I know there is other threads about null safety and the 
"possible" ways to support this in D and so on.


This is only an open question to know what code patterns you 
usually use to solve this situation in D:


  if(person.father.father.name == "Peter") doSomething();
  if(person.father.age > 80 ) doSomething();

knowing that *person*, or its *father* property can be null

i.e.: the incremental null check solution

if(
  person !is null &&
  person.father !is null &&
  person.father.father !is null &&
  person.father.father.name == "Peter"
)
{
  doSomething();
}

or the "monad" way

[person].
  filter!"a !is null".map!"a.father".
  filter!"a !is null".map!"a.father".
  filter!"a !is null".map!"a.name".
  each!( (name) {
if(name == "Peter") doSomething();
  });

or, may be, you have some helper function/structs/templates

if( person.d!"father".d!"father".d!"name".get == "Peter" ){
  doSomething()
}
if( person.d!"father".d!"age".get(0) > 80 ){
  doSomething()
}

or an "xml path" like template

if( person.get!"father.father.name" == "Peter" )
if( person.get!"father.father.name.length"(0) == 5 )
if( person.get!"father.father.age"(0) > 80 )


If it's not a bother, I'd like to know how you usually approach it

Thanks!!!




Re: Why many programmers don't like GC?

2021-01-14 Thread mw via Digitalmars-d-learn
On Thursday, 14 January 2021 at 09:26:06 UTC, Ola Fosheim Grøstad 
wrote:

On Thursday, 14 January 2021 at 00:37:29 UTC, mw wrote:

ok, what I really mean is:

... in other "(more popular) languages (than D, and directly 
supported by the language & std library only)" ...


Well, even Python supports both


Python's `del` isn't guaranteed to free the memory, that's what 
we are discussing here: core.memory.GC.free / 
core.stdc.stdlib.free


https://www.quora.com/Why-doesnt-Python-release-the-memory-when-I-delete-a-large-object

In CPython (the default reference distribution), the Garbage 
collection in Python is not guaranteed to run when you delete the 
object - all del (or the object going out of scope) does is 
decrement the reference count on the object. The memory used by 
the object is not guaranteed to be freed and returned to the 
processes pool at any time before the process exits. Even if the 
Garbage collection does run - all it needs is another object 
referencing the deleted object and the garbage collection won’t 
free the object at all.





Re: Directory recursive walking

2021-01-14 Thread drug via Digitalmars-d-learn

On 1/14/21 7:06 PM, dog2002 wrote:

On Thursday, 14 January 2021 at 16:01:43 UTC, drug wrote:

On 1/14/21 6:55 PM, drug wrote:


But this method consumes a huge amount of memory (up to 4 GB and 
more). Is there a more appropriate way to walk directories 
recursively that does not consume a lot of memory?


DirEntry is a struct. First of all I would try this:
```D
foreach(ref entry; dirEntries(path, SpanMode.shallow, false))
```


Does your directory just contain large amount of files?


Yes. I forgot to add it in the original post.


How much files do you have? DirEntry size is 168 bytes only and dirEntry 
is lazy range so I'm curious what is the reason of huge memory 
consumption. Do you use Windows 32 bits between?


Re: Directory recursive walking

2021-01-14 Thread drug via Digitalmars-d-learn

On 1/14/21 7:30 PM, dog2002 wrote:

On Thursday, 14 January 2021 at 16:18:28 UTC, drug wrote:

On 1/14/21 7:06 PM, dog2002 wrote:

On Thursday, 14 January 2021 at 16:01:43 UTC, drug wrote:

[...]


Yes. I forgot to add it in the original post.


Does using `ref` changed anything?
Try following:
```
import std;

void DirIteration(ref DirEntry dir) {
    try {
    foreach(ref entry; dirEntries(dir, SpanMode.shallow, false)) { 
//SpanMode.shallow allows skip directories if any error happens

    if (entry.isFile && !entry.isSymlink)
    writeln(entry); //Or something instead of this
    if (entry.isDir)
    DirIteration(entry);
    }
    }
    catch (Throwable) {}
}

void main()
{
    auto de = DirEntry(".");
    DirIteration(de);
}
```


No, it doesn't. Seems like memory can't clear.


It is a recursion. Memory will be freed only after completion. Then I 
would try to get rid of recursion.


Re: Directory recursive walking

2021-01-14 Thread dog2002 via Digitalmars-d-learn

On Thursday, 14 January 2021 at 16:18:28 UTC, drug wrote:

On 1/14/21 7:06 PM, dog2002 wrote:

On Thursday, 14 January 2021 at 16:01:43 UTC, drug wrote:

[...]


Yes. I forgot to add it in the original post.


Does using `ref` changed anything?
Try following:
```
import std;

void DirIteration(ref DirEntry dir) {
try {
foreach(ref entry; dirEntries(dir, SpanMode.shallow, 
false)) { //SpanMode.shallow allows skip directories if any 
error happens

if (entry.isFile && !entry.isSymlink)
writeln(entry); //Or something instead of this
if (entry.isDir)
DirIteration(entry);
}
}
catch (Throwable) {}
}

void main()
{
auto de = DirEntry(".");
DirIteration(de);
}
```


No, it doesn't. Seems like memory can't clear.


Re: Directory recursive walking

2021-01-14 Thread drug via Digitalmars-d-learn

On 1/14/21 7:06 PM, dog2002 wrote:

On Thursday, 14 January 2021 at 16:01:43 UTC, drug wrote:

On 1/14/21 6:55 PM, drug wrote:


But this method consumes a huge amount of memory (up to 4 GB and 
more). Is there a more appropriate way to walk directories 
recursively that does not consume a lot of memory?


DirEntry is a struct. First of all I would try this:
```D
foreach(ref entry; dirEntries(path, SpanMode.shallow, false))
```


Does your directory just contain large amount of files?


Yes. I forgot to add it in the original post.


Does using `ref` changed anything?
Try following:
```
import std;

void DirIteration(ref DirEntry dir) {
try {
foreach(ref entry; dirEntries(dir, SpanMode.shallow, false)) { 
//SpanMode.shallow allows skip directories if any error happens

if (entry.isFile && !entry.isSymlink)
writeln(entry); //Or something instead of this
if (entry.isDir)
DirIteration(entry);
}
}
catch (Throwable) {}
}

void main()
{
auto de = DirEntry(".");
DirIteration(de);
}
```


Re: Directory recursive walking

2021-01-14 Thread dog2002 via Digitalmars-d-learn

On Thursday, 14 January 2021 at 16:01:43 UTC, drug wrote:

On 1/14/21 6:55 PM, drug wrote:


But this method consumes a huge amount of memory (up to 4 GB 
and more). Is there a more appropriate way to walk 
directories recursively that does not consume a lot of memory?


DirEntry is a struct. First of all I would try this:
```D
foreach(ref entry; dirEntries(path, SpanMode.shallow, false))
```


Does your directory just contain large amount of files?


Yes. I forgot to add it in the original post.


Re: Directory recursive walking

2021-01-14 Thread drug via Digitalmars-d-learn

On 1/14/21 6:55 PM, drug wrote:


But this method consumes a huge amount of memory (up to 4 GB and 
more). Is there a more appropriate way to walk directories recursively 
that does not consume a lot of memory?


DirEntry is a struct. First of all I would try this:
```D
foreach(ref entry; dirEntries(path, SpanMode.shallow, false))
```


Does your directory just contain large amount of files?


Re: Directory recursive walking

2021-01-14 Thread drug via Digitalmars-d-learn

On 1/14/21 6:46 PM, dog2002 wrote:
I need to make some operations with all the files in a directory and 
subdirectories. Currently, I do it like this:


import std;

void DirIteration(string path) {
     try {
     foreach(entry; dirEntries(path, SpanMode.shallow, false)) { 
//SpanMode.shallow allows skip directories if any error happens

     if (entry.isFile && !entry.isSymlink)
     writeln(entry); //Or something instead of this
     if (entry.isDir)
     DirIteration(entry);
     }
     }
     catch (Throwable) {}
}

void main()
{
     DirIteration("C:\\Users\\angrypuppy\\MyDir");
}

But this method consumes a huge amount of memory (up to 4 GB and more). 
Is there a more appropriate way to walk directories recursively that 
does not consume a lot of memory?


DirEntry is a struct. First of all I would try this:
```D
foreach(ref entry; dirEntries(path, SpanMode.shallow, false))
```


Directory recursive walking

2021-01-14 Thread dog2002 via Digitalmars-d-learn
I need to make some operations with all the files in a directory 
and subdirectories. Currently, I do it like this:


import std;

void DirIteration(string path) {
try {
foreach(entry; dirEntries(path, SpanMode.shallow, false)) 
{ //SpanMode.shallow allows skip directories if any error happens

if (entry.isFile && !entry.isSymlink)
writeln(entry); //Or something instead of this
if (entry.isDir)
DirIteration(entry);
}
}
catch (Throwable) {}
}

void main()
{
DirIteration("C:\\Users\\angrypuppy\\MyDir");
}

But this method consumes a huge amount of memory (up to 4 GB and 
more). Is there a more appropriate way to walk directories 
recursively that does not consume a lot of memory?


Re: Why doesn't this work when the function is a static method?

2021-01-14 Thread Anonymouse via Digitalmars-d-learn

On Thursday, 14 January 2021 at 15:20:54 UTC, Jack wrote:

On Thursday, 14 January 2021 at 09:13:27 UTC, evilrat wrote:

On Thursday, 14 January 2021 at 05:44:43 UTC, Jack wrote:
On Wednesday, 13 January 2021 at 17:21:23 UTC, Paul Backus 
wrote:


Member functions (including static ones) can't be called 
with UFCS.



 is this documented somewhere? Is this going to change?


It will stay as is.
It is somewhat vaguely described in p.7 under UFCS section in 
functions


https://dlang.org/spec/function.html#pseudo-member


I see, thanks


If it's really important you can make a module-level alias to the 
static method.


https://run.dlang.io/is/4IFsjr


Re: Why doesn't this work when the function is a static method?

2021-01-14 Thread Jack via Digitalmars-d-learn

On Thursday, 14 January 2021 at 09:13:27 UTC, evilrat wrote:

On Thursday, 14 January 2021 at 05:44:43 UTC, Jack wrote:
On Wednesday, 13 January 2021 at 17:21:23 UTC, Paul Backus 
wrote:


Member functions (including static ones) can't be called with 
UFCS.



 is this documented somewhere? Is this going to change?


It will stay as is.
It is somewhat vaguely described in p.7 under UFCS section in 
functions


https://dlang.org/spec/function.html#pseudo-member


I see, thanks


Re: Why many programmers don't like GC?

2021-01-14 Thread ddcovery via Digitalmars-d-learn

On Thursday, 14 January 2021 at 10:28:13 UTC, Basile B. wrote:

On Wednesday, 13 January 2021 at 18:58:56 UTC, Marcone wrote:
I've always heard programmers complain about Garbage Collector 
GC. But I never understood why they complain. What's bad about 
GC?


Semi serious answer:

In the domain of hoby-ism and small companies programmers that 
work with statically typed languages all believe that they are 
super hero in the domain of memory managment. When they see 
"GC" they think that they are considered as 2nd grade student ^^


It's basically snobbism.


Hi Basile,

My experience:

in 90's I worked with Pascal, C and C++ with rudimentary memory 
management: basically it was no difference between working with 
memory or files in terms of life-cycle management: you must 
alloc/free memory and you must open/close files.  The secret for 
"stability" was a set of conventions to determine who was the 
responsible of the resource handler or memory pointer:  I 
developed some ERP/CRMs, some multimedia products  and some 
industrial environment applications (real time ones).


 At the end of 90's I began to work with VB and the COM model 
(that uses references counter) and I discovered that the best way 
to manage memory (avoiding death-locks) was treating objects as 
"external" unmanaged resources:  The VB6 "WITH" statement was key 
to use ARM techniques (similar to future "using" in C#).


And then arrived GC with C#, Java and Scala:  I have found GC 
good enough for all applications and services that I have been 
developing last 20 years because this languages (and it's 
frameworks+based libraries) have never crossed certain limits:  
they always separated managed and unmanaged resources:  developer 
is responsible of unmanaged resources, and Memory is managed by 
GC.   Language itself offers you good tooling to ARM (like 
"using" in c#, "try-with-resources" in java, ...).


Finally arrived the last actors to the scene: mainly javascript 
and derivatives (when working in a browser context), where 
developer is abstracted of how memory and resources are really 
managed (I can remember critical bugs in chrome like Image object 
memory leaks because this "abstraction").


GC has introduced a "productive" way of working removing old 
memory problems for large scale projects (and finally with other 
kind of resources in some scenarios) but, as 
developers/architects, we have de responsibility to recognize the 
limits to each technique and when it fits to our needs.


After all, my opinion is that if I was to develop something like 
a Real Time app (industrial/medical/aeronautics/...) or a game 
where a large amount of objects must be mutated ~30 times per 
second,  GC "unpredictable" or "large" time cost will be enough 
to stop using it.  There is other reasons (like "efficient" 
memory management when we need to manage large amounts of memory 
or to run in limited memory environments).



I understand perfectly the D community people that needs to work 
without GC:  **it is not snobbish**:  it is a real need.  But not 
only a "need"... sometimes it is basically the way a team wants 
to work:  explicit memory management vs GC.


D toke the way of GC without "cutting" the relationship with 
C/C++ developers:  I really don't have enough knowledge of the 
language and libraries to know the level of support that D offers 
to non GC based developments, but I find completely logic trying 
to maintain this relationship (in the basis that GC must continue 
been the default way of working)


Sorry for my "extended", may be unnecessary, explanation (and my 
"poor" english :-p).


Re: Why many programmers don't like GC?

2021-01-14 Thread Dukc via Digitalmars-d-learn
On Thursday, 14 January 2021 at 14:28:43 UTC, Виталий Фадеев 
wrote:

On Wednesday, 13 January 2021 at 18:58:56 UTC, Marcone wrote:
I've always heard programmers complain about Garbage Collector 
GC. But I never understood why they complain. What's bad about 
GC?


How write quickly without GC ?


In DMD style: never release memory!

This is not an option for long-running programs though, nor for 
anything that otherwise uses significant amounts of memory.


Better to just use the GC if unsure.


Re: Why many programmers don't like GC?

2021-01-14 Thread Виталий Фадеев via Digitalmars-d-learn

On Wednesday, 13 January 2021 at 18:58:56 UTC, Marcone wrote:
I've always heard programmers complain about Garbage Collector 
GC. But I never understood why they complain. What's bad about 
GC?


I like GC.

How write quickly without GC ?



Re: Why many programmers don't like GC?

2021-01-14 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 14 January 2021 at 13:05:31 UTC, sighoya wrote:
But this is already the case for C++ and Rust. Remembering the 
days back developing in C++ there were a huge amount of memory 
deallocation side effects because opencv's memory management 
differs from qt's memory management.


The problem in C++ is that older frameworks have their own ways 
of doing things for performance reasons or because the C++ 
standard they started with didn't provide what they needed...


And... most C++ frameworks that are big are old... If you avoid 
big frameworks then it gets better.


Personally, I find it better to prefer encapsulating manual 
memory management and not to leak them outside.


Yes. Most programmers don't need system level programming. So if 
D defines itself to not be a system level programming language 
then there would be room to improve a lot, but then it should 
move towards more high level features and prevent the usage of 
some low level features like untagged non-discriminating unions 
of pointers. Rust is more high level than D... I think.




Re: Why many programmers don't like GC?

2021-01-14 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
On Thursday, 14 January 2021 at 13:16:16 UTC, Ola Fosheim Grøstad 
wrote:
1. Use "shared" to prevent GC allocated memory from entering 
other threads and switch to thread local GC. Then use ARC for 
shared.


2. Redefine language semantics/type system for a different GC 
model. This will break existing code.


3. Keep the existing GC for existing code and introduce ARC 
across the board for new code. Add a versioning statement that 
people can add to their libraries to tell the compiler which 
models they support.






Re: Why many programmers don't like GC?

2021-01-14 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 14 January 2021 at 13:10:14 UTC, sighoya wrote:
On Thursday, 14 January 2021 at 13:08:06 UTC, Ola Fosheim 
Grøstad wrote:


Because Java has a well defined virtual machine with lots of 
restrictions.


So you're insisting this isn't possible in D?


It isn't possible in a meaningful way.

In system level programming languages you have to manually uphold 
the invariants needed to not break the GC collection algorithm.


So if you change to a significantly different collection model, 
the needed invariants will change.


The possible alternatives are:

1. Use "shared" to prevent GC allocated memory from entering 
other threads and switch to thread local GC. Then use ARC for 
shared.


2. Redefine language semantics/type system for a different GC 
model. This will break existing code.







Re: Why many programmers don't like GC?

2021-01-14 Thread sighoya via Digitalmars-d-learn
On Thursday, 14 January 2021 at 13:08:06 UTC, Ola Fosheim Grøstad 
wrote:


Because Java has a well defined virtual machine with lots of 
restrictions.


So you're insisting this isn't possible in D?


Re: Why many programmers don't like GC?

2021-01-14 Thread sighoya via Digitalmars-d-learn
On Thursday, 14 January 2021 at 11:11:58 UTC, Ola Fosheim Grøstad 
wrote:


I know your response is *tongue in cheek*, but I actually find 
it easier to use c++11 style memory management across the board 
than mixing two models.


But this is already the case for C++ and Rust. Remembering the 
days back developing in C++ there were a huge amount of memory 
deallocation side effects because opencv's memory management 
differs from qt's memory management.

Just to say it was a hell.

Personally, I find it better to prefer encapsulating manual 
memory management and not to leak them outside.


Re: Why many programmers don't like GC?

2021-01-14 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 14 January 2021 at 13:01:04 UTC, sighoya wrote:

Why not offering more than one just as it is the case in Java?
The advantage hereby is to adapt the GC algorithm after the 
program was compiled, so you can reuse the same program with 
different GC algorithms.


Because Java has a well defined virtual machine with lots of 
restrictions.




Re: Why many programmers don't like GC?

2021-01-14 Thread sighoya via Digitalmars-d-learn
As other people already mentioned, garbage collection incurs some 
amount of non-determinism and people working in low level areas 
prefer to handle things deterministically because they think 
non-deterministic handling of memory makes your code slow.


For example rendering in gaming gets paused by the GC prolonging 
the whole rendering process.
The conclusion arrives that code runs slow, but it doesn't. In 
fact, a tracing GC tries to do the opposite, in order to make the 
whole process faster, it releases memory in a buffer like mode 
often yielding faster execution in the long run, but not in the 
short run where it is mandatory not to introduce any kind of 
pauses.


So, in the end, it isn't a fate about performance rather a fate 
of determinism vs non-determinism.


Non-determinism has the potential to let the code run faster.
For instance, no one really uses the proposed threading model in 
Rust with owned values where one thread can only work mutably on 
an owned value because other threads wanting to mutate that value 
have to wait. This works by creating a deterministic order of 
thread execution where each thread can only work after the other 
thread releases its work.
This model gets often praised in Rust but the potential seems 
only a theoretical one.
As a result you most often see the use of atomic reference 
counting (ARC) cluttering in codebases in Rust.


The other point is the increased memory footprint because you 
have a runtime memory manager taking responsibility over 
(de)allocation which is impossible to have in some areas of 
limited memory systems.


However, why just provide a one size fits all solution when there 
are plenty of GC algorithms for different kinds of problem 
domains?

Why not offering more than one just as it is the case in Java?
The advantage hereby is to adapt the GC algorithm after the 
program was compiled, so you can reuse the same program with 
different GC algorithms.




Re: Why many programmers don't like GC?

2021-01-14 Thread claptrap via Digitalmars-d-learn

On Wednesday, 13 January 2021 at 20:06:51 UTC, H. S. Teoh wrote:
On Wed, Jan 13, 2021 at 06:58:56PM +, Marcone via 
Digitalmars-d-learn wrote:
I've always heard programmers complain about Garbage Collector 
GC. But I never understood why they complain. What's bad about 
GC?


It's not merely a technical issue, but also a historical and 
sociological one.  The perception of many people, esp. those 
with C/C++ background, is heavily colored by the GC shipped 
with early versions of Java, which was stop-the-world, 
inefficient, and associated with random GUI freezes and jerky 
animations.  This initial bad impression continues to persist 
today esp. among the C/C++ crowd, despite GC technology having 
made great advances since those early Java days.


Aside from skewed impressions, there's still these potential 
concerns with the GC:


(1) Stop-the-world GC pauses (no longer a problem with modern
generational collectors, but still applies to D's GC);

(2) Non-deterministic destruction of objects (D's dtors are not 
even
guaranteed to run if it's a GC'd object) -- you cannot predict 
when an

object will be collected;

(3) GC generally needs more memory than the equivalent manual 
memory

management system.


I think you also have to consider that the GC you get with D is 
not state of the art, and if the opinions expressed on the 
newsgroup are accurate, it's not likely to get any better. So 
while you can find examples of high performance applications, AAA 
games, or whatever that use GC, I doubt any of them would be 
feasible with Ds GC. And given the design choices D has made as a 
language, a high performance GC is not really possible.


So the GC is actually a poor fit for D as a language. It's like a 
convertible car with a roof that is only safe up to 50 mph, go 
over that and its likely to be torn off. So if you want to drive 
fast you have to put the roof down.





Re: Why many programmers don't like GC?

2021-01-14 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 14 January 2021 at 10:28:13 UTC, Basile B. wrote:

Semi serious answer:

In the domain of hoby-ism and small companies programmers that 
work with statically typed languages all believe that they are 
super hero in the domain of memory managment. When they see 
"GC" they think that they are considered as 2nd grade student ^^


It's basically snobbism.


I know your response is *tongue in cheek*, but I actually find it 
easier to use c++11 style memory management across the board than 
mixing two models.


C style memory management, on the other hand, is pretty horrible 
and you'll end up spend much of your time debugging 
"unexplainable" crashes. I don't experience that much in C++ when 
staying within their standard regime.


When you want more performance than standard C++ memory 
management, things can go wrong e.g. manual emplace strategies 
and forgetting to call destructors etc, but that is the same in 
D. And frankly, you seldom need that, maybe 2-3 critical places 
in your program (e.g. graphics/audio).




Re: Why many programmers don't like GC?

2021-01-14 Thread Basile B. via Digitalmars-d-learn

On Wednesday, 13 January 2021 at 18:58:56 UTC, Marcone wrote:
I've always heard programmers complain about Garbage Collector 
GC. But I never understood why they complain. What's bad about 
GC?


Semi serious answer:

In the domain of hoby-ism and small companies programmers that 
work with statically typed languages all believe that they are 
super hero in the domain of memory managment. When they see "GC" 
they think that they are considered as 2nd grade student ^^


It's basically snobbism.


Re: Why many programmers don't like GC?

2021-01-14 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
On Thursday, 14 January 2021 at 10:05:51 UTC, Guillaume Piolat 
wrote:

On Wednesday, 13 January 2021 at 18:58:56 UTC, Marcone wrote:
I've always heard programmers complain about Garbage Collector 
GC. But I never understood why they complain. What's bad about 
GC?


Languages where the GC usage is unavoidable (Javascript and 
Java) have created a lot of situations where there is a GC 
pause in realtime program and the cause is this dynamically 
allocated memory. So a lot of people make their opinion of GC 
while using setup where you couldn't really avoid it.


Indeed, but I don't think we should underestimate the perceived 
value of having a minimal runtime. Like, if D had a better GC 
solution that involved an even heavier runtime, it would still be 
a big issue for people interested in low level system programming.


Transparency is an issue. System level programming means you want 
to have a clear picture of what is going on in the system at all 
levels, all the way down to the hardware. If you cannot 
understand how the runtime works you also cannot fix issues... so 
a simple runtime is more valuable than a feature rich complex 
runtime.


That is kinda what defines system level programming: you know 
exactly what every subsystem is doing so that you can anticipate 
performance/resource issues. And that is the opposite of high 
level programming where you make no assumptions about the 
underlying machinery and only care about the abstract 
descriptions of language semantics.







Re: Why many programmers don't like GC?

2021-01-14 Thread Guillaume Piolat via Digitalmars-d-learn

On Wednesday, 13 January 2021 at 18:58:56 UTC, Marcone wrote:
I've always heard programmers complain about Garbage Collector 
GC. But I never understood why they complain. What's bad about 
GC?


Languages where the GC usage is unavoidable (Javascript and Java) 
have created a lot of situations where there is a GC pause in 
realtime program and the cause is this dynamically allocated 
memory. So a lot of people make their opinion of GC while using 
setup where you couldn't really avoid it.


For example in Javascript from 10 years ago just using a closure 
or an array literals could make your web game stutter.


Re: Why many programmers don't like GC?

2021-01-14 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 14 January 2021 at 00:37:29 UTC, mw wrote:

ok, what I really mean is:

... in other "(more popular) languages (than D, and directly 
supported by the language & std library only)" ...


Well, even Python supports both, if you want to, so... I suppose 
you mean system level programming languages? The reality is that 
GC for a system level programming language is not popular to 
begin with. In that domain it is fairly common to not use the 
standard library and use custom runtimes as we can see for C and 
C++.


Anyway, what makes the D GC weak is exactly that there is not 
much support for it in the D language or the compilers, only in 
the runtime and the bare minimum of RTTI. LLVM support more 
advanced GC features than D provides.


So, the D GC doesn't do much more for programmers than Boehm. And 
Boehm is not popular either...


Oilpan, that Chrome uses has more advanced features than the D 
GC, and does what most system level programmers want: limits it 
to designated GC types and supports incremental collection. The 
downside is that each Oilpan GC type also has to specify which 
pointers to trace, but then again, not being able to do that in D 
is a disadvantage...


For systems programming, I think D would be better off 
appropriating the approach taken by Oilpan and mix it with 
reference counting, but make it a language/compiler feature. That 
is at least a proven approach for one big interactive 
application. Basically make "D class" objects GC and everything 
else RC or manual.






Re: Why doesn't this work when the function is a static method?

2021-01-14 Thread evilrat via Digitalmars-d-learn

On Thursday, 14 January 2021 at 05:44:43 UTC, Jack wrote:
On Wednesday, 13 January 2021 at 17:21:23 UTC, Paul Backus 
wrote:


Member functions (including static ones) can't be called with 
UFCS.



 is this documented somewhere? Is this going to change?


It will stay as is.
It is somewhat vaguely described in p.7 under UFCS section in 
functions


https://dlang.org/spec/function.html#pseudo-member