Re: Program crash: GC destroys an object unexpectedly

2021-09-14 Thread Ali Çehreli via Digitalmars-d-learn

On 9/14/21 9:56 AM, eugene wrote:

> On Tuesday, 14 September 2021 at 16:43:50 UTC, jfondren wrote:

>> The misaligned pointer and the
>> reference-containing struct that vanishes on the return of your
>> corresponding function are both problems for this.
>
> where did you find 'misaligned pointer'?...

I think it's the align(1) for EpollEvent.

I was able to reproduce the segmentation fault and was seemingly able to 
fix it by making the EventSource class references alive by adding a 
constructor:


align (1) struct EpollEvent {
align(1):
uint event_mask;
EventSource es;

  this(uint event_mask, EventSource es) {
this.event_mask = event_mask;
this.es = es;
living ~= es;  // <-- Introduced this constructor for this line
  }
/* just do not want to use that union, epoll_data_t */
}

// Here is the array that keeps EventSource alive:
EventSource[] living;

If that really is the fix, of course the references must be taken out of 
that container when possible.


Ali



Re: Building several dynamic libraries with one shared GC

2021-09-12 Thread Ali Çehreli via Digitalmars-d-learn

On 9/12/21 1:25 PM, NonNull wrote:

On Sunday, 12 September 2021 at 18:56:50 UTC, Ali Çehreli wrote:
All initialization functions of the plugins were called automatically 
in my D test environment and all plugins were usable. The trouble 
started when the main library was being used in a foreign environment 
(something like Python loading Python loading C++ library loading our 
D library): Although the initialization function of the main library 
was being called, the 'shared static this' functions of the plugins 
were not being called.


So here, your main dynamic library in turn dynamically loads plugins. 
Did you try simply calling a function exported by a plugin from the 
static constructor in the main library after it had made the call to 
initialize druntime to see if that stimulated running the plugin's 
static constructors first? The problem you linked to suggests that might 
do the job. I haven't run into this problem yet myself. But I'm interested.


I did not try it because I learned about that potential cause after we 
worked around the issue with the daemons.


Ali




Re: Building several dynamic libraries with one shared GC

2021-09-12 Thread Ali Çehreli via Digitalmars-d-learn

On 9/12/21 7:31 AM, NonNull wrote:
> I am making a plug-in development system for a high performance Linux
> application that already exists and is written in C and will not be
> modified for this purpose.

I've done something similar but in my case the main application is in D 
and the plugins are code-generated D (hand edited by non-D developers).


However, as is common in software, the requirements changed :) and we 
wanted to use it as a library as well; so, plugins became part of a main 
D library (which exposed C functions).


All initialization functions of the plugins were called automatically in 
my D test environment and all plugins were usable. The trouble started 
when the main library was being used in a foreign environment (something 
like Python loading Python loading C++ library loading our D library): 
Although the initialization function of the main library was being 
called, the 'shared static this' functions of the plugins were not being 
called.


(I tried dlopen after guessing intelligently the name of the 'shared 
static this' function (not obvious); it was not satisfactory and I don't 
remember exactly why not.)


Later I learned, this could be because merely loading a plugin might not 
be enough, and perhaps the main library might have to use a feature of 
the library as well:


  https://forum.dlang.org/post/sdb5jb$2rk3$1...@digitalmars.com

If that link indeed explains the issue, I did not know about it when we 
worked around the initialization problem by running a D daemon per 
thread behind this main library.


Each thread of the library passes information to its daemon through 
shared memory and the daeman does it's thing and returns the result 
back. (The difference is, the plugins are linked to the daemon; avoiding 
the problem initialization scenario; 'shared static this' are called 
from a D environment.)


> If several plugins are built by different third parties, each dynamic
> library will have its own GC and copy of druntime right now.

Like the user 'frame', I don't think that's the case.

Going off topic, I started thinking about this "one daemon per library 
thread" idea: becaues I am under the impression that running multiple 
daemons does not put much stress on the system under Linux, this idea 
can automatically translate to "independent GCs for each thread". For 
example, the main library has 10 threads using 10 separate daemons on 
their backgrounds; each daemon handles its own GC needs without even 
knowing about the other daemons that are effectively working for the 
same main library. I haven't experimented with this yet.


Ali



Re: Ali's Book - Programming in D

2021-09-10 Thread Ali Çehreli via Digitalmars-d-learn

On 9/10/21 11:05 AM, Ron Tarrant wrote:

On Friday, 10 September 2021 at 14:21:12 UTC, Ali Çehreli wrote:

tldr; Yes, it's print-on-demand and 2019 is correct for the current 
print edition. I would download the PDF version from ddili.org.



D version: 2.094.2
Book revision: 2021-02-26


Off the top of your head, do you know how much difference there is 
between the 2019 and 2021 version?


Not off the top of my head but by actual commits. :)

  https://bitbucket.org/acehreli/ddili/commits/

One major change that I can see is @property being discouraged.

Ali



Re: Ali's Book - Programming in D

2021-09-10 Thread Ali Çehreli via Digitalmars-d-learn

On 9/10/21 4:48 AM, Ron Tarrant wrote:
> On Friday, 10 September 2021 at 10:59:10 UTC, bauss wrote:
>
>> Publisher ‏ : ‎ CreateSpace Independent Publishing Platform; 1st
>> edition (Aug. 19 2015)
>
> Yeah, I saw that, too. And if you do a "Look inside," the copyright date
> is 2019... thus my question. :)

tldr; Yes, it's print-on-demand and 2019 is correct for the current 
print edition. I would download the PDF version from ddili.org.


The following is a list of different versions of the book.

1) The git clone on my computer is the newest, which I may sit on for 
weeks for minor corrections. (These corrections are recommended by most 
of you; thank you!) So, this version would have today's date and the 
code samples in the book (some of them) would be checked with the dmd 
version installed on my computer.


2) Although updating the site is pretty much automated and free, I may 
not bother updating the site for minor corrections.


If you are happy with a PDF version, the PDF at ddili.org is almost 
always newer and formatted in almost exactly the same way. The only 
format differences are that the online PDF version has colored code 
samples and it does not have a book cover.


Currently, the online PDF version says

D version: 2.094.2
Book revision: 2021-02-26

3a) The PDF version given to the printers is older partly because 
updates have some restrictions (e.g. a number of times per certain 
number of weeks) and updating them requires some labor.


I see from your message that the current print versions are from 2019.

3b) The ebook versions may be even older mostly because they require 
much more labor. (Passing the HTML through Calibre , clicking the 
correct boxes, etc.)


But I think the ebook versions are the same as the printer versions as 
of this writing.



Although I am very happy with the appreciation it gets, of course there 
are many parts of the book that I want to improve. Some parts even make 
me cringe. :)


- I am embarrassed that the copy constructors still are not in the book. 
(Post-blit is featured.)


- I want to rewrite parts of the "Imutability" chapter after emails from 
Don Allen. It was written before I understood immutable better. There 
are many examples in the book that use 'immutable' even though I always 
use 'const' in my own code:


  immutable a = Foo();  // Should be only when really necessary
  const b = Foo();  // Should be used almost always

I see people write 'immutable' on these forums and I feel guilty about 
it. :/


- I can't understand where I got the initial motivation to finish the 
book. I don't have it now. :/


- I want to thank Steven Schveighoffer here once more for his help with 
the book. I later realized that his name should have much more 
prominence. I can't understand how my older self did not realize this 
fact when the book was being finalized.


Ali




Re: Documentation generator is not working

2021-09-05 Thread Ali Çehreli via Digitalmars-d-learn

On 9/5/21 3:22 PM, Vinod K Chandran wrote:

On Friday, 3 September 2021 at 20:21:43 UTC, Ali Çehreli wrote:


So, change your program to respond to -D and generate the 
documentation potentially by spawning a dmd instance. :o)



I am not sure i get the point correctly. You mean, starting dmd as a new 
process from my program and pass the file name as parameter ?


Yes, but it was meant to be a joke. Don't do that. :)

Ali



Re: Forum posting question ... how post a thread question with color syntax highlighting ??

2021-09-05 Thread Ali Çehreli via Digitalmars-d-learn

On 9/5/21 4:24 PM, someone wrote:
>
> For example; IIRC Ali's posts are always no-markdown.
>

That's because I've been using Thunderbird for mail and news for a long 
time now and unfortunately it is impossible to convince Thunderbird to 
add the necessary header field. (Vladimir has a recommendation where I 
can run a simply local server that augments Thunderbird's headers but I 
haven't tried it yet.)


I should go back to using Emacs for news. I am pretty sure it will be 
configurable.


Ali



Re: "+=" (overloads) with custom array slices on both lhs, and rhs ??

2021-09-05 Thread Ali Çehreli via Digitalmars-d-learn

On 9/5/21 12:43 PM, james.p.leblanc wrote:

> I have constructed a custom array type that works, but is missing
> correct functioning on some operator overloads.

With its old, new, and newest styles; and support for multi-dimensional 
use cases; operator overloading can be difficult to get right. Here is a 
one-dimensional case that works:


struct MyArray(T) {
  T[] elements;

  this(size_t length) {
this.elements.length = length;
  }

  size_t opDollar() const {
return elements.length;
  }

  auto opSliceOpAssign(string op)(T value, size_t beg, size_t end) {
auto slice = elements[beg .. end];
mixin (format!q{
slice[] %s= value;
  }(op));
return slice;
  }

  // For the entire range of elements
  auto opSliceOpAssign(string op)(T value) {
// Dispatch to the other one
return this.opSliceOpAssign!op(value, 0, elements.length);
  }
}

import std.stdio;
import std.format;

void main() {
  auto m = MyArray!(int)(10);

  m[2 .. 5] += 42;
  writeln(m);

  m[4 .. $] -= 100;
  writeln(m);

  m[] *= 2;
  writeln(m);
}

Ali



Re: Documentation generator is not working

2021-09-03 Thread Ali Çehreli via Digitalmars-d-learn

On 9/2/21 10:38 AM, Vinod K Chandran wrote:

On Thursday, 2 September 2021 at 17:34:59 UTC, Adam D Ruppe wrote:


Anything after -run goes to your program not the compiler.

Args to the compiler must be before -run.


Thanks for the reply. Got the point now. :)



So, change your program to respond to -D and generate the documentation 
potentially by spawning a dmd instance. :o)


Ali




Re: Run-time setting of immutable variable?

2021-09-02 Thread Ali Çehreli via Digitalmars-d-learn

On 9/2/21 9:01 AM, DLearner wrote:
Suppose there is a variable that is set once per run, and is (supposed) 
never to be altered again.


An accessor function can be a solution, which supports your other 
comment about data potentially mutating by other means:


// Assume these are in a module
// 

// This is private; you can even name it arr_.
private
ubyte[10] arr;

// This is the accessor:
public
const(ubyte)* arrPtr() {
  return arr.ptr;
}
// 

void main() {
  *arrPtr = 42;  // Compilation ERROR; good.
}

Ali


Re: Labelled @nogc Working With Inner Scopes

2021-08-30 Thread Ali Çehreli via Digitalmars-d-learn
I don't have a strong opinion on the question but I tend to agree with 
the current behavior because it's easy to add the attributes anyway.


Going off topic, I want to mention that the 'in' and 'out' contracts 
have a simpler syntax now and that the 'do' (or 'body') keyword is 
optional in that place:


struct Dummy
{
// ...

  this(int memberInt, string memberStr) nothrow
  in (memberInt > MAX_MEMBER_INT, "You can put a message here")
  out (; this.memberInt == memberInt, "etc.")
  out (; this.memberStr == memberStr, "etc.")
  {
this.memberInt = memberInt;
this.memberStr = memberStr;
  }
}

I am reminded that the semicolons in the 'out' contracts are necessary 
even for a function that does not return a value (like a constructor 
does not).


Ali



Re: pipeProcess, interactions with stderr ... I am missing something here

2021-08-30 Thread Ali Çehreli via Digitalmars-d-learn

On 8/30/21 9:35 AM, james.p.leblanc wrote:
> D-ers,
>
> I am attempting to use pipeProcess for interacting with an external
> process.
> My simplified routine can work somewhat.  But, trying to print any 
messages

> that process writes to stderr yields the message:
>
> (master) gnuplot > gnuplot_example
> **core.exception.InvalidMemoryOperationError@src/core/exception.d(647):
> Invalid memory operation**

That error almost always means you are allocating memory in a 
destructor, which sometimes is presumably due to using parts of your 
object that have already been finalized by the GC. (Or, the GC has 
already been terminated? I am not sure.)


In this case, converting your ~this to a named function solves the issue:

  // Was: ~this()
  void close() {
// ...
  }

// ...

  auto gp = new Gnuplot();
  scope (exit) {
gp.close();
  }

Ali



Re: template parameters

2021-08-29 Thread Ali Çehreli via Digitalmars-d-learn

On 8/29/21 3:31 PM, Charles Hixson wrote:
> Thanks.  I going to have to study:
>
> enum supportsCall = isIntegral!(typeof(T.init.%s()));
>
>
> for awhile to make any sense of that, but it looks like just what I was
> looking for.

Trying to explain with comments:

// This is an eponymous template because it contains
// a symbol that's the same as the name of this template.
// And that symbol is 'supportsCall'. So, this template
// will be whatever that symbol is. (In this case, it
// will be a compile-time know entity: 'enum bool'.)

template supportsCall(T, string func) {
  import std.format : format;
  import std.traits : isIntegral;

  // This is a string expression we will mix-in below.
  enum expr = format!q{
enum supportsCall = isIntegral!(typeof(T.init.%s()));
  }(func);

  // The above expression will be the following e.g.
  // for 'int' and for "ndx":
  //
  //   enum supportsCall = isIntegral!(typeof(int.init.ndx()));
  //
  // So, it's determining whether the typeof the expression
  // int.init.ndx() is an integral.
  //
  // 'supportsCall' is a bool, which I could have made explicit:
  //
  //   enum bool supportsCall = [...]
  //
  // You can prove it for yourself by "printing" the expression
  // at compile time:

  pragma(msg, expr);

  // Here is where we mix-in the expression into this template's
  // definition.

  mixin (expr);
}

Then the whole template can be used as a compile-time bool value.

Ali



Re: template parameters

2021-08-29 Thread Ali Çehreli via Digitalmars-d-learn

On 8/29/21 11:32 AM, Charles H. wrote:

I've set up a class template (so far untested) thus:

     class    AARL (T, ndx = "ndx")
     if (isIntegral(T.init.ndx) )

     If I'm correct, this should work for ndx an integer variable of T, 
but I'd really like T to be able to be anything which can be stored both 
in an array and in an associative array.  But I can't figure out how to 
specify ndx.  After all, T might be a float, so it wouldn't have any 
appropriate attributes.  And I'd also like ndx to be able to be a 
function either a member of the class/struct T or a stand alone function.


So how should I set up this template?



I came up with the following:

template supportsCall(T, string func) {
  import std.format : format;
  import std.traits : isIntegral;

  enum expr = format!q{
enum supportsCall = isIntegral!(typeof(T.init.%s()));
  }(func);

  mixin (expr);
}

class AARL (T, string func = "ndx")
if (supportsCall!(T, func)) {
}

int ndx(int i) {
  return 42;
}

struct S {
  long ndx() {
return 100;
  }
}

void main() {
  auto a = new AARL!int();
  auto b = new AARL!S();
}

Ali



Re: byte + byte = int: why?

2021-08-29 Thread Ali Çehreli via Digitalmars-d-learn

On 1/18/19 9:09 AM, Mek101 wrote:

>  source/hash.d(11,25): Error: cannot implicitly convert expression
> `cast(int)temp[fowardI] + cast(int)temp[backwardI]` of type `int` to 
`byte`


Others suggested casting as a solution which works but it will hide 
potential errors.


Depending on the situation, you may want to use std.conv.to, which does 
a value range check and throws an exception to prevent an error:


byte foo(byte a, byte b) {
  import std.conv : to;
  return (a + b).to!byte;
}

void main() {
  foo(42, 42);// Works
  foo(100, 100);  // Throws ConvOverflowException
}

Of course, because of the checks, 'to' is slower than casting blindly.

Ali



Re: byte + byte = int: why?

2021-08-29 Thread Ali Çehreli via Digitalmars-d-learn

On 8/29/21 3:57 AM, Rekel wrote:

On Friday, 18 January 2019 at 18:49:23 UTC, Steven Schveighoffer wrote:
As others have said, those are the rules D has for historical reasons, 
you just have to deal with them.


Is that to ensure compatibility with C?



Yes. It's mentioned multiple times in this zombie-ish thread. :)

Ali


Re: A little help with Ranges

2021-08-26 Thread Ali Çehreli via Digitalmars-d-learn

On 8/26/21 7:17 PM, Merlin Diavova wrote:

What I meant about the handling an empty filter is, what if I want to 
take an alternative route if the filter returns empty?


Then the operations downstream will not produce any results. For 
example, the array will be empty below:


import std.stdio;
import std.range;
import std.algorithm;
import std.string;
import std.functional;

void main() {
  auto significantLines = stdin
  .byLineCopy
  .map!strip
  .filter!(not!empty)
  .filter!(line => line.front != '#')
  .array;

  if (significantLines.empty) {
writeln("There were no significant lines.");

  } else {
writefln!"The lines: %-(\n%s%)"(significantLines);
  }
}

Ali


Re: Scope of Mixins

2021-08-26 Thread Ali Çehreli via Digitalmars-d-learn

On 8/26/21 10:45 AM, Adam D Ruppe wrote:

On Thursday, 26 August 2021 at 17:39:16 UTC, Ali Çehreli wrote:
String mixins are appealing because they can inject code like C macros 
do. It's not trivially possible to do the same with template mixins.


Template mixins are great, but obviously totally inappropriate here. I'm 
just talking about using a normal function, possibly with an alias 
argument, instead of any kind of mixin.


Too often D programmers reach for fancy code generation when a simpler 
function is a better fit.


Agreed. Something like the following for the OP:

import std.traits : isPointer;

auto valueFrom(T)(T var)
if (isPointer!(typeof(var))) {
  return *var;
}

auto valueFrom(T)(T var)
if (!isPointer!(typeof(var))) {
  return var;
}

void main() {
  int x;
  int i = 42;
  x = valueFrom(i);

  int * p = 
  x = valueFrom(p);
}

In some cases it's more useful to have a 'static if' inside a single 
function template instead of two separate function templates.


Ali



Re: Scope of Mixins

2021-08-26 Thread Ali Çehreli via Digitalmars-d-learn

On 8/26/21 10:06 AM, Adam D Ruppe wrote:

On Thursday, 26 August 2021 at 17:01:06 UTC, DLearner wrote:
The object was to take a variable, and do alternative things with it 
depending on (say) whether it was an 'int' or an 'int*'.


That's *very* easy to do with the alias. You can just check `typeof(v)` 
in there.


String mixins are appealing because they can inject code like C macros 
do. It's not trivially possible to do the same with template mixins.


import std.traits : isPointer;
import std.stdio : writeln;

mixin template valueFrom(alias var)
if (isPointer!(typeof(var))) {
  writeln("Dereferencing a pointer");  // ERROR
  x = *var;
}

mixin template valueFrom(alias var)
if (!isPointer!(typeof(var))) {
  writeln("Using a scalar");   // ERROR
  x = var;
}

void main() {
  int x;
  int i = 42;
  mixin valueFrom!i;

  int * p = 
  mixin valueFrom!p;
}

Yes, there are tricks one can play or change the design but when it 
comes to "injecting code", template mixins are not as convenient as 
string mixins.


Ali


Re: foreach() behavior on ranges

2021-08-24 Thread Ali Çehreli via Digitalmars-d-learn

On 8/24/21 1:44 PM, Ferhat Kurtulmuş wrote:

> Just out of curiosity, if a range implementation uses malloc in save, is
> it only possible to free the memory with the dtor?

Yes but It depends on the specific case. For example, if the type has a 
clear() function that does clean up, then one might call that. I don't 
see it as being different from any other resource management.


> Is a save function only meaningful for GC ranges?

save() is to store the iteration state of a range. It should seldom 
require memory allocation unless we're dealing with e.g. stdin where we 
would have to store input lines just to support save(). It would not be 
a good design to hide such  potentilly expensive storage of lines behind 
save().


To me, save() should mostly be as trivial as returning a copy of the 
struct object to preserve the state of the original range. Here is a 
trivial generator:


import std.range;

struct Squares {
  int current;

  enum empty = false;

  int front() const {
return current * current;
  }

  void popFront() {
++current;
  }

  auto save() {
return this;
  }
}

void main() {
  auto r = Squares(0);
  r.popFront();  // Drop 0 * 0
  r.popFront();  // Drop 1 * 1

  auto copy = r.save;
  copy.popFront();  // Drop 2 * 2 only from the copy

  assert(r.front == 2 * 2);  // Saved original still has 2 * 2
}

Ali




Re: Possible to overload assignment of struct field ??

2021-08-23 Thread Ali Çehreli via Digitalmars-d-learn

On 8/23/21 10:25 PM, james.p.leblanc wrote:

So, you need a "property". Easy... :)

1) Rename the member e.g. as a_.

2) Write setter and getter functions named 'a'.

struct Foo{
  int a_;

  int a() const {
return a_;
  }

  void a(int value) {
a_ = value;
  }
}

void main(){
  auto x = Foo(1);
  x.a = 100;
  assert(x.a == 100);
}

Ali


Re: Potential strategy for avoiding problems with copy of a struct (maybe??)

2021-08-22 Thread Ali Çehreli via Digitalmars-d-learn

On 8/22/21 6:03 AM, james.p.leblanc wrote:

>  struct Foo {
>  int a, b, c;
>  Foo* myadd;
>
>  this(int a, int b, int c) {
>  this.a = a;
>  this.b = b;
>  this.c = c;
>  this.myadd = 

As Matthias Lang mentioned, keeping a reference to itself makes a struct 
object illegal in D. D sees structs as value types: It is supposed that 
any copy can be used in place of another copy.


Ali



Re: modules and mains

2021-08-21 Thread Ali Çehreli via Digitalmars-d-learn

On 8/21/21 8:46 PM, Brian Tiffin wrote:

> prompt$ cat B.d
> module B;
> version = boss;

A cannot know about 'version' condition inside B.

The solution is to provide version on the command line. This is how I do 
it with dmd:


$ dmd -version=boss [...]

(So, remove 'version = boss;' line in B.d)

> But I'm getting a link error from gdc
>
> ```
> prompt$ gdc -o B B.d
> /tmp/ccWg1BrF.o: In function `_Dmain':
> B.d:(.text+0x52): undefined reference to `_D1A7commandFAAyaZi'
> collect2: error: ld returned 1 exit status
> ```
>
> Is it just wrong thinking and *try again, ya noob*?   ;-)

Never! :)

D modules work both like C's .h files and .c files. (Well, more like 
C++'s .h files because templates don't need .cpp part.) We import for 
declarations but we must also include for linking. Again, this is how it 
works with dmd:


$ dmd B.d A.d -version=boss

Another option is to use dmd's -i switch, which automatically includes 
modules for linking but I don't have experience with it other than it works:


$ dmd B.d -version=boss -i

(-i can take a pattern as well.)

Ali



Re: Unqualified class name

2021-08-21 Thread Ali Çehreli via Digitalmars-d-learn

On 8/21/21 2:48 PM, jfondren wrote:

On Saturday, 21 August 2021 at 21:13:58 UTC, Jeremy T. Gibson wrote:

On Saturday, 21 August 2021 at 18:27:34 UTC, Ali Çehreli wrote:

    return __traits(identifier, typeof(this));


That works perfectly!  Thanks. =)


This is exactly the solution you linked to in your first post, and found 
wanting.


```d
class Whoami {
     string name() {
     return __traits(identifier, typeof(this));
     }
}
class AnotherOne : Whoami { }

unittest {
     assert((new Whoami).name == "Whoami");
     assert((new AnotherOne).name == "Whoami");
}
```


I did not read the linked thread but a "this template parameter" seems 
to work in this case:


class Whoami {
  string name(this This)() const {
return __traits(identifier, This);
  }
}
class AnotherOne : Whoami { }

unittest {
  assert((new Whoami).name == "Whoami");
  assert((new AnotherOne).name == "AnotherOne");
}

void main() {
}

Ali



Re: Unqualified class name

2021-08-21 Thread Ali Çehreli via Digitalmars-d-learn

On 8/21/21 10:33 AM, Jeremy T. Gibson wrote:

`typeid(class).name` always yields the full classname, including its 
module information (i.e., "modulename.classname"), where I only want 
"classname" on its own.


I've been reminded of __traits(identifier) on this forum just yesterday:

import std.stdio;

class Coo {

  string name() const {
return __traits(identifier, typeof(this));
  }
}

void main() {
  auto c = new Coo();
  writeln(c.name());
}

Ali


Re: Lexicographical object comparison by selected members of a struct

2021-08-21 Thread Ali Çehreli via Digitalmars-d-learn

On 8/21/21 1:31 AM, Tejas wrote:

> I was more impressed that you found that hack in the first place

I can't take credit. :) 'static foreach' had that difference since its 
inception. The spec says "If a new scope is desired for each expansion, 
use another set of braces:"


  https://dlang.org/spec/version.html#staticforeach

Ali



Re: Lexicographical object comparison by selected members of a struct

2021-08-21 Thread Ali Çehreli via Digitalmars-d-learn

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

On Saturday, 21 August 2021 at 06:03:33 UTC, Ali Çehreli wrote:

On 8/20/21 10:37 PM, Alexandru Ermicioi wrote:

[...]


Cool! Much better. :)

I could not do

[...]


Did you use that double curly bracket in `static foreach` so that you 
don't get error for declaring stuff inside `static foreach` ?


Yes. 'static foreach' does not introduce scope, which can be pretty 
useful. For example, one can define functions at module scope.


The subtle differences between 'static foreach' and '(compile-time) 
foreach' can be surprising. For example, I don't understand why I can't use


  foreach (i; 0 .. members.length) {
enum ident = __traits(identifier, members[i]);
// ...
  }

Error: variable `i` cannot be read at compile time.

I think it should be. :) members.length is compile-time; so, 'i' should 
be compile time.


And then, why can't 'static foreach' iterate over 'members'?

  static foreach (member; members) {{
// ...
  }}

Error: value of `this` is not known at compile time

Hm? Well, I am happy that there is always a path through. :)

Ali




Re: Lexicographical object comparison by selected members of a struct

2021-08-21 Thread Ali Çehreli via Digitalmars-d-learn

On 8/20/21 10:37 PM, Alexandru Ermicioi wrote:

On Saturday, 21 August 2021 at 05:34:59 UTC, Alexandru Ermicioi wrote:

...


Also there is no need for mixing string code here. You can get the field 
using __traits(getMember, this, member).


Cool! Much better. :)

I could not do

  static foreach (member; members) {{
// ...
  }}

So I am happy with iterating over 0 .. members.length.

// Mixes in opEquals() and opCmp() that perform lexicographical
// comparisons according to the order of 'members'.
mixin template MemberwiseComparison(members...) {
  bool opEquals(const typeof(this) that) const {

// Comparison code per member, which would potentially return an
// early 'false' result.
static foreach (i; 0 .. members.length) {{
  // mixin (makeCode(__traits(identifier, members[i])));
enum ident = __traits(identifier, members[i]);

if (__traits(getMember, this, ident) != __traits(getMember, 
that, ident)) {

  return false;
}
}}

// There was no mismatch if we got here.
return true;
  }

  int opCmp(const typeof(this) that) const {

// Comparison code per member, which would potentially return an
// early before or after decision.
static foreach (i; 0 .. members.length) {{
  enum ident = __traits(identifier, members[i]);

  if (__traits(getMember, this, ident) < __traits(getMember, that, 
ident)) {

return -1;
  }
  if (__traits(getMember, this, ident) > __traits(getMember, that, 
ident)) {

return 1;
  }
}}

// Neither 'this' nor 'that' was before if we got here.
return 0;
  }
}

Ali



Lexicographical object comparison by selected members of a struct

2021-08-20 Thread Ali Çehreli via Digitalmars-d-learn
Sometimes I need comparison operators that should consider only some 
members of a struct:


struct S {
  int year; // Primary member
  int month;// Secondary member

  string[] values;  // Irrelevant
}

I've been using the laziest tuple+tupleof solution in some of my structs:

  bool opEquals(const typeof(this) that) {
import std.typecons : tuple;

return tuple(this.tupleof).opEquals(tuple(that.tupleof));
  }

  // Similar for opCmp.

That is repetitive, expensive at run time, and does not satisfy a 
requirement: Some members (like 'values' above) should not be considered 
during comparison.


I am sure you must have come up with similar solutions like the 
following code, or perhaps this whole thing exists in Phobos but I just 
wrote it today... for fun... :) (I think it exists somewhere but I could 
not find it.)  The code is not used in production yet but it should 
allow me to do the following:


struct S {
  int year; // Primary member
  int month;// Secondary member

  string[] values;  // Irrelevant

  mixin MemberwiseComparison!(year, month);  // 'values' excluded; good
}

What do you think?

I have a feeling that e.g. extracting member names from the strings like 
"this.foo" with the help of findSplitAfter(members[i].stringof) is 
pretty suspect. Could I do better?


At least the generated assembly is minimal to my eyes. (Much better than 
my lazy tuple+tupleof complication! :) )


// This helper function is defined outside of MemberwiseComparison
// because we don't want to mixin such a member function into user
// structs.
private string memberName(string thisName) {
  import std.algorithm : findSplitAfter;
  import std.exception : enforce;
  import std.range : empty;
  import std.format : format;

  const found = thisName.findSplitAfter(".");
  enforce(!found[0].empty,
  format!`Failed to find '.' in "%s"`(thisName));

  return found[1];
}

unittest {
  assert(memberName("this.foo") == "foo");

  // It should throw when no '.' is found.
  import std.exception;
  assertThrown(memberName("woo/hoo"));
}

// Mixes in opEquals() and opCmp() that perform lexicographical
// comparisons according to the order of 'members'.
mixin template MemberwiseComparison(members...) {
  bool opEquals(const typeof(this) that) const {

// A nested function that makes a comparison expression.
string makeCode(string name) {
  import std.format : format;

  return format!q{
const a = this.%s;
const b = that.%s;

if (a != b) {
  // Early return at first mismatch
  return false;
}
  }(name, name);
}

// Comparison code per member, which would potentially return an
// early 'false' result.
static foreach (i; 0 .. members.length) {{
  mixin (makeCode(memberName(members[i].stringof)));
}}

// There was no mismatch if we got here.
return true;
  }

  int opCmp(const typeof(this) that) const {

// A nested function that makes a comparison expression.
string makeCode(string name) {
  import std.format : format;

  return format!q{
const a = this.%s;
const b = that.%s;

if (a < b) {
  // 'this' is before; early return
  return -1;
}

if (a > b) {
  // 'this' is after; early return
  return  1;
}
  }(name, name);
}

// Comparison code per member, which would potentially return an
// early before or after decision.
static foreach (i; 0 .. members.length) {{
  mixin (makeCode(memberName(members[i].stringof)));
}}

// Neither 'this' or 'that' was before if we got here.
return 0;
  }
}

unittest {
  struct S {
int i;
double d;
string s;

// Only i and d are considered for this type.
mixin MemberwiseComparison!(i, d);
  }

  // The order is decided by the first member.
  assert(S(1, 2) < S(2, 2));
  assert(S(3, 2) > S(2, 2));

  // The order is decided by the second member.
  assert(S(1, 2) < S(1, 3));
  assert(S(1, 2) > S(1, 1));

  // Objects are equal regardless of the third member.
  assert(S(7, 42, "hello") == S(7, 42, "world"));
}

void main() {
}

Ali


Re: Non-consistent implicit function template specializations

2021-08-18 Thread Ali Çehreli via Digitalmars-d-learn

On 8/18/21 4:10 AM, Rekel wrote:

>>   isArray!T && (isArray!(ElementType!T))
>
> I tried looking into how isArray is defined. Like, does being able to
> index mean it's an array, or are these only static &/or dynamic arrays?

The definitions are in phobos/std/traits.d

  enum bool isArray(T) = isStaticArray!T || isDynamicArray!T;

isStaticArray uses the compiler's __traits feature:

  enum bool isStaticArray(T) = __traits(isStaticArray, T);

isDynamicArray uses the is expression but apparently has some history:

template isDynamicArray(T)
{
static if (is(T == U[], U))
enum bool isDynamicArray = true;
else static if (is(T U == enum))
// BUG: isDynamicArray / isStaticArray considers enums
// with appropriate base types as dynamic/static arrays
// Retain old behaviour for now, see
// https://github.com/dlang/phobos/pull/7574
enum bool isDynamicArray = isDynamicArray!U;
else
enum bool isDynamicArray = false;
}

Ali



Re: Concurrency message passing

2021-08-17 Thread Ali Çehreli via Digitalmars-d-learn

On 8/17/21 11:36 AM, JG wrote:

>>> Maybe message parsing isn't the
>>> correct solution?

I use message passing in many of my programs.

> After being populated it should be passed to
> the other thread and no references are kept.

Then you simply cast to-and-from 'shared' and be happy with it. :) I 
explain what I do here:


  https://www.youtube.com/watch?v=dRORNQIB2wA=1735s

Ali



Re: Non-consistent implicit function template specializations

2021-08-17 Thread Ali Çehreli via Digitalmars-d-learn

On 8/17/21 2:59 AM, Rekel wrote:

> template TFoo(T){ void foo(){writeln("1");} } // #1
> template TFoo(T : T[])  { void foo(){writeln("2");} } // #2

I don't have such problems because I am not smart enough to understand 
that syntax so I don't use it. :) I use template constraints (which have 
other problems).


import std.traits;
import std.stdio;

template TFoo(T)
if (!isArray!T)
{
  void foo(){
writeln("not array");
  }
}

template TFoo(T)
if (isArray!T)
{
  void foo(){
writeln("array");
  }
}

void main() {
  TFoo!(int).foo();
  TFoo!(int[]).foo();
}

If you want 2 dimensional arrays, then you can use

import std.range;

  isArray!T && (isArray!(ElementType!T))

Ali



Re: simple (I think) eponymous template question ... what is proper idimatic way ?

2021-08-17 Thread Ali Çehreli via Digitalmars-d-learn

On 8/17/21 11:11 AM, james.p.leblanc wrote:

> auto foo(T)(T a, T b) { ... }
>
> Now, suppose I need to restrict "T" only certain subsets of variable 
types.


There are template constraints:

import std.traits;

auto foo(T)(T a, T b)
if (isArray!T) {
  // ...
}

auto foo(T)(T a, T b)
if (isFloatingPoint!T)
{
  // ...
}

void main() {
  foo(1.5, 2.5);
}

See __traits as well and of course you can use any compile-time check in 
the template constraint.


> I can imagine putting in some "static if" statements in my function body,

That method can display an intelligible error message if there is only 
one template implementation. Template constraints on the other hand, are 
not errors; they just determine what template implementations are 
available for instantiation for the used parameters.


And of course, 'static if' has more uses other than just error 
reporting; which might be performed better with 'static assert'.


Ali



Re: Drawbacks of exceptions being globally allocated

2021-08-15 Thread Ali Çehreli via Digitalmars-d-learn

On 8/15/21 2:10 AM, Alexandru Ermicioi wrote:

>> This may be useful in some cases but in general, these colatteral
>> exceptions don't carry much information and I don't think anybody
>> looks at them. Usually, the first one is the one that explains the
>> error case.

> That is just an assumption.

Agreed but it's based on hands-on experience as well as exposure to 
these forums. :)


> There could be designs where original
> exception gets wrapped in another one

Wrapping is different and yes, it is useful. There have been cases where 
I hit a ConvException which only tells me a conversion failed. I do 
catch and augment it in outer contexts to saying something similar ot 
"That happened while doing this".


> Regarding exception chaining, do you mean that it will automatically get
> chained, even without explicitly passing it as constructor of wrapping
> exception?

Yes. That's the functionality which isn't very useful because the 
collateral exceptions are usually because of the main one: Imagine the 
file system is full and a destructor cannot flush a file. The 
destructor's error is not interesting in this case.


class Main : Exception {
  this() {
super("Main failed");
  }
}

class Dtor : Exception {
  this() {
super("The destructor failed");
  }
}

struct S {
  ~this() {
throw new Dtor();
  }
}

import std.stdio;

void main() {
  try {
auto s = S();
throw new Main();

  } catch (Exception exc) {
stderr.writeln("Failed: ", exc.msg);
stderr.writeln("This failed too: ", exc.next.msg);
// (Of course, real code should stop when 'next' is null.)
  }
}

That output contains two automatically chained exceptions:

Failed: Main failed
This failed too: The destructor failed

Ali



Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread Ali Çehreli via Digitalmars-d-learn
Lot's of great information and pointers already. I will try from another 
angle. :)


On 8/14/21 11:10 PM, rempas wrote:

> So when I'm doing something like the following: `string name = "John";`
> Then what's the actual type of the literal `"John"`?

As you say and as the code shows, there are two constructs in that line. 
The right-hand side is a string literal. The left-hand side is a 'string'.


>> Strings are not 0 terminated in D. See "Data Type Compatibility" for
>> more information about this. However, string literals in D are 0
>> terminated.

The string literal is embedded into the compiled program as 5 bytes in 
this case: 'J', 'o', 'h', 'n', '\0'. That's the right-hand side of your 
code above.


'string' is an array in D and arrays are stored as the following pair:

  size_t length;// The number of elements
  T * ptr;  // The pointer to the first element

(This is called a "fat pointer".)

So, if we assume that the literal 'John' was placed at memory location 
0x1000, then the left-hand side of your code will satisfy the following 
conditions:


  assert(name.length == 4);// <-- NOT 5
  assert(name.ptr == 0x1000);

The important part to note is how even though the string literal was 
stored as 5 bytes but the string's length is 4.


As others said, when we add a character to a string, there is no '\0' 
involved. Only the newly added char will the added.


Functions in D do not need the '\0' sentinel to know where the string 
ends. The end is already known from the 'length' property.


Ali



Re: Drawbacks of exceptions being globally allocated

2021-08-14 Thread Ali Çehreli via Digitalmars-d-learn

On 8/14/21 4:41 AM, Tejas wrote:

> What is the drawback of the following "simple" ```@nogc``` exception
> creation technique?
>
> ```d
> import std;
> void main()@nogc
> {
>  try{
>  __gshared a = new Exception("help");
>  scope b = a;
>  throw b;
>  }
>  catch(Exception e){
>  printf("caught");
>  }
> }
> ```

So, there would be many exception objects one for each place that an 
exception can be thrown. Functions like enforce() would have to take a 
reference to the exception object that is associated with that local scope.


I don't have a clear idea on whether it would work or whether it would 
be cumbersome to use or not. I wrote the following by misunderstanding 
you. I thought you you were proposing just one exception object for the 
whole program. I am still posting it because it is something I realized 
relatively recently.


Even though this feature is probably never used, in D, multiple 
exception objects are chained. For example, you can throw e.g. in a 
destructor when there is an active exception in flight and that second 
object gets attached to the first one in linked list fashion.


This may be useful in some cases but in general, these colatteral 
exceptions don't carry much information and I don't think anybody looks 
at them. Usually, the first one is the one that explains the error case.


All such collateral exceptions are accessible through the Throwable.next 
function.


However, even if D did not have such a feature and it had only a single 
exception that could be thrown (like in C++), the reality is, there can 
be infinite number of exceptions objects alive. This fact is true for 
C++ as well and this fact is one of the main reasons why exceptions are 
not allowed in safety-critical systems: When you can't limit the number 
of exception objects, you can't guarantee that the system will not run 
out of memory.


Here is how even in C++ there can be infine exception objects. (Note: 
Yes, there is only one in flight but there is no limit on the number of 
caught exception objects that are alive.)


try {
  foo();

} catch (Exception exc) {
  // Note: We caught the exception; so it's not in flight anymore

  bar();

  // For the following to work, exc must be alive even after bar()
  writeln(exc.msg);
}

Now imagine bar() had a try-catch of its own where it caught another 
exception. During the execution of bar's catch clause, there are two 
exception objects alive.


So, the problem with your proposal is, there is no room for the 
exception that was throw during bar's execution.


Ali



Re: How to extend the string class to return this inside the square bracket?

2021-08-13 Thread Ali Çehreli via Digitalmars-d-learn

On 8/13/21 4:23 PM, Marcone wrote:

> string x = "Hello World!";
> writeln(x[x.indexOf("e")..x.indexOf("r")]);

I don't see the usefulness and there are the following problems with it:

- Not an algorithmic complexity issue but it sounds to me like a 
pessimization to go through the elements in linear fashion, obtain 
indexes and then iterate between the indexes again.


- This approach requires random access, which only a subset of 
collections provide.


- The semantics of the second index is not clear. What is the intent 
when we say "from 'f' to 'n'" in the string "confusing"? Is it an error 
because the indexes 3..2 would be illegal? Or did we mean second 'n' in 
the string?


On the other hand, the programmer can build any semantic with the 
existing range algorithms. And that would work even with InputRanges.


You didn't ask but sorry, this feature is not for me. :)

Ali



Re: How to extend the string class to return this inside the square bracket?

2021-08-13 Thread Ali Çehreli via Digitalmars-d-learn

On 8/13/21 4:08 PM, jfondren wrote:

On Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote:


Isn't there some unario operator template that I can use with lambda 
to handle a string literal?


So, something other than an exact "lit"[0..this.xx(..)] syntax is fine?

What didn't you like about `"Hello World!".findSplit("o")[0].writeln;` 
then?


What is a real example of something you want to do?


And I started writing the following but stopped because the semantics 
are not clear. I first called it 'between' but then should the 'o' that 
was searched be a part of the output?


Should "from 'o' to 'o'" produce an empty string, should it include a 
single 'o' or should it go all the way to the next 'o'?


What about the last line which says "from 'd' to 'a'"? Is that an 
entirely empty range or just 'd' or 'd' till the end?


I don't think the programming language can decide one way or the other.

import std.algorithm;
import std.range;
import std.stdio;

auto inclusive(R, E)(R range, E fromNeedle, E toNeedle) {
  auto found = range.find(fromNeedle);
  return chain(found.front.only, 
found.drop(1).findSplitAfter(only(toNeedle))[0]);

}

void main() {
  const s = "Hello World!";
  auto r = s.inclusive('o', 'o');
  writeln(r);

  writeln("abcdef".inclusive('d', 'a'));
}

Ali


Re: Anyway to achieve the following

2021-08-13 Thread Ali Çehreli via Digitalmars-d-learn

On 8/13/21 1:25 AM, JG wrote:

> Suppose one has a pointer p of type T*.
> Can on declare variable a of type T which is stored in the location
> pointed to by p?

You may be looking for core.lifetime.emplace. (core.lifetime is not on 
dlang.org at the moment for me but it is under 
/usr/include/dmd/druntime/import/core on my computer.)


I have some content about 'emplace' but it is not in std.conv anymore:

  http://ddili.org/ders/d.en/memory.html#ix_memory.construction,%20emplace

Ali



Re: I do not understand copy constructors

2021-08-12 Thread Ali Çehreli via Digitalmars-d-learn

On 8/12/21 4:32 AM, Paul Backus wrote:

> Qualifying the ctor as `inout` works fine

I can see how a DConf Online presention is shaping up in your head. ;)

  http://dconf.org/2021/online/index.html

We need a collective understanding of effective use of such fundamental 
concepts.


Ali



Re: D has the same memory model as C++

2021-08-11 Thread Ali Çehreli via Digitalmars-d-learn

On 8/11/21 12:19 PM, Tejas wrote:


Atleast leave some pointers on where to start :(


I DuckDuckGo'ed it for you. :)

  https://en.cppreference.com/w/cpp/language/memory_model

Then looked it up at Wikipedia too:

  https://en.wikipedia.org/wiki/Memory_model_(programming)

Ali


Re: D has the same memory model as C++

2021-08-11 Thread Ali Çehreli via Digitalmars-d-learn
This is an interesting thread but "memory model" does not cover or mean 
all of the points discussed here. I can't define it precisely, so I'm 
leaving it to interested parties to search for themselves. :)


Ali



Re: writef, compile-checked format, pointer

2021-08-10 Thread Ali Çehreli via Digitalmars-d-learn

On 8/9/21 10:03 PM, nov wrote:

> i dreamed that programming will be less-error with compile checking 
format.


I still think so because many errors that can be caught at compile time 
are moved to run time in non-statically-typed languages.


> but reality disappoint :(
> message for every error in compile-checked format occupy whole screen :(

When that happens, I simply change it to runtime-checked format string 
like you did and it works. (Better would be to identify and fix the 
problem. Maybe some other time for me...)


Ali



Re: writef, compile-checked format, pointer

2021-08-09 Thread Ali Çehreli via Digitalmars-d-learn

On 8/9/21 3:46 PM, Adam D Ruppe wrote:

> The compile time checker [...] implementation is really really
> slow and pretty bloated in codegen too.
>
> My personal policy is to never use it.

My personal policy is to kindly ask you to fix it! :p

Ali



Re: writef, compile-checked format, pointer

2021-08-09 Thread Ali Çehreli via Digitalmars-d-learn

On 8/9/21 3:01 PM, Patrick Schluter wrote:

> On Monday, 9 August 2021 at 19:38:28 UTC, novice2 wrote:
>> format!"fmt"() and writef!"fmt"() templates
>> with compile-time checked format string
>> not accept %X for pointers,
>>
>> but format() and writef() accept it
>>
>> https://run.dlang.io/is/aQ05Ux
>> ```
>> void main() {
>> import std.stdio: writefln;
>> int x;
>> writefln("%X", );  //ok
>> writefln!"%s"();  //ok
>> //writefln!"%X"();  //compile error
>> }
>> ```
>>
>> is this intentional?
>
> Yes. %X is to format integers. Runtime evaluation of a format string
> does not allow for type checking. When using the template, the
> evaluation can be thorough and the types can be checked properly.

Sensible explanation but it conflicts both with the documentation at

  https://dlang.org/phobos/std_format.html

and the error message for the following:

  // Intentionally wrong specifier:
  writefln!"%_"((int*).init);

Error: expression `FormatException("Expected one of %s, %x or %X for 
pointer type.", "/usr/include/dmd/phobos/std/format/internal/write.d", 
2990LU, null, null, 0u)` is not constant


Both the documentation and the error message suggest %x and %X.

> You
> have 2 solutions for your problem, either a type cast
>
>  writefln!"%X"(cast(size_t));
>
> or using the generic format specifier that will deduce itself the format
> to using depending in the passed type.
>
>  writefln!"%s"();

That would be my choice but I've just learned that %s prints the null 
value as "null" instead of hex 0, which may be undesirable in some cases.


I think there really is a bug here.

I've been hitting a similar bug with some complex range expressions 
where compile-time checked format strings would not work. I don't know 
the reason but I suspect a bug in the compile-time checker that involves 
.init values for arguments. I assume the checker uses .init values to 
see whether the format expression compiles and works. In fact, the 
mention of 'null' in the OP's error message makes me think it may be 
related. Perhaps the un-typed 'null' literal is used somewhere. (?)


Ali



Re: Proper way to protect (lock) a struct field after initialization ??

2021-08-08 Thread Ali Çehreli via Digitalmars-d-learn

On 8/8/21 3:11 AM, james.p.leblanc wrote:

Hello All.

Is there a standard way to protect a field of a struct after
the struct has been initialized?

Is this possible with a struct?

If not, I suppose a class (object) would be needed?  If so,
are there any simple pointers to an example of this?

Thanks in advance,

James



I understand your question differently from jfondren. You may be looking 
for a 'const' (or 'immutable') member:


struct S {
  const int i;

  this(int i) {
// This will work because "first assignment is initialization"
this.i = i;
  }
}

void main() {
  auto s = S(42);

  // This won't work
  s.i = 43;

  // This won't work either
  s = S(44);
}

Ali



Re: best/proper way to declare constants ?

2021-08-05 Thread Ali Çehreli via Digitalmars-d-learn

On 8/5/21 5:11 PM, someone wrote:

> Although I have very little experience with D, I second this:
> refactoring, even huge refactors, proved to be far more straightforward
> than I expected.

May I humbly suggest names like Location instead of structureLocation to 
make refactoring even more straightforward. ;)


Ali



Re: __traits() to get parameter details only ? ... hasMember looks up everything within

2021-08-05 Thread Ali Çehreli via Digitalmars-d-learn

On 8/4/21 7:21 PM, someone wrote:

> somewhere I read
> Ali saying there's nothing wrong implementing properties the old-way via
> functions because @property has nothing special about it but I can't
> state where I read what I am stating so take it with a grain of salt.

As I understand it, @property is discouraged by the community. That's 
what I say here:


  http://ddili.org/ders/d.en/property.html#ix_property.@property

Quoting the whole section:


@property

Property functions may be defined with the @property attribute as well. 
However, as a best practice, the use of this attribute is discouraged.


import std.stdio;

struct Foo {
@property int a() const {
return 42;
}

int b() const {// ← Defined without @property
return 42;
}
}

void main() {
auto f = Foo();

writeln(typeof(f.a).stringof);
writeln(typeof(f.b).stringof);
}

The only effect of the @property attribute is when determining the type 
of an expression that could syntactically be a property function call. 
As seen in the output below, the types of the expressions f.a and f.b 
are different:


int← The type of the expression f.a (the return type)
const int()← The type of the member function Foo.b


Ali

P.S. I found that section by searching for "property" on the Index page:

  http://ddili.org/ders/d.en/ix.html

The Index page is linked from the title page (aka index.html) as "The 
Index Section". (Too many indexes! :) )


  http://ddili.org/ders/d.en/index.html




Re: __FILE__

2021-08-04 Thread Ali Çehreli via Digitalmars-d-learn

On 8/4/21 7:17 PM, Steven Schveighoffer wrote:

>> The compiler has to evaluate the default argument as constant
>> expression in order to use it as default value..
>
> This is not true, you can use runtime calls as default values.

What??? I just checked and it works! :)

string bar() {
  import std.process;
  return ("BAR" in environment) ? environment["BAR"] : null;
}

string foo(string s = bar()) {
  return s;
}

void main() {
  import std.stdio;
  writeln(foo("hello world"));
  writeln(foo());
}

Run e.g. with

$ BAR=whaaat ./deneme

I wonder whether this feature is thanks to 'lazy' parameters, which are 
actually delegates.


Ali



Re: module search paths

2021-08-03 Thread Ali Çehreli via Digitalmars-d-learn

On 8/3/21 9:51 PM, Brian Tiffin wrote:

> I added an `import std.json;`.  That did not include the
> JSONType enum.

It works for me:

import std.json;

int main() {
  return JSONType.null_;
}

> Is there a go to quick and easy way of tracking down
> module members?

Searching for it at dlang.org usually works pretty well. Although, I 
hear that Adam's Phobos documentation site is better. (I don't use it 
just because I don't have a habit of it yet.)


Finally, I sometimes grep under /usr/include/dmd. Ultimate truth! :)

Ali



Re: Find struct not passed by reference

2021-08-03 Thread Ali Çehreli via Digitalmars-d-learn

On 8/3/21 12:22 PM, frame wrote:

On Tuesday, 3 August 2021 at 19:19:27 UTC, jfondren wrote:

On Tuesday, 3 August 2021 at 19:11:16 UTC, frame wrote:

On Tuesday, 3 August 2021 at 16:35:04 UTC, Ali Çehreli wrote:
Why foreach() does not accept a pointer?


pointers don't come with a length?


Where is the problem if it points to something with a range interface?


Must be more complicated than a trivial derefencing:

import std.range;

void main() {
  auto r = 5.iota;
  auto p = 

  foreach (e; *p) {
  }
}

Having said that, I swear there is a seemingly-over-the-top help of D 
for foreach loops, which I can't remember now. Similar to what you said, 
it works with a certain type of construct by thinking outside the box.


Do others know what I am trying to remember?

Ali



Re: align dynamic array (for avx friendliness) hints? / possible??

2021-08-03 Thread Ali Çehreli via Digitalmars-d-learn

On 8/3/21 10:50 AM, james.p.leblanc wrote:

> **Is there some highly visible place this is already documented?

For what it's worth, it appears as "slice from pointer" in my index:


http://ddili.org/ders/d.en/pointers.html#ix_pointers.slice%20from%20pointer

Admittedly, one needs to know the concept first to think about that 
entry. :/


Ali



Re: Name Mangling & its representation of D types

2021-08-03 Thread Ali Çehreli via Digitalmars-d-learn

On 8/3/21 9:43 AM, NonNull wrote:
I'd like to understand how any D type is represented as a string by the 
name mangling done by the compilers.


Related article that mentions .mangleof, a property of all symbols:

  https://dlang.org/blog/2017/12/20/ds-newfangled-name-mangling/

Ali


Re: Find struct not passed by reference

2021-08-03 Thread Ali Çehreli via Digitalmars-d-learn

On 8/2/21 4:06 PM, frame wrote:
Is there a way to find a struct which should be passed by reference but 
accidentally isn't? Maybe with copy constructors?


If I understand it correctly, your current value-type needs to be a 
reference type. Would the following be workable solutions?


a) Classes are already reference types. So, replace struct with class:

class Foo {
  // ...
}


b) Make your struct a reference type by

i) Renaming it

struct FooImplementation {
  // ...
}

ii) Using a wrapper with the old name

struct Foo {
  FooImplementation * impl;

  this(int i) {
this.impl = new FooImplementation(i);
  }

  // ...
}

But the problem with the 'b' option is, all objects are being allocated 
dynamically with that constructor. Then, there can be a ref-taking 
constructor (as well):


struct Foo {
  // ...

  this(ref FooImplementation impl) {
this.impl = 
  }
}

Finally, an 'alias this' can make the transition easy in the 'b' case.

Ali


Re: Is returning void functions inside void functions a feature or an artifact?

2021-08-02 Thread Ali Çehreli via Digitalmars-d-learn

On 8/2/21 9:42 AM, Rekel wrote:

> when would one use an alias instead of a
> function/delegate? I haven't used aliases before.

alias will match both functions and delegates... and... any symbol at 
all. So, if you don't have a reason to constain the user, callable 
template parameters are most usefully aliases.


Ali



Re: Exit before second main with -funittest

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

On 7/30/21 7:48 PM, Brian TIffin wrote:

> Found, find, C++ too hot for most to handle, so why?

I rubbed shoulders with C++ people who would argue to the effect of "C++ 
was not meant to be for everyone."


> And a deeper thanks, Ali, for the book.

You're welcome. I am very happy when it is helpful.

> Just in case you ever want to try Unicon programming, or need to glue to
> some COBOL data, I put these on offer, umm, meaning free.
>
> - Unicon Programming 
> - GnuCOBOL FAQ 

I've just browsed them. Impressive work; both the content and the 
technology covered. :)


Ali



Re: Exit before second main with -funittest

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

On 7/30/21 3:08 PM, Brian Tiffin wrote:

> Don't take to C++, never have, even while watching
> cfront and Walter having the first** brain to craft a native compiler.

[...]

> ** I'm not sure Walter was first first, or close first, or...

He wrote the first C++ compiler. (cfront was a C++-to-C transpiler.) I 
hope I am relaying correctly: Walter claims that without his compiler 
that made C++ accessible to the public, C++ might have remained in 
research organizations.


Ali



Re: Exit before second main with -funittest

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

On 7/29/21 9:22 PM, Mathias LANG wrote:

> On Friday, 30 July 2021 at 03:45:21 UTC, Ali Çehreli wrote:
>> Almost all of my programs are in the following pattern:
>>
>> ```D
>> import std.stdio;
>>
>> void main(string[] args) {
>>   version (unittest) {
>> // Don't execute the main program when unit testing
>> return;
>>   }
>> }
>> ```
>
> Are you aware that this isn't necessary since v2.090.0 ?
> https://dlang.org/changelog/2.090.0.html#unittest-default

No, I wasn't aware. Thanks! Part of the reason must be because these 
programs started with 2.084. :)


Ali




Re: Exit before second main with -funittest

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

Almost all of my programs are in the following pattern:

import std.stdio;

void main(string[] args) {
  version (unittest) {
// Don't execute the main program when unit testing
return;
  }

  try {
// Dispatch to the actual "main" function
doIt(args);

  } catch (Exception exc) {
// Note .msg because we don't want to print stack trace
stderr.writefln!"ERROR: %s"(exc.msg);

  } catch (Error err) {
// Note NO .msg because we DO want to print stack trace
stderr.writefln!"ERROR: %s"(err);
  }
}

// This is the actual "main"
void doIt(string[] args) {
  // ...
}

Ali



Re: Performance issue with fiber

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

On 7/28/21 1:15 AM, hanabi1224 wrote:

> On Wednesday, 28 July 2021 at 01:12:16 UTC, Denis Feklushkin wrote:
>> Spawning fiber is expensive
>
> Sorry but I cannot agree with the logic behind this statement, the whole
> point of using fiber is that, spwaning system thread is expensive, thus
> ppl create lightweight thread 'fiber'

I assume the opposite because normally, the number of times a thread or 
fiber is spawned is nothing compared to the number of times they are 
context-switched. So, spawning can be expensive and nobody would realize 
as long as switching is cheap.


There are other reasons why fibers are faster than threads all related 
to context switching:


- CPU cache efficiency

- Translation lookaside buffer (TLB) efficiency

- Holding on to the entirety of the time slice given by the OS

Ali

P.S. The little I know on these topics is included in this presentation:

  https://dconf.org/2016/talks/cehreli.html



Re: Why does Unconst exist?

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

On 7/27/21 10:38 PM, Tejas wrote:
When I initially saw it, I was hopeful that it would allow me to bypass 
some of the restrictions of ```const``` , but it literally just takes a 
type and strips the ```const``` from it, you can't pass a variable to it 
in order to get rid of ```const``` . What use does it serve then?


https://dlang.org/library/std/traits/unconst.html


Searching under /usr/include/dmd reveals that it is used in the 
implementations of array property 'dup' and 'copyEmplace', which makes 
sense: We want copies to be mutable.


Ali


Re: POST request with std.net.curl

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

On 7/23/21 11:11 AM, bachmeier wrote:
I'm writing a D program that interacts with the Todoist API using 
std.net.curl. It's not a problem to do get requests to query tasks, but 
I cannot find a way to get post to work to create a new task.


This is a working bash script, where APIKEY is defined elsewhere and $1 
and $2 are user input when running the script:


```
curl "https://api.todoist.com/rest/v1/tasks; -X POST --data 
"{"'"'"content"'"'": "'"'"$1"'"'", "'"'"project_id"'"'": $2}" -H 
"Content-Type: application/json" -H "Authorization: Bearer $APIKEY"

```

(For obvious reasons I'm not going to provide a working example.) How 
can I translate this into a post function call within D?


[Todoist API 
Reference](https://developer.todoist.com/rest/v1/?shell#create-a-new-task)


I haven't used it but isn't it the version of post that takes a 
dictionary here?


  https://dlang.org/phobos/std_net_curl.html#.post

If the Authorization is the problem, I wonder whether addRequestHeader 
is the solution:


  https://dlang.org/phobos/std_net_curl.html#.HTTP.addRequestHeader

Ali


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

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

On 7/23/21 12:30 PM, apz28 wrote:

> The -debug build with passing unit-tests so no problem there.
> The -release build is having problem. After make change to accommodate
> it, it takes forever to build. I started it yesterday 11AM and it is
> still compiling now (more than a day already.) It takes a full 100% core
> and peek memory usage is 2.2GB. The hard-drive is SSD

There is definitely something wrong with the compiler. That build time 
is ridiculously high.


Ali



Re: enum true, or 1

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

On 7/22/21 1:44 PM, Brian Tiffin wrote:

> So would there be any cringes

Not from me. :)

> seeing a skeleton D source file that
> always ended with
>
> ~~~d
> /++
> Disclaimer
>
>  This software is distributed in the hope that it will be useful, but
>  WITHOUT ANY WARRANTY; direct or indirect, without even the implied
>  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> +/
> enum INDEMNITY = true;
> ~~~ ??
>
> The goal is attaching backmatter doc comments to a declaration that
> follows without being too intrusive.

I don't feel qualified to comment on such a topic but it looks fine. 
Perhaps INDEMNIFIED is more grammatically correct but weirder too. :)


Ali



Re: Initializing a complex dynamic array (with real part from one array, and imaginary from other array)?

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

On 7/21/21 2:17 AM, drug wrote:

>  auto z = zip(x, y)  // concatenate two ranges
>  .map!(a=>Complex!double(a[0],a[1])) // take the current first
> element of the first range as the real part and the current first
> element of the second range as the imaginary part
>  .array; // convert the lazy range
> to a dynamic array, probably you can avoid but this depends on how you
> use it later

One of the *nonexistent* ;) features of D is automatic tuple expansion, 
which works only in foreach loops. I think it makes the code much more 
readable in this case:


   Complex!double[] z;

   import std.range;
   import std.algorithm;

   foreach (re, im; zip(x, y)) {
 z ~= complex(re, im);
   }

An alternative is lockstep:

   foreach (re, im; lockstep(x, y)) {
 z ~= complex(re, im);
   }

Ali



Re: associative array with Parallel

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

On 7/21/21 11:01 PM, frame wrote:

> This is another parallel foreach body conversion question.
> Isn't the compiler clever enough to put a synchronized block here?

parallel is a *function* (not a D feature). So, the compiler might have 
to analyze the entire code to suspect race conditions. No, D does not 
have such features.


But even if it did, we wouldn't want synchronized blocks in 
parallelization because a synchronized block would run a single thread 
at a time and nothing would be running in parallel anymore.


Ali



Re: enum true, or 1

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

On 7/21/21 8:44 PM, Brian Tiffin wrote:

> What is the preferred syntax for simple on/off states?

I use std.typecons.Flag. It feels very repetitive but that's what we have:

import std.typecons;

void foo(Flag!"doFilter" doFilter) {
  if (doFilter) {
// ...
  }
}

bool someCondition;

void main() {
  // Literal values of Flag!"doFilter"
  foo(Yes.doFilter);
  foo(No.doFilter);

  // Assuming we start with an existing 'bool'...
  bool doFilter = someCondition;
  // ... I like this helper (see below):
  foo(flagFromBool!doFilter);
}

template flagFromBool(alias variable) {
  enum flagName = variable.stringof;

  auto flagFromBool() {
import std.format : format;

enum expr = format!q{
  return variable ? Yes.%s : No.%s;
}(flagName, flagName);

mixin (expr);
  }
}

> Did I read that
> D was moving to strictly 1 and 0 literals instead of true/false on/off
> yes/no?

Walter sees 'bool' as a 1-bit integer type. I can't. :) I cringe 
everytime I see assert(0). To me, it is assert(false); :/


> If so, is there an idiom for yes/no/maybe  -1,0,1 less/equal/greater?

opCmp's return value has three states:

 < 0
 == 0
 > 0

Ali



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 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: Yet another parallel foreach + continue question

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

On 7/19/21 5:07 PM, seany wrote:

> Consider :
>
>  for (int i = 0; i < max_value_of_i; i++) {
>  foreach ( j, dummyVar; myTaskPool.parallel(array_to_get_j_from,
> my_workunitSize) {
>
>  if ( boolean_function(i,j) ) continue;
>  double d = expensiveFunction(i,j);
>  // ... stuff ...
>  }
>  }

Arranging the code to its equivalent may reveal the answer:

if (!boolean_function(i, j)) {
  double d = expensiveFunction(i, j);
  // ... stuff ...
}

We removed 'continue' and nothing changed and your question disappeared. :)

> I understand, that the parallel iterator will pick lazily values of `j`
> (up to `my_workunitsize`), and execute the for loop for those values in
> its own thread.

Yes.

> Say, values of `j` from `10`to `20` is filled where `my_workunitsize` =
> 11. Say, at `j = 13` the `boolean_function` returns true.
>
> Will then the for loop just jump to the next value of `j = 14` like a
> normal for loop?

Yes.

> I am having a bit of difficulty to understand this.
> Thank you.

parallel is only for performance gain. The 2 knobs that it provides are 
also for performance reasons:


1) "Use just this many cores, not all"

2) "Process this many elements, not 100 (the default)" because otherwise 
context switches are too expensive


Other than that, it shouldn't be any different from running the loop 
regularly.


Ali



Re: Including a file

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

On 7/18/21 10:28 AM, Vindex wrote:

> ```
> ldc2 source/main.d -ofmyprogram -L-l:libmylib.so.0
> Error: file "thing.json" cannot be found or not in a path specified 
with -J

> ```
>
> Is the actual inclusion of the file on import deferred until the link 
step?


I wonder whether it's an ldc thing related to its link-time powers?

> I could insert the entire json into the file, but I would hate to do 
that.


I insert two many-megabytes long tar.gz files in there. :) I unzip and 
untar the files into a cache directory to use at runtime. I just works. 
The zipped version of a json file may be very small.


I my case, the files are gzip'ped during the build stage and I unzip with

  https://dlang.org/phobos/std_zlib.html

Ali



Re: function parameters: is it possible to pass byref ... while being optional at the same time ?

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

On 7/17/21 8:52 PM, someone wrote:

> I am a self-taught programmer

Same here.

> well before college

Not here because I had access to a Sinclair Spectrum only in 1985. :/

> I have a degree in electronics engineering

Same here.

> one of the things that I felt in love with when I was first exposed 
to was OOP; with all its pros and cons


I learned it with C++. Then I realized that it wasn't much used in D. 
The following two presentations made me leave it completely behind 
unless a simple class hierarchy is really necessary.


1) Our friend Luís Marques presented the following at one of our local 
meetups. (He was distant. :) )


  http://files.meetup.com/18234529/luis_marques_anemic_domain_models.pdf

That presentation concludes that anemic domain models are better than 
rich design models.


An interesting question from the presentation to all OOP people is "How 
might you design a program that lets people play Monopoly with each 
other over the internet?"


Very eye opening!

2) Our "open methods" friend Jean-Louis Leroy concludes that OOP took a 
wrong path in programming language history:


  https://dconf.org/2018/talks/leroy.html

It starts with the "expression problem" (which is *not* about 
"expressions").


> it was on one of my first jobs as a developer at a financial 
institution which by the time back in the early 90s was

> using a database manager called FoxPro

Same here! :) I learned and programmed in FoxPro for my first job in the 
US, in Sausalito, CA in 1994. I was maintaining and improving an order 
entry, invoicing, inventory, etc. system.


I had not even heard about OOP back then to know whether FoxPro was good 
at it. :)


> It was with this tool that I learned primarily to encapsulate everything
> -and it payed off; code quality using OOP was far superior.

Ah! OOP carries many meanings with it. Yes, encapsulation is important, 
which I take less advantage of as I gain experience. :) (I am going 
backward!) But I left "everything is an object" mantra way back in my 
programming history. Pffft!


> C++ came afterward with all its complexity and 50% of the guys loving
> it

I've been one of those.

> I respect it, it is powerful, the
> problem with C++ is that anyone writing code with it feels the need to
> show you how big has his ...

That.

I've been there myself and I am pretty sure most of the brain power that 
is attracted to C++ is there for the same reason. I asked a C++ speaker 
why he was interested in C++ instead of one of the more modern languages 
and he said "because it is hard".


> unless you have some guidelines cast in stone at company level

More than 400 rules in Core Guidelines alone... Add to that more 
hundreds of MISRA, AUTOSAR, etc. standards. How can one expect 
programmers to observe all of those rules? And only some of the 
guidelines are machine-checkable.


Anyway... Back to D... :)

Ali




Re: function parameters: is it possible to pass byref ... while being optional at the same time ?

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

On 7/17/21 6:49 PM, Brian Tiffin wrote:

> *Practice makes perfect?  No, practice makes permanent.*

One reference for that quote is "Classical Guitar Pedagogy" by Anthony 
Glise, Chapter Nine--Practicing. ;)


Ali



Re: Creating immutable arrays in @safe code

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

On 7/16/21 3:21 PM, Dennis wrote:

> But `pure` is no silver bullet:

Agreed. I occasionally struggle with these issues as well. Here is a 
related one:


import std;

void foo(const int[] a) {
  auto b = a.array;
  b.front = 42;
  // Error: cannot modify `const` expression `front(b)`
}

I think that is a Phobos usability issue with array() because the 
freshly *copied* int elements are const. Really? So just because the 
programmer promised not to modify the parameter, now he/she is penalized 
to be *safe* with own data. I am not sure whether array() is the only 
culprit with this problem. (I think array() can be improved to pick 
mutable type for element types that have no indirections.)


> ```D
> import std;
>
> pure: @safe:
>
> struct Expression
> {
>  immutable(Expression)[] children;
>  int value;
> }
>
> Expression withSortedChildren(Expression exp)
> {
>  return Expression(expr.children.dup.sort!((a, b) => a.value <
> b.value).release);
> }
> ```
>
>> Error: cannot implicitly convert expression
>> `sort(dup(cast(const(Expression)[])expr.children)).release()` of type
>> `Expression[]` to `immutable(Expression)[]`
>
> I've tried structuring it in a way that makes the compiler allow the
> conversion to immutable, but had no luck so far.

I don't have a solution and you have more experience with this. :/

Ali



Re: Creating immutable arrays in @safe code

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

On 7/16/21 1:19 PM, Dennis wrote:

> I like passing around immutable data

I think the D community needs to talk more about guidelines around 
'immutable'. We don't... And I lack a complete understanding myself. :)


To me, 'immutable' is a demand of the user from the provider that the 
data will not mutate. So, I don't agree with the sentiment "I like 
passing around immutable data" because 'immutable' limits usability 
without a user to demand it to begin with. To me, 'immutable' must be 
used when really needed.


> , but I don't like creating it.

I think making newly-created data 'immutable' renders it less useful. 
(The caller cannot mutate it.) So to me, newly created data should be 
mutable for the most usability. 'immutable' should be decided by the 
caller. Luckily, we have 'pure' allows the caller to make it 'immutable' 
effortlessly:


import std;

pure
int[] positive(int[] input) @safe
{
return input.filter!(x => x > 0).array;
}

void main() {
  immutable p = positive([1, 2]);
}

Now the function is 'pure' and the caller's data is 'immutable' because 
the caller decided it had to be immutable. On the other hand, the 
function is happier because it is useful to callers that may mutate the 
data. :)


Ali



Re: How to create friends of a class at compile time?

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

On 7/15/21 5:46 PM, Ali Çehreli wrote:

> On 7/15/21 11:24 AM, Tejas wrote:

>  > package(qualifiedIdentifier)

> Just don't do it

Ok, I said all that before realizing what you needed with transpiling 
C++ to D and the solution of package(qualifiedIdentifier). (And 
package(qualifiedIdentifier) is news to me! :) )


Ali




Re: How to create friends of a class at compile time?

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

On 7/15/21 11:24 AM, Tejas wrote:

> it seems like seperating chunks of C++ code into seperate modules
> and using the
> ```d
> package(qualifiedIdentifier)
> ```
> access specifier seems to be the way to go.

That would be necessary if one agreed with C++'s 'private' to begin 
with. In other words, one would agree that implementations inside one 
source file should be protected from each other.


Through Walter Bright's experience, D does not buy into that view: It is 
silly to protect implementation details of features of the same file 
from each other. Personally, I fully agree! I am rarely strongly 
opinionated; this topic is one of those cases. :) In hind sight, this is 
one of the examples of D that thought me and improved me.


C++'s 'friend' "feature" covers up a language design mistake: It is a 
mistake because a tool should be useful; C++'s 'private' protects the 
programmer unnecessarily strongly from himself or herself. What a view 
that causes unnecessary mental load on many programmers with the 
'friend' keyword...


If you agree with all of that, then your idea of separating chunks into 
separate modules becomes unnecessary work. Just don't do it and you will 
miss nothing at all. You will gain a lot in the future without even 
noticing it. :)


Ali



Re: opIndexUnary post in-/decrement how to ?

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

On 7/14/21 11:27 AM, Tejas wrote:

> the compiler error should have been a dead giveaway
> that opIndex was returning a _constant_ value

I know you mean "rvalue" but if I may be unnecessarily pedantic, an 
rvalue can indeed be mutated:


struct A {
  int i;
  void mutate() {
i = 42;
import std.stdio;
writeln("I am not constant. :)");
  }
}

struct B {
  auto opUnary(string op)() {
return A();
  }
}

void main() {
  auto b = B();
  (++b).mutate();  // <-- Mutating an rvalue
}

Ali



Re: opIndexUnary post in-/decrement how to ?

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

On 7/14/21 9:13 AM, Tejas wrote:

>  ref/*notice this ref*/ int opIndex(int index)return/*NOTICE THE
> RETURN*/ {

Indeed... I cover that 'ref' here:


http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.return%20type,%20operator

Two quotes from that section:

1) "it is advisable to observe the return type of the same operator on 
fundamental types."


NOTE: I agree that for that to make sense, one needs to know the "return 
type" of fundamental type operations. It may not be clear that ++i is a 
reference to 'i' ("i itself"):


void main() {
  int i;
  ++i = 42;
  assert(i == 42);
}

2) "With the exception of opAssign, it is recommended that the operators 
that modify the object return the object itself. [...] The return type 
is the type of the struct, marked by the ref keyword to mean reference."


Ali



Re: Error with implicit cast of ^^=

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

On 7/14/21 2:44 AM, wjoe wrote:

>>   x = (x ^^ y).to!(typeof(x));
>> }
>>
>> For example, run-time error if y == 7.

> I was planning on adding support for over-/underflow bits but this is
> much better. Thanks!

If so, then there is also std.experimental.checkedint:

  https://dlang.org/phobos/std_experimental_checkedint.html

Andrei Alexandrescu introduced it in this presentation:

  https://dconf.org/2017/talks/alexandrescu.html

Ali



Re: Error with implicit cast of ^^=

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

On 7/13/21 4:12 AM, wjoe wrote:
> ```D
> byte x = some_val;
> long y = some_val;
>
> x ^^= y; // Error:  cannot implicitly convert expression
> pow(cast(long)cast(int)x, y) of type long to byte

[...]

> I rewrote it to something like
> ```D
> mixin("x = cast(typeof(x))(x" ~ op[0..$-1] ~ " y);");
> ```
> but I'm curious if there's a less convoluted way.

If it's important, std.conv.to checks the value:

import std.conv;

void main() {
  byte x = 2;
  long y = 6;
  x = (x ^^ y).to!(typeof(x));
}

For example, run-time error if y == 7.

Ali



Re: mixin template's alias parameter ... ignored ?

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

On 7/12/21 5:42 PM, someone wrote:

> On Monday, 12 July 2021 at 23:25:13 UTC, Ali Çehreli wrote:
>> On 7/12/21 3:35 PM, someone wrote:
>>
>> >>> private size_t pintSequenceCurrent = cast(size_t) 0;
>> >
>> >> Style: There's no need for the casts (throughout).
>> >
>> > [...] besides, it won't hurt, and it helps me in many ways.
>>
>> I think you are doing it only for literal values but in general, casts
>> can be very cumbersome and harmful.
>
> Cumbersome and harmful ... could you explain ?

Cumbersome because one has to make sure existing casts are correct after 
changing a type.


Harmful because it bypasses the compiler's type checking.

>> For example, if we change the parameter from 'int' to 'long', the cast
>> in the function body is a bug to be chased and fixed:
>>
>> // Used to be 'int arg'
>> void foo(long arg) {
>>   // ...
>>   auto a = cast(int)arg;  // BUG?
>>   // ...
>> }
>
> nope, I'll never do such a downcast

The point was, nobody did a downcast in that code. The original 
parameter was 'int' so cast(int) was "correct" initially. Then somebody 
charnged the parameter to "long" and the cast became potentially harmful.


> UNLESS I previously tested with if
> () {} for proper int range; I use cast a lot, but this is mainly because
> I am used to strongly-typed languages etc etc,

Hm. I am used to strongly-typed languages as well and that's exactly why 
I *avoid* casts as much as possible. :)


> for example if for
> whatever reason I have to:
>
> ushort a = 250;
> ubyte b = cast(ubyte) a;
>
> I'll do:
>
> ushort a = 250;
> ubyte b = cast(ubyte) 0; /// redundant of course; but we don't have

We have a different way of looking at this. :) My first preference would be:

 ubyte b;

This alternative has less typing than your method and is easier to 
change the code because 'ubyte' appears only in one place. (DRY principle.)


  auto b = ubyte(0);

Another alternative:

  auto b = ubyte.init;

Ali




Re: mixin template's alias parameter ... ignored ?

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

On 7/12/21 3:35 PM, someone wrote:

>>> private size_t pintSequenceCurrent = cast(size_t) 0;
>
>> Style: There's no need for the casts (throughout).
>
> [...] besides, it won't hurt, and it helps me in many ways.

I think you are doing it only for literal values but in general, casts 
can be very cumbersome and harmful.


For example, if we change the parameter from 'int' to 'long', the cast 
in the function body is a bug to be chased and fixed:


// Used to be 'int arg'
void foo(long arg) {
  // ...
  auto a = cast(int)arg;  // BUG?
  // ...
}

void main() {
  foo(long.max);
}

Ali



Re: mixin template's alias parameter ... ignored ?

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

On 7/10/21 10:20 PM, someone wrote:

> mixin template templateUGC (
> typeStringUTF,
> alias lstrStructureID
> ) {
>
> public struct lstrStructureID {

The only way that I know is to take a string parameter and use it with a 
string mixin:


mixin template templateUGC (
   typeStringUTF,
   string lstrStructureID
   ) {

  mixin("public struct " ~ lstrStructureID ~ q{
  {
typeStringUTF whatever;

  }
});

}

mixin templateUGC!(string,  "gudtUGC08");
mixin templateUGC!(dstring, "gudtUGC16");
mixin templateUGC!(wstring, "gudtUGC32");

void main() {

   gudtUGC32 something;

}

Ali



Re: Can I get the time "Duration" in "nsecs" acurracy?

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

On 7/9/21 11:28 PM, rempas wrote:

> So it's an OS thing?

Don't listen to me on this. :) A quick search yesterday made me believe 
you need kernel support as well. Even if so, I would imagine modern 
kernel on modern hardware should work.


Ali



Re: assert(false) and GC

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

On 7/9/21 4:12 PM, russhy wrote:

>> One way of forcing compile-time evaluation in D is to define an enum
>> (which means "manifest constant" in that use).

That's all I meant. It was a general comment.

> this is very bad, assert are good because they are one liner, making it
> 2 line to avoid GC is just poor design, compiler should be smarter

There must be a misunderstanding. The one-liner does not allocate either 
(or @nogc is broken).


Ali



Re: assert(false) and GC

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

On 7/8/21 11:11 AM, DLearner wrote:

Hi

Please confirm that:
`
    assert(false, __FUNCTION__ ~ "This is an error message");
`

Will _not_ trigger GC issues, as the text is entirely known at compile 
time.


Best regards


One way of forcing compile-time evaluation in D is to define an enum 
(which means "manifest constant" in that use). I used @nogc to prove 
that there is no GC allocation as well:


@nogc
void main() {
  enum msg = __FUNCTION__ ~ "This is an error message";
  assert(false, msg);
}

Ali



Re: Can I get the time "Duration" in "nsecs" acurracy?

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

On 7/9/21 1:54 PM, Paul Backus wrote:

On Friday, 9 July 2021 at 20:43:48 UTC, rempas wrote:
I'm reading the library reference for 
[core.time](https://dlang.org/phobos/core_time.html#Duration) and It 
says that the duration is taken in "hnsecs" and I cannot understand if 
we can change that and choose the precision. Does anyone know if we 
can do that?


It is stored internally in "hnsecs", but you can convert it to other 
units using the `total` method [1]; for example, 
`myDuration.total!"nsecs"`.


[1] https://dlang.org/phobos/core_time.html#.Duration.total


Yes but the resolution seems not to be better than 100 nsecs. A quick 
research reveals a better resolution is not possible with common 
hardware on at least Linux.


The following program always prints multiples of 100 on my Mint OS:

import std.stdio;
import core.thread;
import std.datetime.stopwatch;

void main() {
  auto sw = StopWatch();
  sw.start();

  foreach (_; 0..10) {
Thread.sleep(0.nsecs);
writefln("%,s", sw.peek.total!"nsecs");
  }
}

Ali


Re: Where is "open" in "core.sys.linux.unistd"?

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

On 7/9/21 8:31 AM, rempas wrote:

> I searched "fnctl" in the repo [...] Probably made a typo

Yes, the typo should be obvious to the non-dyslexic among us. :)

fnctl <-- wrong
fcntl <-- correct

Ali



Re: Why I'm getting this "Range Violation" error?

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

On 7/9/21 12:21 AM, rempas wrote:

>while (prompt[i] != '{' && i < len) {

In addition to what others said, you can take advantage of ranges to 
separate concerns of filtering and iteration. Here are two ways:


import core.stdc.stdio;
import std.algorithm;

// Same as your original
void print(T)(string prompt, T args...) {
  prompt
.filter!(c => c != '{')
.each!(c => printf("%c", c));

  // If you are not familiar with the shorthand lambda syntax,
  // I read c => foo(c) as "given c, produce foo(c)."
  //
  // Well... 'each' is different because it does not
  // produce anything. It its case: "given c, do this."
}

// This one dispatches filtering to another function but
// still uses a 'foreach' loop
void print2(T)(string prompt, T args...) {
  foreach (c; prompt.sansCurly) {
printf("%c", c);
  }
}

// I used R instead of 'string' in case it will be more useful
auto sansCurly(R)(R range) {
  return range.filter!(c => c != '{');
}

void main() {
  print("Hello, {world!\n", 10);
  print2("Hello, {world!\n", 10);
}

Ali



Re: Template arg deduction

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

On 7/7/21 12:14 PM, Kevin Bailey wrote:

> fairly simple template argument deduction

It's not the simplest but it is still complicated. :)

> I guess D can't crack open a type like that?

There are other ways of achieving the same thing the simplest of which 
is probably the following:


void func(B)(B f) {
}

Apparently, there are additional constraints on B, which can be 
expressed in D with some flexibility, pragmatism, and optimism.


Ali



Re: Remove array element within function

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

On 7/5/21 8:14 AM, Rekel wrote:

> On Monday, 5 July 2021 at 14:22:24 UTC, jfondren wrote:
>> What use of long?
>>
>> remove returns the same type of range as it gets:
>
> My apology, I meant to say countUntil instead of remove in that context.

countUntil says it returns ptrdiff_t, which is the signed version of size_t:

  https://dlang.org/spec/type.html#ptrdiff_t

size_t is an alias of 'long' on 64-bit systems (it would be 'int' on 
32-bit systems).


So, you needen't guess the type of count; it is ptrdiff_t :)

  ptrdiff_t index = countUntil(a, element);

However, its common to use 'auto' for return types of most algorithms as 
they may not be mentionable (although, not in this case; see Voldemort 
types):


  auto index = countUntil(a, element);

And I always think of 'const' first to prevent silly mistakes:

  const index = countUntil(a, element);

Some other people think of 'immutable' first in the same way:

  immutable index = countUntil(a, element);

All should work in this case but 'const' and 'immutable' will have a 
"turtles all the way down" behavior which may be cumbersome in some case 
e.g. when the type has indirections.


Ali



Re: How to call stop from parallel foreach

2021-06-25 Thread Ali Çehreli via Digitalmars-d-learn

On 6/25/21 7:21 AM, seany wrote:

> The code without the parallel foreach works fine. No segfault.

That's very common.

What I meant is, is the code written in a way to work safely in a 
parallel foreach loop? (i.e. Is the code "independent"?) (But I assume 
it is because it's been the common theme in this thread; so there must 
be something stranger going on.)


Ali



Re: How to call stop from parallel foreach

2021-06-25 Thread Ali Çehreli via Digitalmars-d-learn

On 6/25/21 6:53 AM, seany wrote:

> I tried this .
>
>  int[][] pnts ;
>  pnts.length = fld.length;
>
>  enum threadCount = 2;
>  auto prTaskPool = new TaskPool(threadCount);
>
>  scope (exit) {
>  prTaskPool.finish();
>  }
>
>  enum workUnitSize = 1;
>
>  foreach(i, fLine; prTaskPool.parallel(fld, workUnitSize)) {
>//
>  }
>
>
> This is throwing random segfaults.
> CPU has 2 cores, but usage is not going above 37%

Performance is not guaranteed depending on many factors. For example, 
inserting a writeln() call in the loop would make all threads compete 
with each other for stdout. There can be many contention points some of 
which depending on your program logic. (And "Amdahl's Law" applies.)


Another reason: 1 can be a horrible value for workUnitSize. Try 100, 
1000, etc. and see whether it helps with performance.


> Even much deeper down in program, much further down the line...
> And the location of segfault is random.

Do you still have two parallel loops? Are both with explicit TaskPool 
objects? If not, I wonder whether multiple threads are using the 
convenient 'parallel' function, stepping over each others' toes. (I am 
not sure about this because perhaps it's safe to do this; never tested.)


It is possible that the segfaults are caused by your code. The code you 
showed in your original post (myFunction0() and others), they all work 
on independent data structures, right?


Ali



Re: How to call stop from parallel foreach

2021-06-24 Thread Ali Çehreli via Digitalmars-d-learn

On 6/24/21 1:41 PM, seany wrote:

> Is there any way to control the number of CPU cores used in
> parallelization ?

Yes. You have to create a task pool explicitly:

import std.parallelism;

void main() {
  enum threadCount = 2;
  auto myTaskPool = new TaskPool(threadCount);
  scope (exit) {
myTaskPool.finish();
  }

  enum workUnitSize = 1; // Or 42 or something else. :)
  foreach (e; myTaskPool.parallel([ 1, 2, 3 ], workUnitSize)) {
// ...
  }
}

I've touched on a few parallelism concepts at this point in a presentation:

  https://www.youtube.com/watch?v=dRORNQIB2wA=1332s

Ali



Re: How to call stop from parallel foreach

2021-06-24 Thread Ali Çehreli via Digitalmars-d-learn

On 6/24/21 1:33 PM, Bastiaan Veelo wrote:

> distributes the load across all cores (but one).

Last time I checked, the current thread would run tasks as well.

Ali



Re: is it possible to sort a float range ?

2021-06-23 Thread Ali Çehreli via Digitalmars-d-learn

On 6/23/21 6:09 PM, mw wrote:

> I think in most other popular language's std lib:
>
> container.sort();
>
> or
>
> sort(container);
>
>
> is just one call, and the user will expect the `container` is sorted
> after the call.

That's exactly the same in D. What's different is, D's sort() does not 
return the original array (more generally, "random access range").


> If D want to convert more people from other more popular languages, it's
> better try to make this conversion as easy as possible.

Agreed but this is not an example of that situation. Instead of calling 
release(), one can return the array as well:


  import std.algorithm;
  lnumRange.sort!(r"a > b"c);
  return lnumRange;

I happen to like SortedRange. It's an interesting and useful experiment 
that constrains functionality. The problem with other languages, you can 
run "binary search" on any array (even if the array is not sorted. The 
correctness is left to the programmer, who is proven to be a source of 
bugs. Other languages will not complain at all... On the other hand, 
Phobos, with the help of SortedRange, protects the programmer from doing 
so: You can binary search only on a SortedRange, which is usually a 
cheap layer over an existing array or any other kind of RandomAccessRange.


As a system programmer, I appreciate assumeSorted() as well, which 
allows me to tell the compiler that "this array is really sorted." So, I 
think SortedRange is very useful.


Ali



Re: Default values in passing delegates to functions

2021-06-23 Thread Ali Çehreli via Digitalmars-d-learn

On 6/23/21 9:16 AM, Anonamoose wrote:

> I have a script in which I want a special case where someone can input
> something like a potential or a dispersion relation for use in physics
> simulations. I want to clean up the implementation for users as not
> every situation requires these. So I wrote a function with the signature
>
> ``` d
> void myFunc(Function initialFunc, int timeSteps, double initialTime,
> double finalTime, int depth,
>  double delegate(double, double) source = , double
> delegate(double, double) spacialDispersion = , bool
> userOutput = false) {...}

That function is expecting a 'delegate'...

> ```
> where
> ```d
> static double nullSource(double a, double b) {
>  return(0);
> }
> static double identitySource(double a, double b) {
>  return(1.0);
> }
> ```

But those are `function`s. (And `static` does not mean anything in D in 
that usage.)


> Is this a good method of implementation?

Yes, that would work if you deal with the `delegate` vs. `function` 
issue. For example, like using std.functional.toDelegate for the default 
arguments:


import std.functional;

// Ali's assumption; so that the code compiles.
alias Function = int function(int);

void myFunc(Function initialFunc, int timeSteps, double initialTime,
double finalTime, int depth,
double delegate(double, double) source = 
toDelegate(), double
delegate(double, double) spacialDispersion = 
toDelegate(), bool

userOutput = false)
{
  // ...
}

static double nullSource(double a, double b) {
  return(0);
}

static double identitySource(double a, double b) {
  return(1.0);
}

void main() {
}

Another approach is to take the functions (or delegates) as `alias` 
template parameters:


// Ali's assumption; so that the code compiles.
alias Function = int function(int);

void myFunc(alias source = nullSource,   // Template parameters
alias spacialDispersion = identitySource)
// Regular function parameters:
(Function initialFunc,
 int timeSteps,
 double initialTime,
 double finalTime,
 int depth,
 bool userOutput = false)
{
  // ...
}

static double nullSource(double a, double b) {
  return(0);
}

static double identitySource(double a, double b) {
  return(1.0);
}

void main() {
  // In this case, I am calling it with a lambda:
  myFunc!((a, b) => a + b)(null, 1, 2, 3, 4);
}

Ali



Re: what is D's idiom of Python's list.extend(another_list)?

2021-06-21 Thread Ali Çehreli via Digitalmars-d-learn

On 6/20/21 10:36 PM, mw wrote:

i.e append an array of elements into another array:


```Python
x = [1, 2, 3]
x.extend([4, 5])
print(x)  # [1, 2, 3, 4, 5]
```

Thanks.


There is also std.range.chain, which can visit multiple ranges in 
sequence without copying elements. This is a lifesaver when the arrays 
are very large.


import std.range;
import std.algorithm;

void main() {
  auto a = [ 1, 2, 3 ];
  auto b = [ 4, 5 ];
  auto expected = iota(1, 6);
  assert(chain(a, b).equal(expected));
}

Ranges can be very useful e.g. to sort elements of different random 
access ranges:


import std.range;
import std.algorithm;

void main() {
  auto a = [ 5, 1, 3 ];
  auto b = [ 4, 2 ];
  auto expected = iota(1, 6);

  // This time we sort:
  assert(chain(a, b).sort.equal(expected));

  // What? :)
  assert(a == [ 1, 2, 3]);
  assert(b == [ 4, 5 ]);
}

Ali



Re: how to filter associative arrays with foreach ?

2021-06-21 Thread Ali Çehreli via Digitalmars-d-learn

On 6/20/21 8:59 PM, someone wrote:
I often need to iterate through a filtered collection (associative 
array) as following:


```d
string strComputerIDunwanted = "WS2"; /// associative array key to exclude

foreach (strComputerID, udtComputer; udtComputers) { /// ..remove!(a => 
a == strComputerIDunwanted) ... ?


    if (strComputerID != strComputerIDunwanted) {

   ...

    }

}
```

Is there a way to filter the collection at the foreach-level to avoid 
the inner if ?


Two options for byKey and byKeyValue:


import std;

void main() {
  auto aa = [ "WS2" : 42, "WS3" : 43 ];
  string strComputerIDunwanted = "WS2";
  foreach (key; aa.byKey.filter!(k => k != strComputerIDunwanted)) {
writeln(key, ' ', aa[key]);
  }

  // 't' is the tuple of key and value
  foreach (t; aa.byKeyValue.filter!(t => t.key != strComputerIDunwanted)) {
writeln(t.key, ' ', t.value);
  }
}

Ali



  1   2   3   4   5   6   7   8   9   10   >