Re: Timeout around function call

2020-09-23 Thread Ali Çehreli via Digitalmars-d-learn

On 9/23/20 1:19 PM, Imperatorn wrote:

> No. You should not share anything. Personally I would just send a
> message to request termination or use the solution provided with timeout.

std.concurrency does not allow "mutable thread-local data"; so one needs 
to cast to shared (assuming copying is not desired e.g. because it's 
expensive). I am modifying my second program[1] with these changes:


The worker's receive() call mentions an element with shared ints:

receive(
  // .. same as before

  // New message type:
  (shared(int)[] arr) {
ownerTid.send(arr[0]);
  }
);

The sender casts to shared and receives a shared(int):

  auto arr = new int[100];
  worker.send(cast(shared)arr);
  writefln!"Received array result: %s"(receiveOnly!(shared(int))());

It is unfortunate that receiveOnly!int does not work because the 
returned int is just a copy. Well, at least we have a way of 
distinguishing int from shared(int). Is it useful?


Ali

[1] https://forum.dlang.org/post/rkdrql$2uht$1...@digitalmars.com


Re: Array of Algebraic argument syntax

2020-09-22 Thread Ali Çehreli via Digitalmars-d-learn

On 9/22/20 2:53 PM, Kasra Sadeghi wrote:

On Tuesday, 22 September 2020 at 21:36:48 UTC, Ali Çehreli wrote:

...
alias Value = Algebraic!(int, double, string, None);
...
void main() {
  printValue([Value(4.5), Value("hello"), Value(42)]);
}


Thanks! Wish there was a less redundant syntax for the arrays.




Do you really need to write literal Value arrays? If not, you would 
build a Value[] at runtime without seeing the syntax above.


Still, here is a function template that provides better syntax:

Value[] valueArray(Args...)(Args args) {
  Value[] result;
  foreach (arg; args) {
result ~= Value(arg);
  }
  return result;
}

void main() {
  printValue(valueArray(4.5, "hello", 42));
}

Ali



Re: Timeout around function call

2020-09-22 Thread Ali Çehreli via Digitalmars-d-learn
On 9/22/20 2:32 AM, drathier wrote:> What's the obvious way to put a 
timeout around a function call? I'm

> thinking a 5 or 30 second timeout, and I'm expecting it to pretty much
> never time out.

I would start a thread and use receiveTimeout():

import std.concurrency;
import std.stdio;
import std.exception;
import core.thread;

// Uncomment to see what happens upon time out.
// version = doTimeout;

void compute(int i) {
  version (doTimeout) {
writeln("The thread is napping.");
Thread.sleep(2.seconds);
  }
  ownerTid.send(i + 1);
}

void main() {
  auto worker = spawn(, 42);
  const received = receiveTimeout(
1.seconds,

(int result) {
  writefln!"Received the result: %s"(result);
}
  );

  enforce(received, "Timed out.");
}

The thread need not be one-shot: It can continue waiting for more 
messages until told to stop:


import std.concurrency;
import std.stdio;
import std.exception;
import core.thread;

// Uncomment to see what happens upon time out.
// version = doTimeout;

struct Done {
}

void computer() {
  bool done = false;
  while (!done) {
receive(
  (Done _) {
done = true;
  },

  (int i) {
version (doTimeout) {
  writeln("The thread is napping.");
  Thread.sleep(2.seconds);
}
ownerTid.send(i + 1);
  }
);
  }
}

void main() {
  // This time we use spawnLinked() so that we will receive
  // a LinkTerminated message. And the name is different and
  // the argument will be passed later with send().
  auto worker = spawnLinked();

  foreach (i; 0 .. 10) {
worker.send(i);
const received = receiveTimeout(
  1.seconds,

  (int result) {
writefln!"Received the result: %s"(result);
  }
);

enforce(received, "Timed out.");
  }

  // Tell worker to stop.
  worker.send(Done());

  // Wait for worker to terminate.
  receiveOnly!LinkTerminated();
}

Ali



Re: Array of Algebraic argument syntax

2020-09-22 Thread Ali Çehreli via Digitalmars-d-learn

On 9/22/20 2:30 PM, Kasra Sadeghi wrote:

Hi everyone!

What's the syntax for passing an array of Algebraics?

definition:

  class None {}
  class Value = Algebraic!(int, double, string, None);


That should be 'alias' instead of 'class':

import std.variant;
import std.stdio;

class None {}
alias Value = Algebraic!(int, double, string, None);

void printValue(Value[] values) {
  foreach(value; values) {
value.writeln;
  }
}

void main() {
  printValue([Value(4.5), Value("hello"), Value(42)]);
}

Ali



Re: QuickSort on ranges

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

On 9/12/20 11:25 AM, jerome wrote:

> 
> import std.stdio : writeln;
> import std.algorithm.sorting;
>
> pure void quickSort(T) (T[] r)
> {
>if (r.length > 1)
>{
>  size_t p = pivotPartition(r, r.length-1);  //r[$-1] is swapped 
to r[p]

>
>  quickSort( r[ 0..p ] );
>  quickSort( r[ p+1..$ ] );
>}
> }
>
> void main()
> {
>int[] arr = [9,7, 4 , 8, 5, 3, 1];
>quickSort!(int)(arr);

  // No need to specify int there because it's deduced from
  // the parameter. Pretty cool: :)
  quickSort(arr);

>writeln("arr : ", arr );
>
> }
> 
>
> I spent some time understanding "ranges", but at the end I am surprised
> I didn't use them. At the beginning I wrote something like quickSort(
> Range r ) and tried randomaccessrange etc but I didn't manage to make it
> work.

Agreed. The most common range type is InputRange and most algorithms 
don't require more than that. Combined with slices being the most common 
RandomAccessRange, it's not obvious why one needs to write algorithms 
that require RandomAccessRange.


So, your algorithm is very useful already but as you said, it can't work 
with all RandomAccessRanges:


  import std.range;
  auto arr2 = iota(5).array;
  quickSort(chain(arr, arr2));// <-- Compilation error

chain() is a very smart algorithm that return a range type that can be a 
RandomAccessRange if all the ranges given to it are RandomAccessRanges. 
(Pretty awesome and very practical that we can write ranges like chain() 
in D!)


So, to make your algorithm with any RandomAccessRange, we need to change 
it like this:


pure void quickSort(R) (R r)// <-- The only change

Now the quickSort(chain(arr, arr2)) expression can be compiled and the 
result is awesome too:


  // Wow! Your quickSort operated on the elements of two
  // separate ranges! :)
  writeln(arr);
  writeln(arr2);

Optionally, you can put a template constraint on your algorithm to 
communicate the fact that it can only work with RandomAccessRanges:


import std.range : isRandomAccessRange;

pure void quickSort(R) (R r)
if (isRandomAccessRange!R)// <-- Here
{
  // ...
}

Doing that moves potential compilation errors from your algorithm to the 
caller. For example, if they call your algorithm with int[string], they 
will get a compilation error saying "you can't call this function with 
int[string]".


Ali



Re: how to do this meta-programming? print the address of random element's address of a variable length of arrays?

2020-09-11 Thread Ali Çehreli via Digitalmars-d-learn

On 9/11/20 6:44 PM, mw wrote:> e.g.
>
> int[] a = new int[la];
> int[] b = new int[lb];
> int[] c = new int[lc];
> int[] d = new int[ld];
>
>
> the func I want to write, e.g. for 2 arrays (instantiation) is like this:
>
> void print_random_elem_addr(int[] x, int[] y) {
>auto i = random_int_between(0, x.length);
>auto j = random_int_between(0, y.length);
>print(&(x[i], &(y[j]));  // only single print() func call allowed!
> }
>
>
> But I want one generic function, which can be called as:
>
> print_random_elem_addr(a, b);
> print_random_elem_addr(a, b, c);
> print_random_elem_addr(a, b, c, d);

If they are all of same type like int[] in this case, then you can 
variable number of parameters, which means "any number of int[] arrays" 
below, elements of which can be called either as separate arguments or 
as a single array argument:


import std.stdio;
import std.random;

void print_random_elem_addr(int[][] arrays...) {
  foreach (i, array; arrays) {
const chosen = uniform(0, array.length);
writefln!"Array %s, element %s: %s"(i, chosen, [chosen]);
  }
}

void main() {
  auto randomLengthArray() {
return new int[uniform(1, 101)];
  }

  auto a = randomLengthArray();
  auto b = randomLengthArray();
  auto c = randomLengthArray();

  writeln("As independent arguments:");
  print_random_elem_addr(a, b, c);

  writeln("As a single argument:");
  print_random_elem_addr([a, b, c]);
}

Warning: The array that is automatically generated by the first 
print_random_elem_addr() call in main() is short-lived: You cannot store 
a slice of it because the array that contains the arguments may be 
destroyed upon leaving the function (e.g. in the "independent" case above).


Here is some more information:


http://ddili.org/ders/d.en/parameter_flexibility.html#ix_parameter_flexibility.variadic%20function

There are other ways of doing the same thing. For example, if you want 
to work with different ranges, you can use tuple template parameters:



http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.tuple%20template%20parameter

Ali




Reducing .init effect of a struct that has large static array members

2020-09-10 Thread Ali Çehreli via Digitalmars-d-learn
[tldr; I have come up with a way of removing all undesired effects of 
large static array struct members. See conclusion at the bottom.]


Continuing the discussion at

  https://forum.dlang.org/thread/rdk3m2$725$1...@digitalmars.com

and understanding kinke's comments there better... And this is all with 
dmd...



1) Assuming that static array members are really required in the 
program, the following definition is not desirable because S.init is 
embedded into the binary image as 8000 bytes (I have much bigger ones in 
the wild):


struct S {
  double[1000] a;
}

static assert (S.init.sizeof == 8000);
// That S.init is embedded into the binary

One way of proving that S.init is indeed embedded into the binary is 
running obj2asm that is shipped with dmd: 'obj2asm deneme.o')


So, that is not good.


2) In order to remove that huge S.init from the program, one can 
initialize the member with '= void':


struct S {
  double[1000] a = void;
}

pragma(msg, S.init); // <-- Aside: As a side effect, this output is
 // now just "S()" and does not include
 // an array of 1000 elements.

Although now the binary does not contain an S.init of 8000 bytes, it 
contains CPU instructions to set 1000 elements:


xor EAX,EAX
mov 0E0C0h[RBP],EAX
mov 0E0C4h[RBP],EAX
[... many more to set all elements ...]

WAT!!! :)

That is not good either because now the compiled code is large. (I think 
and hope other compilers use memset() here.)


As explained in that earlier thread and as seen above, contrary to spec 
(perhaps to an earlier spec?) and fortunately, '= void' does not "leave 
the elements uninitialized" but the elements are now 0.0.


So, that's doubly [pun] bad: The code is large and the elements are not 
double.nan.



3) To remove that huge struct initialization code, one can @disable the 
default constructor. And to provide double.nan values, one can provide a 
function; which may be named specially, or marked with a UDA or some 
other way. Below, I use a constructor that takes a special type to mark 
that this is my "default constructor":


struct DefaultCtor {}// <-- My special "marker"

struct S {
  double[1000] a = void;
  @disable this();

  this(DefaultCtor) {// <-- My "default constructor"
a[] = double.init;   // <-- Good: not 0.0 anymore
  }
}

void main() {
  auto s = S(DefaultCtor());// <-- But now the syntax is ugly

  import std;
  assert(s.a[42].isNaN);
}


4) CONCLUSION: The following 'defaulted' template makes the syntax 
acceptable as well at least for Ali:


struct DefaultCtor {} // Special type used as a user-defined UDA ;)

struct S {
  double[1000] a = void;  // To not embed S.init into the binary
  @disable this();// To not generate many CPU instructions

  this(DefaultCtor) { // My "default constructor". (This could
a[] = double.init;// be a template to not even need a
  // theoretical rvalue parameter.)
  }
}

template defaulted(T) {  // Generic template for my default constructor 
syntax

  enum defaulted = {
return T(DefaultCtor());
  }();
}

void main() {
  auto s = defaulted!S;  // My default construction syntax
}

That method works for me. Am I missing something?

Ali


Re: how stdin stream works?

2020-08-20 Thread Ali Çehreli via Digitalmars-d-learn

On 8/19/20 11:46 AM, Flade wrote:

Try instead getting a line via readln, and then trying to read that 
into your expected input.


-Steve


Thanks Steve! I will get the input a string then as you said and then 
I'll try to convert it! Thanks a lot, have a nice day!


In some cases clearerr() and readln() may be what is needed:

import std.stdio;

void main() {
  int x;

  bool accepted = false;

  while (!accepted) {
try {
  write("x: ");
  readf(" %d", x);
  accepted = true;

} catch (Exception msg) {

  writeln("Please give a right coordinate");
  stdin.clearerr();
  stdin.readln();
}
  }

  writeln("x is ", x);
}

Note that I used " %d" because "%d/n" would not clean when nothing was 
input by just hitting the Enter key. A space character in the format 
string means "read and ignore any whitespace at this point" and I like 
it. :)


Also note I changed the name of the variable as 'accepted'. :)

Ali


Re: Disjoint slices of an array as reference

2020-08-20 Thread Ali Çehreli via Digitalmars-d-learn

On 8/19/20 9:11 PM, data pulverizer wrote:

On Thursday, 20 August 2020 at 03:47:15 UTC, Paul Backus wrote:

double[][] y;
y ~= x[0..5];


Thanks. I might go for a design like this:

```
struct View(T){
   T* data;
   long[2][] ranges;
}
```
The ranges are were the slices are stored and T* (maybe even 
immutable(T*)) is a pointer is to the start of the original array. I'll 
use an opIndex that calculates the correct index in the original array 
to obtain the right data.




I implemented the same idea recently; it's a fun exercise. :) I didn't 
bother with opIndex because my use case was happy with just the 
InputRange primitives (and .length I think).


And I had to implement it because std.range.chain works only with 
statically known number of sub-ranges. :/ If the number of ranges are 
known, then this works:


import std.stdio;
import std.range;

void main() {
  auto x = [1,  2,  3, 4,  5,
6,  7,  8, 9,  10,
11, 12, 13, 14, 15];
  auto y = chain(x[0..5], x[9..14]);
  writeln(y);
}

[1, 2, 3, 4, 5, 10, 11, 12, 13, 14]

Ali



Re: Disjoint slices of an array as reference

2020-08-20 Thread Ali Çehreli via Digitalmars-d-learn

On 8/19/20 7:40 PM, data pulverizer wrote:

> An array in D is either two pointers or one pointer and a length (I
> don't know which)

It is the length, followed by the pointer, equivalent of the following 
struct:


struct A {
  size_t length_;
  void * ptr;

  size_t length() {
return length_;
  }

  size_t length(size_t newLength) {
// Modify length_ and ptr as necessary
  }
}

Ali



Re: Factory pattern for classes

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

On 8/10/20 8:38 AM, lexxn wrote:

Btw is it possible to pass a property to the constructor, if I've one 
declared, in the factory? I'm talking about this piece 
cast(A)Object.factory("deneme.A")


I think you mean "parameter". No, Object.factory creates the object with 
its default constructor.



Ali


Re: generating random numbers

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

On 8/9/20 10:51 PM, Andy Balba wrote:
generating random numbers using 
https://dlang.org/library/std/random/uniform01.html


I find the example given in this section totally incomprehensible
... Can any help me answer two simple questions:
How to generate a random floating number in range [0,1) ?
How to set a seed value, prior to generating random values ?


I think feqrel() is the confusing and unnecessary part there. The 
following is all you need:


import std.stdio;
import std.random;

void main() {
  auto rnd = MinstdRand0(42);  // <-- Seed
  foreach (i; 0 .. 10) {
writeln(rnd.uniform01());
  }
}

feqrel, defined at

  https://dlang.org/phobos/std_math.html#.feqrel

is used to prove that the first two floating point values generated are 
equal to 0.000328707 and 0.524587. (Check out the return value of 
feqrel, which is used in assert statements there to prove that the 
numbers are "equal" to those.)


Ali


Re: Factory pattern for classes

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

On 8/9/20 7:27 AM, lexxn wrote:

> I assume that the correct syntax for the getClassById is
> Object getClassById(uint id) {
>  if (id == 0) {
>  return new A();
>  } else if (id == 1) {
>  return new B();
>  } else {
>  return new C();
>  }
> }
> or maybe I'm wrong.

Because those example classes are not a part of a hierarchy, their 
common interface is Object. That is the only way to get the code compile.


> This way if I try auto myClass = getClassById(0) and
> if I've a method in A,B classes when I try to call it with myClass I
> get no property methodName for type object.Object.

If methodName() is a virtual function of your hierarchy, then normally 
it is a part of an interface that all those classes implement and the 
return type is that common ancestor. Here is a working example:


module deneme;

import std.stdio;

interface I {
  void methodName();
}

class A : I {
  void methodName() {
writeln("A");
  }
}

class B : I {
  void methodName() {
writeln("B");
  }
}

class C : I {
  void methodName() {
writeln("C");
  }
}

I getClassById(uint id)
{
if (id == 0) {
return cast(A)Object.factory("deneme.A");
} else if(id == 1) {
return cast(B)Object.factory("deneme.B");
} else {
return cast(C)Object.factory("deneme.C");
}
}

void main() {
  auto o = getClassById(1);
  o.methodName();
}

Ali



Re: Non-recursive maxSizeOf

2020-08-06 Thread Ali Çehreli via Digitalmars-d-learn

On 8/6/20 4:44 AM, Per Nordlöw wrote:

On Thursday, 6 August 2020 at 01:13:28 UTC, Ali Çehreli wrote:

Boring in D. :p

template maxSizeOf(T...) {
  enum maxSizeOf = compute();

  auto compute() {
    size_t result;
    static foreach (t; T) {
  if (t.sizeof > result) {
    result = t.sizeof;
  }
    }
    return result;
  }
}


Thanks. I'm gonna benchmark this against my templated solution.


I guess an anonymous function would remove the need for that creative 
name. :)


  enum maxSizeOf = {
// ...
  }();

Ali



Re: Non-recursive maxSizeOf

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

On 8/5/20 5:58 PM, Per Nordlöw wrote:

Is it possible to implement

template maxSizeOf(T...)
{
     static if (T.length == 1)
     enum size_t maxSizeOf = T[0].sizeof;
     else
     {
     enum size_t firstSize = T[0].sizeof;
     enum size_t maxSizeRest = maxSizeOf!(T[1 .. $]);
     enum size_t maxSizeOf = firstSize >= maxSizeRest ? firstSize : 
maxSizeRest;

     }
}

in a non-recursive way?


Boring in D. :p

template maxSizeOf(T...) {
  enum maxSizeOf = compute();

  auto compute() {
size_t result;
static foreach (t; T) {
  if (t.sizeof > result) {
result = t.sizeof;
  }
}
return result;
  }
}

void main() {
  pragma(msg, maxSizeOf!(double, char, string));
}

Ali



Re: Question about UDAs

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

On 8/2/20 8:00 PM, Cecil Ward wrote:

> Ali Çehreli’s book mentions them briefly with an example
> but that doesn’t seem to qualify as a realistic use-case.

The XML example I chose there qualifies as serialization like H. S. Teoh 
mentions. UDAs on user-defined type members are for marking them for 
later introspection in use cases like "do this for all members but take 
UDAs into account." For example, the UDA in my example contributes as 
"serialize all members as XML but obfuscate the members that have a 
special UDA."


UDAs were added to D by a request from Manu Evans and that's when I 
learned them. In one of Manu's use cases they would put a @Tweakable 
attribute to certain struct members. The effect of that attribute would 
be to compile special code that would expose that member in a dialog box 
where the developer would "tweak" its value to see how the program (a 
game) would behave at specific values of that member.


The awesomeness comes from the fact that once they have this @Tweakable 
machinery, they don't change their code at all: They put that attribute 
to certain members during development, find good values and then remove 
it; perhaps in half an hour. The only addition to code is one @Tweakable 
attribute and some magic produces a dialog box; then they remove the 
attribute. Pretty cool. :)


Manu's presentatian is available here:

 https://www.youtube.com/watch?v=FKceA691Wcg

Slide 25 at minute 18:30 is one spot he talks about it.

Ali




Re: 2-D array initialization

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

On 8/1/20 7:00 PM, Andy Balba wrote:

>> >> ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35,
>> 35,35]  ];

> Although not detailed in my original question, in my actual app
> I have array ubyte [1000][3] Big which consists of research data I
> obtained,
>   and from which I want to randomly select 4 observations to construct
> ubyte c[ ][ ].

It depends on how the data is layed out. Your original question makes me 
think the data is "code generated" into a D module and that's where you 
want to initialize that 2D fixed-length (static) array.


So, you simply want to import that module in your analysis program:

import data;

However, I really think the type should be ubyte[3][].

The following option reads the data from a file before analysis. 
Assuming the data is formatted one ubyte on a line:


--- 8< ---
5
5
5
15
15
15
25
25
25
35
35
35
--- 8< ---

then the following program does what you want:

import std.stdio : File, writefln;
import std.algorithm : map;
import std.range : array, chunks;
import std.string : strip;
import std.conv : to;
import std.random : choice;

auto parseData(string fileName) {
  return
File(fileName)   // - Open the file
.byLine  // - Iterate line-by-line as a range
 //   (WARNING: same line buffer is
 //   shared use byLineCopy if
 //   necessary.)
.map!strip   // - Strip the element
.map!(to!ubyte)  // - Convert to ubyte
.chunks(3)   // - Treat 3 consecutive elements as one
 //   unit
.map!(c => c.array)  // - Make an array from each chunk
;

  // NOTE: The returned range object is a chain of
  // operations to apply on fileName. Nothing will be read
  // from the file until the returned range is actually
  // used (i.e. the range is "lazy").
}

void main() {
  auto c = parseData("research_data")  // - The lazy range
   .array; // - As we want to pick
   //   random elements; we
   //   convert the data
   //   range to an
   //   array. This step is
   //   "eager": the entire
   //   file is parsed here.

  // Demonstrate that the type is a 2D array
  static assert (is (typeof(c) == ubyte[][]));

  // The rest is a random choice from that array:
  foreach (_; 0 .. 10) {
auto chosen = c.choice;
writefln!"chosen: %s"(chosen);
  }
}

If the three ubytes should actually be used as parts of a struct like 
Color, here is another approach:


import std.stdio;
import std.algorithm;
import std.range;
import std.string;
import std.conv;
import std.random;

struct Color {
  ubyte r;
  ubyte g;
  ubyte b;
}

// Assumes data is one ubyte per line
auto parseData(string fileName) {
  return
File(fileName)
.byLine
.map!strip
.map!(to!ubyte);
}

auto makeColors(R)(R range) {
  Color[] colors;

  while (!range.empty) {
ubyte pop() {
  auto value = range.front;
  range.popFront();
  return value;
}

auto r = pop();
auto g = pop();
auto b = pop();

colors ~= Color(r, g, b);
  }

  return colors;
}

void main() {
  auto data = parseData("research_data");

  auto c = makeColors(data);
  writefln!"data:\n%(%s\n%)"(c);

  foreach (_; 0 .. 10) {
auto chosen = c.choice;
writefln!"chosen: %s"(chosen);
  }
}

Sorry my liberal use of 'auto', which hides types. You can define 'c' 
with explicit types like Color[], or you can expose a variable's type at 
compile time with pragma(msg):


  pragma(msg, "the type: ", typeof(c));

That prints Color[] for the second program above.

Ali



Re: 2-D array initialization

2020-08-01 Thread Ali Çehreli via Digitalmars-d-learn

On 8/1/20 12:57 PM, Andy Balba wrote:

> On Saturday, 1 August 2020 at 00:08:33 UTC, MoonlightSentinel wrote:
>> On Friday, 31 July 2020 at 23:42:45 UTC, Andy Balba wrote:
>>> How does one initialize c in D ?
>>
>> ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 35,35]  ];

> I'm a D newbie. moving over from C/C++, and I'm really finding it hard
> to adjusting to D syntax, which I find somewhat cryptic compared to 
C/C++.


That's surprising to me. I came from C++03 year ago but everything in D 
was much better for me. :)


I wanted to respond to your question yesterday and started typing some 
code but then I decided to ask first: Do you really need a static array? 
Otherwise, the following is a quite usable 2D array:


  ubyte[][] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 35,35]  ];

However, that's quite different from a ubyte[3][4] static array because 
'c' above can be represented like the following graph in memory. (Sorry 
if this is already known to you.)


c.ptr --> | .ptr | .ptr | .ptr | .ptr |
  |  |  |  |
  .  .  |   --> | 35 | 35 | 35 | 35 |
 etc.   etc. --> | 25 | 25 | 25 | 25 |

In other words, each element is reached through 2 dereferences in memory.

On the other hand, a static array consists of nothing but the elements 
in memory. So, a ubyte[3][4] would be the following elements in memory:


  | 5 | 5 | ... | 35 | 35 |

One big difference is that static arrays are value types, meaning that 
all elements are copied e.g. as arguments during function calls. On the 
other hand, slices are copied just as fat pointers (ptr+length pair), 
hence have reference semantics.


Here are some ways of initializing a static array. This one is the most 
natural one:


  ubyte[3][4] c = [ [5, 5, 5], [15, 15,15], [25, 25,25], [35, 35,35]  ];

Yes, that works! :) Why did you need to cast to begin with? One reason 
may be you had a value that could not fit in a ubyte so the compiler did 
not agree. (?)


This one casts a 1D array as the desired type:

  ubyte[3][4] c = *cast(ubyte[3][4]*)(cast(ubyte[])[ 5, 5, 5, 15, 15, 
15, 25, 25, 25, 35, 35, 35 ]).ptr;


The inner cast is required because 5 etc. are ints by-default.

There is std.array.staticArray as well but I haven't used it.

Ali



Re: dynamic array .length vs .reserve - what's the difference?

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

On 7/30/20 4:42 PM, wjoe wrote:

> So .capacity can't be assigned a value like length to reserve the RAM ?

Yes, a read-only property...

>> auto a = b;
>> b = b[0 .. $-1];
>> b ~= someT;
>>
>> If that last line is done in-place, then it overwrites a[$-1].
>
> So this is a case of sharing being terminated ?

Yes but the "sharing being terminated" phrase was my attempt at 
explaining things, which did not catch on. :)


> Expired structs are put back into (appended to) the array for reuse.
> When the length of the array == 0, upon releasing a struct, this array
> is reallocated which isn't supposed to happen. It should just grow like
> it did with length > 1.
> assumeSafeAppend should accomplish that :)

Yes, assumeSafeAppend is exactly for cases like that and it helps.

Another option, which is curiously said to be more performant in memory 
allocation than native arrays, is std.array.Appender. I've used 
function-local static Appenders to cut down on memory allocation. Here 
is an uncompiled pseudo code:


void foo() {
  static Appender!int a;
  a.clear();  // <- Clear state from last execution of this function.
  //'a' still holds on to its memory.

  while (someCondition()) {
a ~= 42;
  }

  // Use 'a' here
}

So, 'a' will have the longest length ever used up to this point, which 
may be exactly what is desired.


The cool thing is, because data is thread-local by-default in D, every 
thread gets their own copy of 'a', so there is not danger of data race. 
:) (Warning: Don't call foo() recursively though. ;) )


Ali



Re: dynamic array .length vs .reserve - what's the difference?

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

On 7/30/20 8:58 AM, wjoe wrote:


     b.reserve(n);
     b.length = n;


There may be something that I don't know but I think assigning to the 
.length property alone should be the same as reserving and then assigning.


reserve is supposed to make sure no memory will be allocated as elements 
are added.


capacity tells how many elements can be added without memory is 
allocated. However, the D runtime does its best to elide actual memory 
allocation if there is room beyond the array's last element and it's 
safe to do so.


This article is considered a must-read for understanding what is going 
on behind the scenes:


  https://dlang.org/articles/d-array-article.html

I tried to introduce the concept of slices "sharing elements" as well as 
how .capacity is used to determine whether sharing will be terminated, here:


  http://ddili.org/ders/d.en/slices.html#ix_slices..capacity

Ali



Re: is using predSwitch the only way to create to create recursive functions in D ?

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

On 7/29/20 3:13 PM, Andy Balba wrote:

,,


Not at all. The wording in the documentation is misleading.

Recursive functions are as trivial as they are:

int foo(uint i) {
  if (i == 0) {
return 42;
  }

  return foo(i - 1);
}

void main() {
  assert(foo(7) == 42);
}

Ali


Re: Using D within a rust codebase

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

On 7/27/20 4:43 AM, Ali Çehreli wrote:
On 7/27/20 3:50 AM, Jacob Carlborg wrote:> On 2020-07-27 03:03, Paul 



 > The D runtime needs to be initialized first [1]. Then it should be
 > terminated as well [2].
 >
 > [1] https://dlang.org/phobos/core_runtime.html#.rt_init


[...]


pragma (crt_constructor)
extern (C)
int lib_init() {
   return Runtime.initialize() ? 0 : 1;
}


Ok, now I learned that my bool-to-int conversion is already taken care 
of by rt_init(). Cool. :)


Ali



Re: Using D within a rust codebase

2020-07-27 Thread Ali Çehreli via Digitalmars-d-learn
On 7/27/20 3:50 AM, Jacob Carlborg wrote:> On 2020-07-27 03:03, Paul 
Backus wrote:

>
>> extern(C) void hello()
>> {
>>  import std.stdio: writeln;
>>  writeln("Hello from D!");
>> }
>
> The D runtime needs to be initialized first [1]. Then it should be
> terminated as well [2].
>
> [1] https://dlang.org/phobos/core_runtime.html#.rt_init
> [2] https://dlang.org/phobos/core_runtime.html#.rt_term
>

They should be taken care of when the program is linked with a D compiler.

Otherwise, e.g. when the extern(C) code is part of a library written in 
D, one way of doing it is to add the following two functions to the 
library. (Typing by hand; may have typos).


import core.runtime;

pragma (crt_constructor)
extern (C)
int lib_init() {
  return Runtime.initialize() ? 0 : 1;
}

pragma (crt_destructor)
extern (C)
int lib_deinit() {
  return Runtime.terminate() ? 0 : 1;
}

Ali



Re: miscellaneous array questions...

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

On 7/20/20 8:16 PM, a...@a.com wrote:

>> 3) Lastly, In the following code snippet, is arrayA and arrayB both
>> allocated on the stack?

arrayA is allocated on thread-local storage and lives as long as the 
program is active. I guess a final interaction with it can be in a 
'static ~this()' or a 'shared static ~this()' block.


Note that this is different from e.g. C++: In that language, arrayA 
would be a "global" variable and there would be a single instance of it. 
In D, there will be as many arrayA variables as there are active 
threads. (One thread's modification to its own arrayA is not seen by 
other threads.)


arrayB is allocated on the stack and lives as long as the scope that it 
is defined inside. That scope is main's body in your code.


> And how does their scopes and/or lifetimes
>> differ?
>>
>>  module1 =
>> int[100] arrayA;
>> void main()
>> {
>> int[100] arrayB;
>> // ...
>> }
>>  module1 =

Ali



Re: How can I make executeShell ask for Admin Elevation?

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

On 7/11/20 7:10 PM, Marcone wrote:
I don't want start program with admin elevation, but ask user for admin 
permission when some function is called.


Here is a hacky solution that attempts the command and fails back to 
asking the password. It should work on POSIX systems. (Tested on Linux.)


import std.stdio;
import std.process;
import std.format;
import std.algorithm;

// Copied the interface from executeShell
auto executeShellSudo(scope const(char)[] command,
  const string[string] env = null,
  Config config = Config.none,
  size_t maxOutput = size_t.max,
  scope const(char)[] workDir = null,
  string shellPath = nativeShell) {
  // First assume the user is super user:
  auto suCommand = format!"sudo --non-interactive %s"(command);
  auto execute() {
return executeShell(suCommand, env, config, maxOutput, workDir, 
shellPath);

  }

  auto result = execute();

  if ((result.status == 1) &&
  (result.output == "sudo: a password is required\n")) {

// Have sudo ask for password. (Alternatively, sudo can be invoked
// with the --askpass switch.)
suCommand = format!"sudo %s"(command);
result = execute();
  }

  return result;
}

void main() {
  auto result = executeShellSudo("cat /dev/null");
  writeln(result);
}

Ali


Re: What's the point of static arrays ?

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

On 7/10/20 8:03 AM, wjoe wrote:

> What I'm saying is even if this allocation is slow let's say 5ms, but it
> only happens once, that wouldn't matter to overall performance at all.

Yes, you are correct and there are dynamic arrays that are allocated 
once in many programs.


I haven't read the rest of your post but you've said elsewhere that a 
static array is on the stack. Yes, there are such static arrays but the 
issue is not that simple.


struct S {
  float[3] rgb;  // Can be on the stack or dynamic memory
}

The member of that struct can be anywhere:

void foo() {
  S s;// On the stack
  auto arr = [ S() ]; // On dynamically allocated memory
}

Additionally, as is common and understandable in D, we are conflating 
dynamic arrays and slices. The way I see it is dynamic array is owned by 
the D runtime. Although a slice is an interface to such dynamic arrays, 
a slice can start its life with non-dynamic arrays and may or may not 
move to accessing dynamic arrays.


struct S {
  float[] arr;  // A slice can use dynamic or static memory
}

void foo() {
  float[10] storage;
  auto a = S(storage[1..7]);  // Slice is referring to the stack space
  auto b = S();
  b.arr ~= 1.5;   // Slice is referring to dynamic memory
}

What is important is overhead:

1) Allocation: Only sometimes an issue.

2) Cost of the slice object (1 pointer and 1 size_t): The cost of this 
may be enormous. (Compare the 12-byte rgb above to a 16-byte slice 
overhead.)


3) Cost of accessing the elements: The access through that extra level 
of indirection may be a cost but the CPU can alleviate it by 
pre-fetching or caching but only for some access patterns.


4) Bounds checking: Some bounds checks for static arrays can be elided 
at run time.


So, there are cases where a dynamic array is better (or must), there are 
cases there is no winner and there are cases where a static array is a 
huge win.


Ali



Re: What's the point of static arrays ?

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

On 7/9/20 5:12 AM, wjoe wrote:

Considering the many downsides why would I ever want to choose a static 
over a dynamic array ?




In addition to what others said, dynamic arrays can be more expensive 
both in space and time.


Time: Dynamic array elements are accessed through an extra pointer 
compared to static arrays. Depending on the usage pattern of the data, 
that extra indirection may be slower (e.g. due to the extra load on the 
CPU's cache).


Space: Every dynamic array is represented by the pair of one pointer 
(void*) one length (size_t) e.g. 2 * 8 = 16 bytes on a 64-bit system. 
Assuming the array is just 3 floats, which is a common type used for 
RGB, 3D coordinates, etc. (3 * 4 = 12 bytes), then those 16 bytes are 
more than the data itself.


I wrote the following program (as a fun morning exercise, before coffee 
:o) ) to display bytes used by different kinds of variables:


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

size_t bytesUsed(T)(T var) {
  static if (isDynamicArray!T) {
enum dynamicArrayOverhead = (void[]).sizeof;
// Double check:
static assert (dynamicArrayOverhead == size_t.sizeof + (void*).sizeof);

return dynamicArrayOverhead + var.map!(element => 
bytesUsed(element)).sum;


  } else static if (isAssociativeArray!T) {
static assert (false, "I don't know the implementation of AAs.");

  } else static if (is (T == struct)) {
// BUG: Ignores alignment
size_t total;
foreach (member; var.tupleof) {
  total += bytesUsed(member);
}
return total;

  } else static if (is (T == class)) {
// BUG: Ignores alignment
size_t total;
foreach (member; var.tupleof) {
  total += bytesUsed(member);
}
enum classOverhead = (void*).sizeof * 2;
return classOverhead + total;

  } else {
return var.sizeof;
  }

// BUG: union?
}

unittest {
  struct S {
int[] arr;
void* ptr;
  }
  assert(bytesUsed(S([1, 2, 3])) == size_t.sizeof + (void*).sizeof + 3 
* int.sizeof + 8);

}

void info(alias var)() {
  writefln!"'%s' is %s and uses %s bytes."(var.stringof, 
typeof(var).stringof, bytesUsed(var));

}

void main() {
  // This is an efficient data structure:
  alias Color = float[3]; // red, green, blue
  alias DayColors = Color[7];

  // Comparing it to the dynamic array equivalent:
  DayColors a;
  auto b = makeDayColors();
  info!a;
  info!b;
}

float[] makeColor() {
  // Syntax confusion alert: Return type is *not* a static array. :/
  return new float[3];
}

float[][] makeDayColors() {
  float[][] result = new float[][7];
  foreach (ref e; result) {
e = makeColor();
  }
  return result;
}

Ali


Re: Template function specialization doesn't work

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

On 7/7/20 12:53 PM, IGotD- wrote:


ubyte[3] ar = [ 1, 2, 3 ];
ubyte[] arSlice = ar;

overloadedFunction(arSlice);

The first function will be used. Shouldn't the template argument (T : 
T[]) make the compiler pick the second one?


There is also template constraints which may be useful:

import std.traits;

void overloadedFunction(T)(ref T val)
if (!isArray!T) {
  writeln("general");
}

void overloadedFunction(T)(ref T s)
if (isArray!T) {
  writeln("T[]");
}

Ali




Re: opApply and attributes

2020-07-07 Thread Ali Çehreli via Digitalmars-d-learn
On 7/6/20 5:20 PM, solidstate1991 wrote:> See implementation of data 
structure here:
> 
https://github.com/ZILtoid1991/collections-d/blob/master/source/collections/treemap.d#L565 


>
>
> If I try to compile this code, it'll fail, limiting it's usecase:
>
> @safe pure unittest {
>  alias IntMap = TreeMap!(int, int, false);
>  IntMap test;
>  test[5] = 5;
>  test[7] = 7;
>  test[3] = 3;
>  foreach(elem, key; test) {
>  assert(elem == key);
>  }
> }

I am not sure whether I understand it correctly but there has been a 
request for opApply() to gain the attributes of the delegate (or the 
range?). In other words, "transfer the attributes to opApply". This is 
needed because I want opApply() to work with any foreach body, 
attributes of which opApply() cannot know.


I am sure I created an issue on Dlang bug tracker for Weka on this topic 
but I can't find it now. (Aside: The search boxes on the bug tracker are 
inferior to the automatic search feature that works when creating a 
bug.) Anyway, this one seems related:


  https://issues.dlang.org/show_bug.cgi?id=7543

Ali



Re: I need an Easy example to understand Alias This

2020-07-06 Thread Ali Çehreli via Digitalmars-d-learn

On 7/6/20 5:44 PM, Marcone wrote:

On Tuesday, 7 July 2020 at 00:42:40 UTC, Ali Çehreli wrote:

On 7/6/20 5:35 PM, Marcone wrote:
Hi, I study Dlang for one year, and I can't understand alias this. I 
need an Easy example to understand Alias This.


Is the following example useful?

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

Ali


I can't undestand it. I need a simple example.


I find the example of converting two integers to double to be a simple 
example of 'alias this'. (If it's not simple, then there is another 
example later.)


So, allow me to change the name of the struct. :) Let's say we have a 
Money class that stores dollars and cents as two separate members. This 
class also has a member function that returns the amount as double:


struct Money {
  long dollars;
  long cents;

  double value() const {
return double(cents) / 100 + dollars;
  }
}

unittest {
  assert(Money(10, 50).value == 10.5);
}

void main() {
}

So far so good: We can get the value by calling value().

*If* this is a type where conversion to double should be automatic, then 
calling value() all over the place might be considered cumbersome and 
too wordy. If that's true, we may want to get the value of this type 
automatically as double. For example, we may want to be able to call the 
following function with Money:


void foo(double d) {
  // ...
}

void main() {
  foo(Money(20, 50));  // <-- Compilation error
}

Currently the code fails to compile because Money is not 'double'. 
(Note: Arguably, Money is not a type that should be converted to double 
automatically, but again, I find this example simple.)


'alias this' allows a type to be converted to a specific type 
automatically. For example, if we want to convert Money objects 
automatically to 'double', then we use the following line inside the 
struct defition:


  alias value this;

What that line means is this: "Dear compiler, please automatically 
convert this type to whatever the type of the 'value' member is." In 
this case, "Allow using an object of Money wherever that object is used 
in place of a double."


So, with that addition, now the call inside main compiles and foo() gets 
called with 'Money(20, 50).value' (compiler injects an automatic call to 
value()).


Here is the complete program:

struct Money {
  long dollars;
  long cents;

  double value() const {
return double(cents) / 100 + dollars;
  }

  alias value this;  // <-- ADDED
}

unittest {
  assert(Money(10, 50).value == 10.5);
}

void foo(double d) {
  // ...
}

void main() {
  foo(Money(20, 50));
}

'alias this' is sometimes used where a type needs to behave like some 
other type with some added functionality. For example, here is another 
example where a Month type should behave like an 'int' but it cannot 
have any value other than 1-12:


struct Month {
  int value;

  this(int value) {
this.value = value;
  }

  invariant() {
assert(value >= 1);
assert(value <= 12);
  }

  alias value this;
}

unittest {
  import std.exception;

  assertThrown!Error(Month(0));
  assertThrown!Error(Month(13));

  void foo(int) {
  }

  // 'alias this' allows the following call to foo()
  assert(__traits(compiles, foo(Month(3;
}

void main() {
}

Ali



Re: I need an Easy example to understand Alias This

2020-07-06 Thread Ali Çehreli via Digitalmars-d-learn

On 7/6/20 5:35 PM, Marcone wrote:
Hi, I study Dlang for one year, and I can't understand alias this. I 
need an Easy example to understand Alias This.


Is the following example useful?

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

Ali


Re: Generating struct .init at run time?

2020-07-02 Thread Ali Çehreli via Digitalmars-d-learn

On 7/2/20 10:51 AM, kinke wrote:

On Thursday, 2 July 2020 at 16:51:52 UTC, kinke wrote:
`= void` for members doesn't work and, I dare say, not work anytime 
soon if ever.


I've quickly checked; `= void` for members has initialize-with-zeros 
semantics too, so with LDC, it's equivalent to `= 0` but applicable to 
user-defined types as well.
For DMD, `= void` for non-default-zero-initialized members can be used 
for the same effect. If all members are effectively zero-initialized, 
the init symbol isn't emitted, and the compiler initializes the whole 
struct with zeros. With `= 0`, DMD still emits the init symbol into the 
object file, but doesn't use it (at least not for stack allocations).


TLDR: Seems like initializing (all non-default-zero-initialized) members 
with `= void` is the portable solution to elide the init symbols *and* 
have the compiler initialize the whole struct with zeros, so a manual 
memset isn't required.


Thank you! I just checked: Even 2.084 behaves the same. I will deal with 
double.nan, etc. for structs where they matter.


Ali



Re: Generating struct .init at run time?

2020-07-02 Thread Ali Çehreli via Digitalmars-d-learn

On 7/2/20 3:37 AM, kinke wrote:

> On Thursday, 2 July 2020 at 07:51:29 UTC, Ali Çehreli wrote:
>> Of course, the solution is to define members with '= void'
>
> Since when? https://issues.dlang.org/show_bug.cgi?id=11331 and your
> https://issues.dlang.org/show_bug.cgi?id=16956 are still open.

Wow! I didn't remember that one. According to its date, it was written 
when I was working for Weka. Apparently, ldc took care of it for them 
after all.


> For recent LDC versions, the 'solution' is to (statically) initialize
> the array with zeros, as fully zero-initialized structs don't feature
> any explicit .init symbols anymore.

What about floating point and char types? Their .init values are not all 
zeros in D spec. (I don't think this matters in my case but still.)


> So you're saying you have a *stack* that can deal with an 800M struct

Sorry, my test code was too simplistic. The actual code constructs these 
objects in dynamic memory for that exact reason.


> I don't think a struct should ever be that large, as it can probably
> only live on the heap anyway and only passed around by refs. I'd
> probably use a thin struct instead, containing and managing a `double[]`
> member (or `double[elementCount]*`).

Exactly.

These structs are code-generated to reflect ROS interface message types. 
Just like in D, arrays have dynamic/static distinction in ROS so I 
blindly translated the types to D without remembering this .init issue.


The following are the options I am considering:

a) Move to ldc

b) As you and IGotD- suggest, define all members with '= void' and 
memset to zero at runtime. (I will decide whether to  take care of char 
and floating point types specially e.g. by setting doubles to NaN; this 
distinction may not be important in our use case.) Luckily, issue 16956 
you mention above does not affect us because these are non-template structs.


c) Again, as you say, define static arrays as dynamic arrays, 
code-generate a default constructor that sets the length to the actual 
static length, which requires some magic as struct default constructor 
cannot be defined for structs.


d) ?

Ali




Re: Generating struct .init at run time?

2020-07-02 Thread Ali Çehreli via Digitalmars-d-learn

On 7/2/20 2:37 AM, IGotD- wrote:

> what on earth are those extra 800MB?

I'm losing my mind. :) Of course it's just 8M. Too many digits for me to 
handle. :p


> Also, this an obvious optimization that can be implemented, that the
> program do an initialization loop instead of putting it in the data
> segment when the array size is above a certain size and they are
> supposed to have the same value.

+1

Ali



Generating struct .init at run time?

2020-07-02 Thread Ali Çehreli via Digitalmars-d-learn
Normally, struct .init values are known at compile time. Unfortunately, 
they add to binary size:


enum elementCount = 1024 * 1024;

struct S {
  double[elementCount] a;
}

void main() {
S s;
assert(typeid(S).initializer.length == double.sizeof * elementCount);
assert(typeid(S).initializer.ptr !is null);
}

Both asserts pass: S.init is 800M and is embedded into the compiled program.

Of course, the solution is to define members with '= void':

enum elementCount = 1024 * 1024;

struct S {
  double[elementCount] a = void;  // <-- HERE
}

void main() {
S s;
assert(typeid(S).initializer.length == double.sizeof * elementCount);
assert(typeid(S).initializer.ptr is null);
}

Now the program binary is 800M shorter. (Note .ptr is now null.) Also 
note that I did NOT use the following syntax because there is a dmd bug:


  auto s = S(); // Segfaults: 
https://issues.dlang.org/show_bug.cgi?id=21004


My question is: Is there a function that I can call to initialize 's' to 
the same .init value that compiler would have used:


S sInit;

shared static this() {
  defaultInitValue();  // Does this exist?
}

I can then use sInit to copy over the bytes of all S objects in the 
program. (Both the structs and their object instantiations are all 
code-generated; so there is no usability issue. There are thousands of 
structs and the current binary size is 2G! :) )


If not, I am planning on writing the equivalent of defaultInitValue() 
that will zero-init the entire struct and then overwrite float, double, 
char, wchar, and dchar members with their respective .init values, 
recursively. Does that make sense?


Ali


Re: How to implement Canceleable spawn() from parent

2020-07-01 Thread Ali Çehreli via Digitalmars-d-learn

On 7/1/20 2:41 AM, aberba wrote:

On Tuesday, 30 June 2020 at 14:43:40 UTC, Steven Schveighoffer wrote:

On 6/30/20 10:15 AM, Simen Kjærås wrote:

[...]


My thinking is I don't want regular consumers using the package to think 
about the technicality of thread_joinAll() at all.


Thinking about putting it in a mixin like:

mixin KeepRunning;

Or something


How about main() starts a thread that starts all the other threads? 
Then, thread_joinAll() would go inside the non-main :) thread.


However, Steve is right: When main() exits, all threads will and should 
exit.


Ali



Re: How to implement Canceleable spawn() from parent

2020-06-29 Thread Ali Çehreli via Digitalmars-d-learn

On 6/29/20 4:34 PM, aberba wrote:

> So with this, without the Thread.sleep() to block main from exiting, the
> spawned thread  will terminate immediately.

You can call core.thread.thread_joinAll at the end of main.

Another way would be to wait for a worker's exit by looking for 
LinkTerminated but you need to start the thread with spawnLinked:


  http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.LinkTerminated

Ali



Re: How to implement Canceleable spawn() from parent

2020-06-28 Thread Ali Çehreli via Digitalmars-d-learn

On 6/28/20 4:08 PM, aberba wrote:

So I checked receiveTimeout() when I was looking for what I could use. I 
wish there was an example in the docs.


https://dlang.org/library/std/concurrency/receive_timeout.html


I have an example of it:

  http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.receiveTimeout

Ali


Re: foreach iterator with closure

2020-06-28 Thread Ali Çehreli via Digitalmars-d-learn

On 6/28/20 9:07 AM, Denis wrote:

> * foreach is the actual iterator,

Yes. foreach is "lowered" to the following equivalent:

  for ( ; !range.empty; range.popFront()) {
// Use range.front here
  }

A struct can support foreach iteration through its opCall() member 
function as well. opCall() takes the body of the foreach as a delegate. 
Because it's a function call, it can take full advantage of the function 
call stack. This may help with e.g. writing recursive iteration algorithms.



http://ddili.org/ders/d.en/foreach_opapply.html#ix_foreach_opapply.opApply

> the instantiation of a struct is the
> range.

Yes.

> * When a constructor is not used, the arguments in the call to
> instantiate the range (in this case, `hello` in letters(`hello`)) are
> mapped sequentially to the member variables in the struct definition
> (i.e. to letters.str).

Yes, that is a very practical struct feature. I write my structs with as 
little as needed and provide a constructor only when it is necessary as 
in your case.


> * When a constructor is used, the member variables in the struct
> definition are in essence private.

Not entirely true. You can still make them public if you want.

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

> The arguments in the call to
> instantiate the range are now mapped directly to the parameters in the
> definition of the "this" function.

Yes.

> * The syntax and conventions for constructors is difficult and
> non-intuitive for anyone who hasn't learned Java (or a derivative).

C++ uses the name of the class as the constructor:

// C++ code
struct S {
  S(); // <-- Constructor
  S(int);  // <-- Another one
};

The problem with that syntax is having to rename more than one thing 
when the name of struct changes e.g. to Q:


struct Q {
  Q();
  Q(int);
};

And usually in the implementation:

Q::Q() {}
Q::Q(int) {}

D's choice of 'this' is productive.

> The
> linked document provides a simplified explanation for the "this"
> keyword, which is helpful for the first read:
> https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html.

I like searching for keywords in my index. The "this, constructor" here 
links to the constructor syntax:


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

> * In some respects, the Java syntax is not very D-like. (For example, it
> breaks the well-established convention of "Do not use the same name to
> mean two different things".)

Yes but it competes with another goal: Change as little code as possible 
when one thing needs to be changed. This is not only practical but helps 
with correctness.


> However, it does need to be learned,
> because it is common in D source code.

I like D. :p

> Here is the complete revised code for the example (in condensed form):
>
>import std.stdio;
>
>struct letters {
>
>  string str;
>  int pos = 1;// Assign here or in this())
>
>  this(string param1) {// cf. shadow str
>str = param1;// cf. this.str = param1 / this.str = str
>writeln(`BEGIN`); }
>
>  char front() { return str[pos]; }
>  void popFront() { pos ++; }
>  bool empty() { return pos == str.length; }
>
>  ~this() { writeln("\nEND"); }}
>
>void main() {
>  foreach (letter; letters(`hello`)) {
>write(letter, ' '); }}
>
> At this point, I do have one followup question:
>
> Why is the shadow str + "this.str = str" the more widely used syntax in
> D, when the syntax in the code above is unambiguous?

Because one needs to come up with names like "param7", "str_", "_str", 
"s", etc. I like and follow D's standard here.


> One possible reason that occurred to me is that "str = param1" might
> require additional GC, because they are different names.

Not at all because there is not memory allocation at all. strings are 
implemented as the equivalent of the following struct:


struct __D_native_string {
  size_t length_;
  char * ptr;
  // ...
}

So, the "str = param1" assignment is nothing but two 64 bit data 
transfer, which can easily by optimized away by the compiler in many cases.


> But I wouldn't
> think it'd make any difference to the compiler.

Yes. :)

>
> Denis

Ali



Re: foreach iterator with closure

2020-06-27 Thread Ali Çehreli via Digitalmars-d-learn

On 6/27/20 8:19 PM, Denis wrote:

> Is it possible to write an iterator

It is arguable whether D's ranges are iterators but if nouns are useful, 
we call them ranges. :) (Iterators can be written in D as well and then 
it would really be confusing.)


>struct letters {
>  string str;
>  int pos = 0;
>  char front() { return str[pos]; }
>  void popFront() { pos ++; }
>  bool empty() {
>if (pos == 0) writeln(`BEGIN`);
>else if (pos == str.length) writeln("\nEND");
>return pos == str.length; }}
>
>void main() {
>  foreach (letter; letters(`hello`)) {
>write(letter, ' '); }
>  writeln(); }
>
> The obvious problems with this code include:
>
> (1) The user can pass a second argument, which will set the initial
> value of pos.

That problem can be solved by a constructor that takes a single string. 
Your BEGIN code would normally go there as well. And END goes into the 
destructor:


struct letters {
this(string str) {
this.str = str;
this.pos = 0;  // Redundant
writeln(`BEGIN`);
}

~this() {
writeln("\nEND");
}

// [...]
}

Note: You may want to either disallow copying of your type or write copy 
constructor that does the right thing:


  https://dlang.org/spec/struct.html#struct-copy-constructor

However, it's common to construct a range object by a function. The 
actual range type can be kept as an implementation detail:


struct Letters {  // Note capital L
  // ...
}

auto letters(string str) {
  // ...
  return Letters(str);
}

struct Letter can be a private type of its module or even a nested 
struct inside letters(), in which case it's called a "Voldemort type".


Ali



Re: Passing iterators into functions

2020-06-25 Thread Ali Çehreli via Digitalmars-d-learn
Collection elements are accessed by ranges in D. Although both iterators 
and ranges fundamentally do the same thing (access elements). More 
accurately, ranges correspond to a pair iterators.


On 6/24/20 8:35 PM, repr-man wrote:

> auto func(R)(R r, size_t width)
> if(isRandomAccessRange!R)
> {
>  return r.chunks(width);
> }
>
> void main()
> {
>  int[5] a = [0, 1, 2, 3, 4];
>  int[5] b = [5, 6, 7, 8, 9];
>  auto x = func!(int[])(chain(a[], b[]), 5);

Is there a reason why you specify the template argument there?

> This seems to have to do with the fact that all iterators return their
> own unique type.

When the element is normally different, there would be no way of using 
one type anyway. This is similar to how vector::iterator is a 
different type from e.g. vector::iterator.


> Could someone help me understand the reason behind
> this design

Andrei Alexandrescu has the following article on D's ranges:

  https://www.informit.com/articles/printerfriendly/1407357

> and how to remedy my situation?

Just don't specify the function template argument and it will work.

Ali



Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine();

2020-06-22 Thread Ali Çehreli via Digitalmars-d-learn

On 6/22/20 2:37 PM, mw wrote:

> On Monday, 22 June 2020 at 20:58:58 UTC, Ali Çehreli wrote:
>
>> Others have other explanations for this but my understanding is about
>> exception safety: If it changed internal state and returned the front
>> object, you would no be able to make a function like popFront()
>> strongly exception safe. (There are ample documentation for this topic
>> in C++ circles.)
>
> That's one consideration. But, it will be more interesting in knowing
> (based on actual usage):
>
> (a) how many bugs % are due to exception un-safe

I am not claiming that strong exception safety is the reason for Phobos 
design. However, knowing what I know, I would use the same primitive 
operations. It's the same with e.g. C++ as well: != end(), operator*, 
operator++. And operator++ does not return the current object either.


Even if zero bugs are due to exception un-safe, a library designer would 
not oversee that knowledge. It is impossible to make an interface 
strongly exception safe but the reverse is always possible.


> (b) how many bugs % are due to front / popFront separation?

I made the mistake of forgetting to call popFront() perhaps 10 times and 
got stuck in an infinite loop and quickly hit a segmentation fault and 
that was it.


> And which is more bug-prone for a typical programmer? my gut feeling is
> (b), at least we just saw one in this thread.
>
>
> And
>
> -- loop thru a static structure content like a simple array, why we need
> to worry about exception safe?

*If* strong exception guarantee is needed, it doesn't matter whether 
it's a simple array or not.


> -- loop thru dynamically generated content, esp. network or more
> external complex structure may worth considering exception safety. But
> even there, do people always need to call !range.empty() check first?
> when it's not empty, how much more exception un-safety that
> popAndReturnFront() can introduce than the combination of `front(); ...;
> popFront();"?

It has been demonstrated on a Stack type that conflating top() and pop() 
cannot be made strongly exception safe. It's the same with front() and 
popFront().


> And why not provide a popAndReturnFront(), and let the user decide based
> on his/her own actual usage?

Because if the primitives were empty() and popAndReturnFront(), then it 
wouldn't be made strongly exception safe. With the current primitives of 
empty(), front(), and popFront(), it's possible to implement 
popAndReturnFront(). I like the following one that I wrote in three 
minutes. :)


import std.stdio;

auto popAndReturnFront(R)(ref R range) {
  import std.range : empty, front, popFront, ElementType;
  import std.typecons : Nullable, nullable;

  if (range.empty) {
return Nullable!(ElementType!R)();
  }

  scope (success) range.popFront();
  return nullable(range.front);
}

void main() {
  auto range = [ 1, 2, 3 ];
  while (true) {
auto front = range.popAndReturnFront;
if (!front.get()) {
  break;
}
writeln(front);
  }
}

>> Another reason is cohesion: We want functions to have as little
>> responsibility as possible (ideally single).
>
> Again we have to weight which way is more bug-prone, any actual
> statistics on the above (a) v.s (b)?

I am not aware of any bugs related to the separation of front() and 
popFront().


Ali




Re: how to skip the next (n) item & continue from (n+1) with a range ? e.g. in File(fn).byLine();

2020-06-22 Thread Ali Çehreli via Digitalmars-d-learn

On 6/22/20 1:46 PM, mw wrote:

> so `front` is peek, and `popFront` is the pop action whose return type
> is `void`, why we need two *separate* calls instead of just let
> `popFront` return T

Others have other explanations for this but my understanding is about 
exception safety: If it changed internal state and returned the front 
object, you would no be able to make a function like popFront() strongly 
exception safe. (There are ample documentation for this topic in C++ 
circles.)


Another reason is cohesion: We want functions to have as little 
responsibility as possible (ideally single).


> (or do we have another function for this)?

There are many useful functions in std.range:

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

The "take" and "drop" functions may be useful.

Ali



Re: GtkD code review - How to update a progressbar using data sharing concurrency

2020-06-22 Thread Ali Çehreli via Digitalmars-d-learn

On 6/21/20 5:52 AM, adnan338 wrote:


I am trying to figure out how to prevent this data race.


I still like the std.concurrency method I used here:

  https://forum.dlang.org/post/rkitcprqvslexgqaf...@forum.dlang.org

The only difference is that your individual progresses are from 0% to 
100%. The example can be changed easily to report 100% once at the end 
of each download.


Ali


Re: Some questions about strings

2020-06-21 Thread Ali Çehreli via Digitalmars-d-learn
On 6/21/20 8:17 PM, Denis wrote:> I have a few questions about how 
strings are stored.

>
> - First, is there any difference between string, wstring and dstring?

string is char[]
wstring is wchar[]
dstring is dchar[]

char is 1 byte: UTF-8 code unit
wchar is 2 bytes: UTF-16 code unit
dchar is 4 bytes: UTF-32 code unit

> For example, a 3-byte Unicode character literal can be assigned to a
> variable of any of these types, then printed, etc, without errors.

You can reveal some of the mystery by looking at their .length property. 
Additionally, foreach will visit these types element-by-element: char, 
wchar, and dchar, respectively.


> - Are the characters of a string stored in memory by their Unicode
> codepoint(s), as opposed to some other encoding?

As UTF encodings; nothing else.

> - Assuming that the answer to the first question is "no difference", do
> strings always allocate 4 bytes per codepoint?

No. They always allocate sufficient bytes to represent the code points 
in their respective UTF encodings. dstring is the only one where the 
number of code points equals the number of elements: UTF-32 code units, 
each being 4 bytes.


> - Can a series of codepoints, appropriately padded to the required
> width, and terminated by a null character,

null character is not required but may be a part of the strings.

> be directly assigned to a
> string WITHOUT GOING THROUGH A DECODING / ENCODING TRANSLATION?

It will go through decoding/encoding.

> The last question gets to the heart of what I'd ultimately like to
> accomplish and avoid.
>
> Thanks for your help.

There is also the infamous "auto decoding" of Phobos algorithms (which 
is as a mistake). I think one tool to get away from auto decoding of 
strings is std.string.representation:


  https://dlang.org/phobos/std_string.html#.representation

Because it returns a type that is not a string, there is not auto 
decoding to speak of. :)


Ali



Re: GtkD code review - How to update a progressbar using data sharing concurrency

2020-06-21 Thread Ali Çehreli via Digitalmars-d-learn

On 6/20/20 9:30 AM, adnan338 wrote:

> Hello, I need a code review on my strategy

I don't know gtkd so I did not compile the code and I did not review the 
code very carefully.


However, I don't think you need to 'synchronized' the whole parallel 
loop. Since there is only one thread that executes start(), that 
synchronized cannot have any effect at all. What you want to synchronize 
is the mutating access to 'completed' by the threads that parallel() 
starts automatically. So, move 'synchronized' just around that expression:


// REMOVE this one:
// synchronized
// {

  foreach (_; downloader.links.parallel())
  {
  Thread.sleep(uniform(0, 6, rnd).seconds());

  // ADD this one:
  synchronized {
++cast() downloader.completed;
  }
  }

// }

Ali



Re: "if not" condition check (for data validation)

2020-06-18 Thread Ali Çehreli via Digitalmars-d-learn

On 6/18/20 5:13 AM, Denis wrote:

> Templates offer a clean syntax

Here is an earlier experiment of nested templates, which may be useful 
in this case. This is unrelated to your problem but the syntax can be 
pretty readable with templates:


// If there are template arguments, then the result is the first of
// them. If there is no argument, then the result is the argument
// of 'otherwise'.
template FirstOf(T...) {
  template otherwise(alias D) {
static if (T.length != 0) {
  enum otherwise = T[0];

} else {
  enum otherwise = D;
}
  }
}

unittest {
  static assert (FirstOf!(1.5, "hello").otherwise!100 == 1.5);
  static assert (FirstOf!().otherwise!42 == 42);
}

auto foo(Args...)() {
  auto temp = FirstOf!Args.otherwise!1.5;
  // ...
  return temp + 0.5;
}

unittest {
  assert(foo!(10, int[])() == 10.5);
  assert(foo() == 2.0);
}

void main() {
}

I think you should be able to pass callables as 'alias' template 
arguments but I couldn't put much thought into it.


Ali



Re: "if not" condition check (for data validation)

2020-06-17 Thread Ali Çehreli via Digitalmars-d-learn
On 6/17/20 4:46 PM, Denis wrote:> Is there a cleaner way to implement an 
"if not" condition check?


>if ( configfile.isFile && configfile.extension == ".conf", message 
) { }

>else 

  if (isConfigFile(name)) {
// ...

  } else {
// ...
  }

The following is suitable in many cases:

  enforce(isConfigFile(name), format!"%s is not a config file"(name));
  // ...

I shortened that in many occasions:

  enforceConfigFile(name);
  // ...

Of course, depending on the situation it is assert() or assertConfigFile().

Ali



Re: How to create Multi Producer-Single Consumer concurrency

2020-06-16 Thread Ali Çehreli via Digitalmars-d-learn

On 6/12/20 3:02 PM, adnan338 wrote:

> So there are multiple "download finished" message producers, and one
> consumer of those messages. Furthermore, that producer has a callback
> that triggers an UI object.

That's almost exactly what I do in some of my programs. I use 
std.concurrency and the following is a working sketch of what I do.


I assumed you get finer individual granularity of progress as opposed to 
the binary 0% -> 100%.


import std.stdio;
import std.concurrency;
import std.algorithm;
import std.range;
import std.exception;
import std.format;
import core.thread;

struct Progress {
  Tid tid;  // The id of the reporting thread
  size_t amount;// The amount of progress so far
  size_t total; // Total progress (can be file size)
}

void display(Progress[Tid] progresses) {
  const amount = progresses.byValue.map!(p => p.amount).sum;
  const total = progresses.byValue.map!(p => p.total).sum;
  writefln!"%6.2f%%"(100.0 * amount / total);
}

// The worker thread function
void download(string url) {
  writefln!"Worker %s downloading %s."(thisTid, url);
  enum total = 20;
  foreach (i; 0 .. total) {
// Imitate some progress
Thread.sleep(100.msecs);

// Report progress to owner
ownerTid.send(Progress(thisTid, i + 1, total));
  }
}

void main() {
  auto list = [ "dlang.org", "ddili.org" ];
  auto downloaders = list.length
 .iota
 .map!(i => spawnLinked(, list[i]))
 .array;

  Progress[Tid] progresses;
  size_t finished = 0;

  while (finished != list.length) {
receive(
  (LinkTerminated arg) {
++finished;

// Check whether this thread is exiting prematurely
enforce((arg.tid in progresses) &&
(progresses[arg.tid].amount ==  progresses[arg.tid].total),
format!"Thread %s exited unexpectedly"(arg.tid));
  },

  (Progress progress) {
progresses[progress.tid] = progress;
progresses.display();
  }
);
  }

  writeln("Processing the downloaded files.");
}

Ali



Re: Initializing an associative array of struct

2020-06-14 Thread Ali Çehreli via Digitalmars-d-learn

On 6/14/20 7:43 AM, Denis wrote:> @Kagamin:
>
> On Sunday, 14 June 2020 at 07:16:18 UTC, Kagamin wrote:
>> parameters[param]=Parameter();
>
> I did not realize that you can use a type on the RHS of an assignment,

Note that it's not just the type but with parenthesis after it. For 
example, Foo() default-constructs an object of Foo.


> There does not appear to be a way to loop over the elements of an enum,

There is std.traits.EnumMembers:

import std.traits;

enum Foo { abc, xyz }

void main() {
  foreach (foo; EnumMembers!Foo) {
// ...
  }
}

Ali



Re: final switch problem

2020-06-13 Thread Ali Çehreli via Digitalmars-d-learn

On 6/13/20 9:22 AM, John Chapman wrote:

Hmm, compiling with -release makes it work. Not a huge issue, I'll just 
avoid final switches in debug mode until it's fixed. Thanks.


Apparently, it's a known issue:

  https://issues.dlang.org/show_bug.cgi?id=19548

Ali


Re: Metaprogramming with D

2020-06-09 Thread Ali Çehreli via Digitalmars-d-learn

On 6/8/20 7:50 AM, ag0aep6g wrote:


https://ddili.org/ders/d.en/literals.html#ix_literals.q%7B%7D


Thank you.

I am biased but I like my :) index of the book, where all such syntax 
items appear:


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

Ali


Re: Metaprogramming with D

2020-06-06 Thread Ali Çehreli via Digitalmars-d-learn
On 6/6/20 5:03 PM, FunkyD wrote:> On Saturday, 6 June 2020 at 09:57:36 
UTC, Jan Hönig wrote:


> D is pretty good for meta-programming. For certain other things it is
> terrible.

I am glad I don't know enough about other technologies to feel that way.

> String mixins simply mix in D code. It lets you build generic D code.
> The big problem here is debugging. There is ZERO ability to properly
> debug string mixins.

"Zero" is too strong an assertion and because of the following, false:

  dmd -mixin= ...

> Well, what it boils down to is writing out the
> string mixin and then debugging that.

When I compile my program and there is an issue with a string mixin, 
Emacs opens the mixin file and shows me the compilation there. This is 
because dmd's error include the exact line in the  where my 
mixin was broken. Not a shiny IDE but still pretty awesome support.


> It would be nice if D had a special D code string that the IDE could
> interpret properly.

I must be misunderstanding you but it must be an IDE limitation because 
of the following:


  writeln(q{
  void foo() {
  }
});

My IDE gives me syntax highlighting in that string, so it works somehow.

> D basically tries to resolve things after the fact so
>
> R add(T)(T a, T b)
> {
>  return a + b;
> }
>
> this will attempt to + on a and b after the types are known. If they
> can't be added then an error will occur, which is usually cryptic for
> templates.

That's why we use template constraints and in some cases 'static assert' 
for custom error messages.


> The issue in using D should not be made based on it's metaprogramming.

I agree. What feature to use usually emerges by itself. For example, 
when an algorithm is repeated for many types, it is an opportunity for 
templates.


> D, IMO, is not capable of writing sophisticated programs...

"Sophisticated" is relative but such strong assertions can be falsified 
by a single counterexample. For example, Weka's product is very 
sophisticated and is written in D. And there is nothing extra or missing 
in D that makes it incapable in that regard.


> this is why
> you do not see any.

I think the fact that many smart programmers are hostage to other 
languages is a stronger reason.


> No one writes large commercial apps in D.

False.

> There is
> not one!

False. And again, even if so, that's not because of D, but because of 
humans. Can you imagine a CTO, say, in Silicon Valley to have guts to 
bring D instead of C++? With C++, the CTO will never be blamed; but D, 
he or she can easily be blamed upon failure. Not because of the 
technologies but because of politics.


> The D ecosystems is poorly structured compared to the top
> contenders.

Agreed but that is not because D is inferior. Again, that's because 
people happen to be busy with other technologies.


> D is good for small apps, utilities, etc. D can be
> integrated with other apps though but then one loses some of the meta
> capabilities(since they won't translate).

What would one technology that is good for small code not work for a 
larger system? Threads, communication e.g. memory mapped files, etc. are 
all there. What magical thing would happen and suddenly D won't work 
beyond a certain limit? If so, is that any different from any other 
language?


Ali




Re: writeln Function while reading a Text File is printing appending text "before text" and "after text" at the same position

2020-06-05 Thread Ali Çehreli via Digitalmars-d-learn

On 6/3/20 1:43 PM, BoQsc wrote:


Chomp sounds kind of funny hahaha.


Also consider strip, stripLeft, and stripRight. (Not because they may be 
funny but because they are useful as well. :) )


Ali


Re: Making alias of a struct field needs "this".

2020-06-02 Thread Ali Çehreli via Digitalmars-d-learn

On 6/2/20 1:56 AM, realhet wrote:

> struct A{
>struct B{ int c; }
>B b;
>
>auto f(){
>  alias d = b.c;

The spec explicitly says it's not legal: "Aliases cannot be used for 
expressions" (Item 10):


  https://dlang.org/spec/declaration.html#alias

I use nested functions for such cases:

  auto f(){
auto d() {
  return b.c;
}
return d;
  }

Ali



Re: How to efficiently resolve Associative Arrays not being sorted?

2020-06-02 Thread Ali Çehreli via Digitalmars-d-learn

On 6/2/20 12:32 AM, BoQsc wrote:

> I want to read a file, put it into an array, make some search and
> replace on the content and output the modified text.

How large is the data? If it fits into memory, just read the whole 
thing, update it, sort the keys, and then output like this:


  import std.stdio;
  import std.algorithm;

  foreach (key; aa.keys.sort) {
writeln(key, aa[key]);
  }

Of course, you can save the sorted array in a local variable as well if 
you will use it again:


  auto keys = aa.keys.sort;

One great thing about programs that read and write files is that unless 
the data is so large that it does not fit into physical memory, you 
can't feel the time cost of that sort operation. :)


Ali



Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?

2020-05-31 Thread Ali Çehreli via Digitalmars-d-learn
On 5/31/20 1:00 PM, mw wrote:> On Sunday, 31 May 2020 at 09:37:24 UTC, 
Ali Çehreli wrote:


> One question: in Sebastiaan's solution opDispatch is performed at
> run-time

Templates don't exist at run time. They are used for generating code at 
compile time and that's it.


opDispatch is a template. Like all templates, it's evaluated at compile 
time and code is generated for it at compile time. However, if 
opDispatch() is a member function template, then there will be a 
function call execution at runtime but this is not different from any 
other member function call.


Here is a struct with an opDispatch() used as a member function template.

struct XmlElement {
  static opDispatch(string tag)(string value) {
import std.range;
import std.format;

enum opening = format!"<%s>"(tag);
enum closing = format!""(tag);

// Note: Although we return a chained range, this could return a
// string[3] as well, which may possibly be more performant.
return chain(opening, value, closing);
  }
}

import std.stdio;

void main() {
  writeln(XmlElement.foo("hello"));
  writeln(XmlElement.bar("world"));
}

opDispatch() is instantiated with two strings in the program: "foo" and 
"bar". As a result, the XmlElement struct will be the equivalent of the 
following one:


struct XmlElement {
  static foo(string value) {
enum opening = "";
enum closing = "";
return chain(opening, value, closing);
  }

  static bar(string value) {
enum opening = "";
enum closing = "";
return chain(opening, value, closing);
  }
}

Note how two member functions are added to XmlElement and all of the 
'opening' and 'closing' strings are computed at compile time.


In my solution opDispatch() boils down to a "mixin template" itself. As 
Paul Backus's code does, that mixin template is used for adding the 
following members to the struct for each instantiation of opDispatch(). 
For example, for x, the struct will gain the following template 
definition. (_FOR_X is my annotation).


mixin template opDispatch_FOR_X(alias code = codeImpl()) {
private int _x;
public auto x() { return _x; }
public auto x(T val) { _x = val; return this; }
}

Note that each instance of opDispatch() for "x", "y", etc. will gain a 
template definition. Those definitions are a compile-time cost. 
Eventually, when user code mixes-in the corresponding template, then the 
three member above will be added to the user's struct.


After that, there is no run-time cost more than adding those members by 
hand.


Ali




Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?

2020-05-31 Thread Ali Çehreli via Digitalmars-d-learn

On 5/31/20 2:26 AM, Ali Çehreli wrote:

Unfortunately, I could not reach the following cleaner syntax with a 
mixin template:


   mixin RW!int.x;


Ok, I solved that too with a very convoluted "eponymous mixin template 
opDispatch." :)


struct RW(T) {
  template opDispatch(string name) {
static codeImpl() {
  import std.format;

  return format!q{
private %s _%s;
public auto %s() { return _%s; }
public auto %s(%s val) { _%s = val; return this; }
  }(T.stringof, name,
name, name,
name, T.stringof, name);
}

mixin template opDispatch(alias code = codeImpl()) {
  mixin (code);
}
  }
}

struct Point {
  mixin RW!int.x;// <-- NICE :)
  mixin RW!int.y;
// etc.
}

import std.traits;
import std.stdio;

void main() {
  pragma(msg, FieldNameTuple!(Point));

  auto p = Point(1, 2);
  p.x = 42;
  p.y = 43;
  writeln(p);
}

Ali



Re: how to achieve C's Token Pasting (##) Operator to generate variable name in D?

2020-05-31 Thread Ali Çehreli via Digitalmars-d-learn

On 5/30/20 11:28 PM, mw wrote:

On Sunday, 31 May 2020 at 00:46:09 UTC, Paul Backus wrote:

You can simplify this considerably using a mixin template [1]:

---
mixin template RW(T, string name) {
    private T var;
    public T get() { return var; }
    public typeof(this) set(T val) { var = val; return this; }

    mixin("private alias _", name, " = var;");
    // two aliases with the same name create an overload set
    mixin("public alias ", name, " = get;");
    mixin("public alias ", name, " = set;");
}

class Point {
    mixin RW!(int, "x");
    mixin RW!(int, "y");


   mixin RW!(string, "z");  // add


}
---


This is better, ... but it breaks std.traits:


The following code solves that I think the following syntax is an 
improvement over Paul Backus's solution because it allows .x instead of 
"x" by taking advantage of a static opDispatch. But it requires 
parenthesis because now it's a string mixin, which is likely to be 
noticeably slow to compile too.


struct RW(T) {
  static string opDispatch(string name)() {
import std.format;

return format!q{
  private %s _%s;
  public auto %s() { return _%s; }
  public auto %s(%s val) { _%s = val; return this; }
}(T.stringof, name,
  name, name,
  name, T.stringof, name);
  }
}

struct Point {
  mixin (RW!int.x);
  mixin (RW!int.y);
// etc.
}

import std.traits;
import std.stdio;

void main() {
  pragma(msg, FieldNameTuple!(Point));

  auto p = Point(1, 2);
  p.x = 42;
  p.y = 43;
  writeln(p);
}

The spec allows opDispatch to be an eponymous template:

  https://dlang.org/spec/operatoroverloading.html#dispatch

Unfortunately, I could not reach the following cleaner syntax with a 
mixin template:


  mixin RW!int.x;

Ali



Re: Overload function template for rectangular array

2020-05-25 Thread Ali Çehreli via Digitalmars-d-learn

On 5/25/20 1:20 AM, John Chapman wrote:

void foo(T)(T[] a) {}
void foo(T)(T[][] a) {}

auto ra = new int[][](5, 5);
ra.foo(); // matches both


import std.traits;

void foo(T)(T[] a)
if (!isArray!T) {}

void foo(T)(T[] a)
if (isArray!T) {}

Or you can take T as parameter and check ElementType!T:

import std.traits;
import std.range;

void foo(T)(T a)
if (!isArray!(ElementType!T)) {}

void foo(T)(T a)
if (isArray!(ElementType!T)) {}

void main() {
  auto ra = new int[][](5, 5);
  ra.foo();
}

Ali


Re: alias this and initialisation

2020-05-25 Thread Ali Çehreli via Digitalmars-d-learn

On 5/24/20 6:35 PM, Danni Coy wrote:> can anybody tell me why
>
> struct S
> {
>  int x;
>  alias x this;
> }
>
> void test()
> {
>  S s;
>  s = 8; // this works
>  S s = 8 // but this does not?
> }

alias this is for implicit conversion, which requires an object to 
convert from. The second case above is about constructing an object.


That's probably why it works that way.

Ali



Re: How to flatten N-dimensional array?

2020-05-24 Thread Ali Çehreli via Digitalmars-d-learn

On 5/24/20 2:37 AM, Pavel Shkadzko wrote:

On Saturday, 23 May 2020 at 19:59:30 UTC, Ali Çehreli wrote:
On 5/23/20 11:15 AM, Pavel Shkadzko wrote:> I have tried to implement 
a simple flatten function for multidimensional


[...]


Thank you, I was lacking practical examples for templates with "if" 
constructs, ehh.


Template constraints are great but 'static if' can be more useful as it 
allows custom error messages:


auto makeNdim(size_t N)(size_t length) {
  static if (N == 1) {
auto result = iota(value, value + length).array;
value += length;
return result;

  } else static if (N > 1) {
return iota(N).map!(n => makeNdim!(N - 1)(length)).array;

  } else {
static assert(false, "N cannot be 0.");
  }
}

Ali



Re: Asserting that a base constructor is always called

2020-05-23 Thread Ali Çehreli via Digitalmars-d-learn

On 5/23/20 3:04 PM, Tim wrote:

I have a base class GameObject:

/// Base class of most objects in the game
class GameObject{
     this(){
     world[layer] = this;
     }

     abstract void update(){}

     void draw(){}
}

I want to make sure that whenever a class inherits from this, the base 
constructor is always called. Either that or have an assertion that 
gives an error if it isn't called.


Thanks


Is it not already called? I tried the following and it seems to work:

import std.stdio;

GameObject[1] world;
enum layer = 0;

/// Base class of most objects in the game
class GameObject{
  this(){
world[layer] = this;
writeln("called");
  }

  abstract void update(){}

  void draw(){}
}

class A : GameObject {
  this(int i) {
writeln(__FUNCTION__);
  }

  override void update() {
  }
}

void main() {
  auto a = new A(42);
}

Ali



Re: How to flatten N-dimensional array?

2020-05-23 Thread Ali Çehreli via Digitalmars-d-learn
On 5/23/20 11:15 AM, Pavel Shkadzko wrote:> I have tried to implement a 
simple flatten function for multidimensional


> I'd like to clarify a couple of questions first.
>
> How come Phobos doesn't have "flatten" function for arrays?

We call in 'joiner'.

I wrote something like this:

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

int value = 0;

auto makeNdim(size_t N)(size_t length)
if (N == 1) {
  auto result = iota(value, value + length).array;
  value += length;
  return result;
}

auto makeNdim(size_t N)(size_t length)
if (N > 1) {
  return iota(N).map!(n => makeNdim!(N - 1)(length)).array;
}

auto flatten(R)(R range)
if (!isInputRange!(ElementType!R)) {
  return range.joiner;
}

auto flatten(R)(R range)
if (isInputRange!(ElementType!R)) {
  return range.map!(r => r.joiner).joiner;
}

void main() {
  auto a = makeNdim!3(5);
  writefln!"Original : %s"(a);
  writefln!"Flattened: %s"(a.flatten);
}

Output:

Original : [[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]], [[10, 11, 12, 13, 14], 
[15, 16, 17, 18, 19]], [[20, 21, 22, 23, 24], [25, 26, 27, 28, 29]]]
Flattened: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]


Ali



Re: None of the overloads of kill are callable using argument types:

2020-05-18 Thread Ali Çehreli via Digitalmars-d-learn
On 5/18/20 1:11 PM, BoQsc wrote:> I'm trying to kill my own process, but 
I'm being unsuccessful at the

> compilation of the program. It seems that neither getpid nor
> thisProcessID returns a correct type value for the kill function.

Of course, Adam D. Ruppe is right: You can simply return from main() in 
this case. Or, Pid is given to you for processes that you've spawned.


Your question brings one of my recent pet peeves in software: the 
'private' keyword.[1] In this case, it's Pid's constructor. I wanted to 
do the following but it failed because the constructor is private:


  auto p = new Pid(thisProcessID());

Ali

[1] I don't think 'private' keyword ever protected me. I'm pretty sure 
of it because if I've ever reached for undocumented features of a type 
or if I've ever used any member, say, having a name starting with '_', I 
would be sure to be punished in the future if the implementation 
changed. I know that and I'm sure it's very easy to teach it to 
beginners. It's too much protecting me from myself.


On the other hand, there have been multiple cases where 'private' 
keyword was hiding a useful feature: D runtime's GC statistics (at least 
in the past), some of std.getopt's parsing functions, etc. Note to self: 
Think twice before making anything 'private'.




Re: Type sniffing at runtime

2020-05-16 Thread Ali Çehreli via Digitalmars-d-learn

On 5/15/20 11:12 PM, Alex wrote:


     static if(__traits(compiles, T.min))
     writeln("Minimum value  : ", T.min);


A little improvement:

static if(__traits(isFloating, T)) {
  writeln("Minimum value  : ", -T.max);

} else {
  writeln("Minimum value  : ", T.min);
}

Ali



Re: Best way to refer to the type of a struct inside itself ?

2020-05-15 Thread Ali Çehreli via Digitalmars-d-learn

On 5/15/20 8:04 AM, Paul Backus wrote:

On Friday, 15 May 2020 at 14:55:07 UTC, Ali Çehreli wrote:
Additionally, the name of a template when used inside that template 
means that instance of it. So just say Foo. :)


struct Foo(A, B, C, size_t a, size_t b)
{
  Foo * p;
}

Ali


To expand a little, this works because a struct template such as the one 
above is actually syntax sugar for the following:


template Foo(A, B, C, size_t a, size_t b)
{
     struct Foo
     {
     // refers to the inner `struct Foo`, not the outer `template Foo`
     Foo* p;
     }
}

The relevant parts of the language spec are:

- Aggregate Templates: 
https://dlang.org/spec/template.html#aggregate_templates
- Eponymous Templates: 
https://dlang.org/spec/template.html#implicit_template_properties

Yes, that is a consistent way of explaining it. :)

As an off-topic trivia, the same feature is in C++ as well:

#include 

template 
struct Foo
{
  Foo * p;  // <-- Foo means the template instance
};

int main() {
  Foo f;
  f.p = 
}

Ali



Re: Best way to refer to the type of a struct inside itself ?

2020-05-15 Thread Ali Çehreli via Digitalmars-d-learn

On 5/15/20 7:37 AM, wjoe wrote:

On Friday, 15 May 2020 at 13:52:38 UTC, Paul Backus wrote:

On Friday, 15 May 2020 at 13:47:43 UTC, wjoe wrote:

struct Foo(A, B, C, size_t a, size_t b)
{
  alias foo_t = Foo!(A, B, C, a, b); // is there a better way to get 
foo_t ?

}


typeof(this)


Thanks :)


Additionally, the name of a template when used inside that template 
means that instance of it. So just say Foo. :)


struct Foo(A, B, C, size_t a, size_t b)
{
  Foo * p;
}

Ali



Re: Surprising interaction of tuples and slicing

2020-05-07 Thread Ali Çehreli via Digitalmars-d-learn
On 5/7/20 8:33 AM, Ben Jones wrote:> I was doing some metaprogramming 
where I wanted to make a slice of a type:


[...]

> alias Ts = AliasSeq!int;
> pragma(msg, Ts);
> alias Tsa = Ts[];
> pragma(msg, Tsa);
> //prints (int), (int)
>
> which confused me until I realized that the [] was slicing the tuple.
> Note, you can add as many [] as you want since it's basically a no-op.

[...]

> Is there any use for this behavior?

Slicing an alias sequence is definitely useful e.g. in recursive templates:

  alias car = T[0];  // (head)
  alias cdr = T[1..$];   // (tail)

> It seems like it might be worth
> warning like "slicing a tuple is a no-op"

The trouble seems to be when slicing the entire tuple. Even in that 
case, printing a warning would not be desired in some situations 
ironically in generic code where e.g. T[0..$] may appear, which is the 
same as T[].


Ali



Re: Error running concurrent process and storing results in array

2020-05-05 Thread Ali Çehreli via Digitalmars-d-learn
On 5/5/20 8:41 PM, data pulverizer wrote:> On Wednesday, 6 May 2020 at 
03:33:12 UTC, Mathias LANG wrote:

>> On Wednesday, 6 May 2020 at 03:25:41 UTC, data pulverizer wrote:

> Is there something I need to do to wait for each thread to finish
> computation?

thread_joinAll(). I have an example here:

  http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.thread_joinAll

Although I understand that you're experimenting with std.concurrency, I 
want to point out that there is also std.parallelism, which may be 
better suited in many cases. Again, here are some examples:


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

Ali



Re: Idomatic way to guarantee to run destructor?

2020-05-04 Thread Ali Çehreli via Digitalmars-d-learn

On 5/4/20 2:47 AM, Olivier Pisano wrote:

On Monday, 4 May 2020 at 09:20:06 UTC, Ali Çehreli wrote:
On 4/30/20 10:04 AM, Ben Jones wrote:> On Thursday, 30 April 2020 at 
16:55:36 UTC, Robert M. Münch wrote:


> I think you want to use scope rather than auto which will put
the class
> on the stack and call its destructor:
> https://dlang.org/spec/attribute.html#scope

That is correct about calling the destructor but the object would 
still be allocated with 'new', hence be on the heap. There is also 
library feature 'scoped', which places the object on the stack:


  https://dlang.org/phobos/std_typecons.html#scoped

Ali


https://godbolt.org/z/SEVsp5

My ASM skills are pretty limited, but it seems to me that the call to 
_d_allocclass is omitted when using scope. At least with LDC and GDC.


Am I missing something ?


I stand corrected.

'scope's running the destructor was news to me, so I tested with a 
writeln example where the messages changed order depending on whether 
'scope' was replaced with 'auto' or not:


import std.stdio;

class C {
  ~this() {
writeln("~this");
  }
}

void foo() {
  scope c = new C();  // <-- here
}

void main() {
  foo();
  writeln("foo returned");
}

Now it's news to me that 'new' does not allocate on the heap when 
'scope' is used. I'm not sure I'm comfortable with it but that's true. 
Is this unique? Otherwise, 'new' always allocates on the heap, no?


I added the following three lines to the end of foo() too see (without 
needing to look at assembly) that the 'scope' and 'auto' class objects 
are allocated on different memory regions (by taking object addresses as 
proof :) ):


  writeln(cast(void*)c);
  auto c2 = new C();
  writeln(cast(void*)c2);

Ali



Re: Idomatic way to guarantee to run destructor?

2020-05-04 Thread Ali Çehreli via Digitalmars-d-learn
On 4/30/20 10:04 AM, Ben Jones wrote:> On Thursday, 30 April 2020 at 
16:55:36 UTC, Robert M. Münch wrote:


> I think you want to use scope rather than auto which will put the class
> on the stack and call its destructor:
> https://dlang.org/spec/attribute.html#scope

That is correct about calling the destructor but the object would still 
be allocated with 'new', hence be on the heap. There is also library 
feature 'scoped', which places the object on the stack:


  https://dlang.org/phobos/std_typecons.html#scoped

Ali




Re: countUntil with negated pre-defined predicate?

2020-05-04 Thread Ali Çehreli via Digitalmars-d-learn
On 5/3/20 2:59 PM, Harry Gillanders wrote:> On Sunday, 3 May 2020 at 
12:19:30 UTC, Robert M. Münch wrote:


> an `auto ref` parameter[1] in a
> function template is essentially a parameter that receives the
> argument by reference if the templated type is a value-type,

Please replace "a value-type" above with "an lvalue".

> whereas if the templated type is a reference-type, it receives the
> argument by value.

And please replace "a reference-type" above with "an rvalue." :)

Ali

> [1]: https://dlang.org/spec/template.html#auto-ref-parameters




Re: How can I check if an element is iterable?

2020-05-03 Thread Ali Çehreli via Digitalmars-d-learn

On 5/3/20 1:44 PM, Marcone wrote:

On Sunday, 3 May 2020 at 20:11:58 UTC, Adam D. Ruppe wrote:

On Sunday, 3 May 2020 at 20:02:09 UTC, Marcone wrote:

How can I check if an element is iterable in Dlang?


http://dpldocs.info/experimental-docs/std.traits.isIterable.html


I don't want to check if type is iterable, but if variable is iterable.


Still, the type of a variable would determine whether whether it's iterable.

As an improvement, the following program can be changed to call use() 
recursively to visit all members of e.g. structs (which can be 
determined by 'is (T == struct)').


import std.stdio;
import std.traits;

void use(T)(T var, size_t indent = 0) {
  static if (isIterable!T && !isSomeString!T) {
foreach (i, e; var) {
  writefln!"%*s: %s"(indent, i, e);
}

  } else {
writefln!"%*s"(indent, var);
  }
}

void main() {
  int i = 42;
  string s = "hello";
  double[] arr = [ 1.5, 2.5, 3.5 ];
  use(i);
  use(s);
  use(arr);
}

Ali


Re: How can I do dmd omite error when if compare two different data types ? (-fpermissive)

2020-05-03 Thread Ali Çehreli via Digitalmars-d-learn

On 5/3/20 4:03 PM, Marcone wrote:

In C++ I just use -fpermissive

foreach(i; tuple(10, "lemon", false, "John", 1.6, 'c'))
{
     writeln(i);
     if(i == "John") break; // Error
}


I am not sure I understand your question because it already omits an 
error. If you're asking how to get that code do what I think you want, 
then the 'is' expression can be used with 'static if' to include the 
comparison into the program only for string types:


import std.typecons;
import std.stdio;

void main() {
  foreach(i; tuple(10, "lemon", false, "John", 1.6, 'c')) {
writeln(i);
static if (is (typeof(i) == string)) {
  if(i == "John") break;
}
  }
}

Ali



Re: a function like writeln that returns a string rather than writes to a file

2020-05-02 Thread Ali Çehreli via Digitalmars-d-learn
On 5/1/20 7:40 PM, dan wrote:> On Saturday, 2 May 2020 at 02:29:43 UTC, 
H. S. Teoh wrote:

>> On Sat, May 02, 2020 at 02:22:42AM +, dan via Digitalmars-d-learn
>> wrote:
>>> I'm looking for a function something like writeln or write, but
>>> instead of writing to stdout, it writes to a string and returns the
>>> string.
>> [...]
>>
>> import std.format : format;
>> string str = format("%s %s %s", obj1, obj2, obj3);
>>
>>
>> T
>
> Thanks HS!
>
> That looks like a good move, if format will do the string conversion for
> me.
>
> But one thing that would be troublesome is that i would have to make
> sure to count up the %s so that they match the number of arguments.  I
> would like to do without that, just like writeln does.

If you can live with a mildly awkward way of passing it, format() can 
take the format string at compile time as well:


  string str = format!"%s %s %s"(obj1, obj2, obj3);

You get a compilation error if format specifications don't match the 
arguments. (There are bug reports about that check but it mostly works 
great.)


Ali



Re: Help, what is the code mean?

2020-04-28 Thread Ali Çehreli via Digitalmars-d-learn

On 4/28/20 1:48 PM, Net wrote:
> () { ... } ();
>
> Is there a name of this kind of function in D? unnamed? anonymous?

Lambda or anonymous function.[1]

Note that the last () is not part of the definition but the execution of 
the function.


This idiom is used for initializing e.g. a const variable with 
non-trivial code as well (in C++ as well):


const a = {
// ... some complex logic ...
return result;
  }();

Ali

[1] I have a page that shows different syntaxes for lambda functions:

  http://ddili.org/ders/d.en/lambda.html#ix_lambda.=%3E



Re: DConf 2017 Videos

2020-04-24 Thread Ali Çehreli via Digitalmars-d-learn
On 4/24/20 2:11 PM, Steven Schveighoffer wrote:> On 4/24/20 4:24 PM, 
matheus wrote:


> whomever controlled the sociomantic youtube account took down
> all the videos.

I think it's unintentional because the same thing happened to my Weka 
account: After I stopped working there, the company naturally deleted my 
account and the videos that were associated with that account 
disappeared from YouTube after a grace period. I think it was one month 
at that time but nobody was aware until it was too late.


Apparently the internet can actually forget some things. :)

Ali



Re: No implicit opOpAssign for structs with basic types?

2020-04-04 Thread Ali Çehreli via Digitalmars-d-learn

On 4/4/20 8:45 AM, Steven Schveighoffer wrote:

>> Yes, sure, but in C++ I don't have to explicitly write this down. It
>> just works. IMO that makes a lot of sense as long as all types fit.
>> This just looks superfluously.
>>
>
> steves@homebuild:~$ cat test.cpp
> struct S
> {
>  float a;
>  float b;
> };
> int main()
> {
>  S a = {1, 5};
>  S b = {2, 5};
>
>  a += b;
> }
> steves@homebuild:~$ g++ -o test test.cpp
> test.cpp: In function ‘int main()’:
> test.cpp:11:4: error: no match for ‘operator+=’ (operand types are ‘S’
> and ‘S’)
>a += b;
>~~^~~~
>
> Doesn't seem to "just work" for me...

I was about to say the same. C++ does not have this feature. What it has 
as a feature and as a guideline is to define an operator+ outside of the 
type's definition. Perhaps that's what's helping in C++ in this case: 
the type looks clean but there are "interface" functions outside of it.


I've used the following trick in D for many of my types, which I've been 
copy-pasting but it can be mixed in:


struct S {
  float a;
  float b;

  int opCmp(const(typeof(this)) that) const {
import std.typecons : tuple;
return tuple(this.tupleof).opCmp(tuple(that.tupleof));
  }
}

unittest {
  assert(S(3) < S(4));
  assert(S(1, 2) > S(1, 1));
}

void main() {
}

Ali




Re: DMD: Is it possible change compile time errors to runtime errors in Dlang?

2020-03-06 Thread Ali Çehreli via Digitalmars-d-learn
On 3/6/20 5:59 AM, Marcone wrote:> On Friday, 6 March 2020 at 05:31:57 
UTC, Mathias Lang wrote:


> I'm coming from Python

The fact that errors are delayed until run time is a Python deficiency. 
We accept that deficiency because we also accept claimed benefits that 
Python brings.


If you want to skip the compilation step, you unfortunately can not, but 
you can combine compilation and execution steps with 'rdmd', which may 
make it look like the errors are caught at run time:


  https://dlang.org/rdmd.html

Ali



Re: in not working for arrays is silly, change my view

2020-02-29 Thread Ali Çehreli via Digitalmars-d-learn

On 2/29/20 11:38 AM, JN wrote:

> assert(1 in [1, 2, 3]);

Because you mentioned canFind, I think you want the semantics to be "is 
there an element with this value." If so, it would be confusing to use 
the same operator for two different things: For associative arrays, it 
means "is there an element accessible with this key."


Unless 'in' works with arrays to mean "is this index valid", then I 
don't see the benefit. If we had it, I think more people would ask "why 
does 'in' work differently for arrays?"


Are there other languages that support this semantic? Checking... Ok, 
Python has it, highly likely because they don't have arrays to begin with.


Ali



Re: What's opIndexAssign supposed to return ?

2020-02-25 Thread Ali Çehreli via Digitalmars-d-learn
On 2/25/20 3:02 AM, wjoe wrote:> Lets say I've got 3 overloads of 
opIndexAssign:

>
> auto opIndexAssign(T t);

> an internet search which didn't find any useful
> information.

I have examples for non-templatized and templatized versions of 
opIndexAssign here:



http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.opIndexAssign


http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.opIndexAssign%20template

I used this index to find those:

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

Ali



Re: Dynamic array of Cycle buffers of size 2 which use a struct?

2020-02-22 Thread Ali Çehreli via Digitalmars-d-learn

On 2/22/20 2:29 PM, Robert M. Münch wrote:
I don't get how I can create a dynamic array of Cycle buffers of size 2 
which use a struct.


  struct ms {
    int a;
    int b;
  }
  ms[2] msBuffer;
  alias circularStructBuffersT = typeof(cycle(msBuffer));
  circularStructBuffersT[int] circularStructBuffers;

  int i = 2;
  auto x = circularStructBuffers.require(i, (){
    ms[2] t;
    return cycle(t,2);
  });


It looks like require() requires :) a value, which it evaluates only if 
necessary:


  https://dlang.org/spec/hash-map.html#inserting_if_not_present

In your case, you're passing a callable. All you need to do is to 
actually call that callable with empty parenthesis:


  auto x = circularStructBuffers.require(i, {
// ...
}());  // <-- HERE

Because the parameter is lazy, it will still be called only when needed.

Ali



Re: 2D matrix operation (subtraction)

2020-02-21 Thread Ali Çehreli via Digitalmars-d-learn

On 2/21/20 12:51 AM, Andre Pany wrote:

Hi,

I have a 2D double array and I want to subtract from the first column a 
value,

is this possible with matrix operation in D?

```
void main()
{
     double[][] data = [[0.0, 1.4], [1.0, 5.2], [2.0, 0.8]];

     // subtract -2.0 from the first column for every value

     // Expected output
     // data = [[-2.0, 1.4], [-1.0, 5.2], [0.0, 0.8]];

}
```

Kind regards
André





I don't have experience with it but mir's ndslice is designed for this:

  https://github.com/libmir/mir-algorithm

Although it feels like something similar is probably already in Phobos, 
I've come up with the following solution just now for fun:


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

// At least something similar to this exists in Phobos?
struct ElementReference(R) {
  ElementType!(ElementType!R) * p;

  ref reference() {
return *p;
  }

  alias reference this;
}

struct Column(R) {
  R range;
  size_t n;

  auto empty() {
return range.empty;
  }

  auto front() {
return ElementReference!R(&(range.front[n]));
  }

  auto popFront() {
return range.popFront();
  }
}

auto byColumn(R)(R range, size_t n) {
  return Column!R(range, n);
}

void main() {
  double[][] data = [[0.0, 1.4], [1.0, 5.2], [2.0, 0.8]];

  data.byColumn(0).each!(a => a -= 2.0);
  writeln(data);
}

Ali



Re: Regex split ignoore empty and whitespace

2020-02-20 Thread Ali Çehreli via Digitalmars-d-learn

On 2/20/20 4:46 PM, Ali Çehreli wrote:

>auto range = std.regex.splitter!(No.keepSeparators)(l,
> ctRegex!`[\s-\)\(\.]+`);

After realizing that No.keepSeparators is the default value anyway, I 
tried 'split' and it worked the way you wanted. So, perhaps all you 
needed was that extra '+' in the regex pattern:


  std.regex.split(l, ctRegex!`[\s-\)\(\.]+`)

Ali




Re: Regex split ignoore empty and whitespace

2020-02-20 Thread Ali Çehreli via Digitalmars-d-learn
On 2/20/20 2:02 PM, AlphaPurned wrote:> std.regex.split(l, 
ctRegex!`[\s-\)\(\.]`);

>
> I'm trying too split a string on spaces and stuff... but it is returning
> empty strings and other matches(e.g., ()).
>
> I realize I can delete afterwards but is there a direct way from split
> or ctRegex?

It turns out, split uses splitter, which is more capable, like allowing 
to say "do not keep the separators". The difference is, splitter returns 
a range, so I called .array to give you an array but it's not necessary.


I took liberty to add a '+' to your pattern, which may not be useful in 
your case:


import std.regex;
import std.stdio;
import std.typecons : No, Yes;
import std.array;

void main() {
  auto l = "hello world\t  and  moon";
  auto range = std.regex.splitter!(No.keepSeparators)(l, 
ctRegex!`[\s-\)\(\.]+`);

  auto array = range.array;

  writeln(range);
  writeln(array);
}

Both lines print ["hello", "world", "and", "moon"].

Ali



Re: Get compilation errors within opDispatch?

2020-02-17 Thread Ali Çehreli via Digitalmars-d-learn

On 2/17/20 8:41 AM, cc wrote:
Is there any way to see the compilation errors that occurred within an 
opDispatch template?


struct Foo {
 void opDispatch(string s, SA...)(SA sargs) {
     literally anything;
 }
}
Foo foo;
foo.hello(5);

Result:  Error: no property `hello` for type `Foo`

Desired result:  Error: undefined identifier `literally`



Try dmd command line switch  -verrors=spec.

Ali



Re: How to refer to different sized static arrays

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

On 2/8/20 12:22 AM, Adnan wrote:
Just a foreword, this is for learning purposes, hence I am not using the 
dynamic array or Array!T.


I have a structure that maintains a heap allocated sized array inside.

struct LifoStack(T) {
   T[?] data;
}

This `data` is manually resized and copied. Thus the size itself is not 
a compile time constant. What should go inside `?` in the the type 
signature of data?


You just leave the parentheses empty:

  T[] data;

T[] is internally two things, the equivalent of the following:

   size_t length;
   T * ptr;


Also, how can I create runtime-determined sized fixed array in the heap?


To have fixed-size array, you have to somehow spell the size out at 
compile time. The closest thing that comes to mind... does not make 
sense... :)


T[N] makeStaticArray(T, size_t N)() {
  T[N] result;
  return result;
}

void main() {
  auto arr = makeStaticArray!(int, 42)(); // <-- Must say 42
}

See std.array.staticArray, which is much more useful:

  https://dlang.org/phobos/std_array.html#staticArray

But, really, if the size is known at run time, it's a dynamic array. :)

Ali



Re: Abstract override behaviour

2020-02-05 Thread Ali Çehreli via Digitalmars-d-learn

On 2/5/20 8:49 AM, Claudiu wrote:

In class "Min" definition I am receiving this error: "cannot implicitly 
override base class method `IncrementalStat.accumulate` with  
`Min.accumulate`; add `override` attribute"


Andrei's book is a little dated. Here is the errata:

  http://erdani.com/index.php?cID=109

Ali



Re: Unexpected result of IsInstanceOf

2020-01-30 Thread Ali Çehreli via Digitalmars-d-learn

On 1/30/20 4:51 PM, Ben Jones wrote:
The following result doesn't make sense to me... how does isInstanceOf 
return false?


```
import std.traits;
import std.stdio;
import std.typecons;
auto f(T)(T t){
 return Nullable!T(t);
}
void main(){
     auto f3 = f(3);
     writeln(typeof(f3).stringof);
     writeln(isInstanceOf!(Nullable, f3));
}
```

outputs

```
Nullable!int
false
```


In this case it's an instance of a type template, which only types would 
be. So, you want to check whether typeof(f3) is an instance of Nullable.


Ali




Re: Subrange type

2020-01-28 Thread Ali Çehreli via Digitalmars-d-learn

On 1/28/20 1:55 AM, Herbert wrote:

> wow, pragma,

pragma was to indicate the type of elements at compile time.

> import ...

Yes, iota is a Phobos feature, part of a module.

> only to declare a subrange type, something so simple and natural

Some languages think so.

> I could use it in many functions as a parameter type with one single
> simple declaration.

Sorry for jumping in the conversation like that but no, it's not a 
subrange type.


> It's a pitty.

My apologies...

Ali



Re: Subrange type

2020-01-27 Thread Ali Çehreli via Digitalmars-d-learn

On 1/27/20 1:15 PM, Herbert wrote:

On Monday, 27 January 2020 at 20:15:33 UTC, Steven Schveighoffer wrote:

On 1/27/20 3:06 PM, Herbert wrote:
How can I create a subrange type, for example ushort DiceValue {1 ... 
6}?


D doesn't have a "Range" type like this. But you can use ranges of 
different types by typing the literals. Note that D numeric ranges are 
always exclusive at the upper end.


e.g.:

ushort(1) .. ushort(6+1)

-Steve


Thank you Steven!

How can I have a function parameter with this type (DiceValue)?



There is also iota() than generates a range:

import std.stdio;
import std.range;

void foo(R)(R range) {
  pragma(msg, "Element type: ", ElementType!R);

  writefln!"Using as a range:\n%-(%s\n%)"(range);

  writeln("Using in a foreach loop:");

  foreach (element; range) {
writeln(element);
  }
}

void main() {
  auto range = iota(ushort(1), ushort(7));
  foo(range);
}

The output:

Using as a range:
1
2
3
4
5
6
Using in a foreach loop:
1
2
3
4
5
6

Ali


Re: How to call 'shared static this()' code of a D shared library?

2020-01-19 Thread Ali Çehreli via Digitalmars-d-learn

On 1/17/20 7:53 PM, Adam D. Ruppe wrote:

Did you already try rt_init? That should trigger it


I was under the impression that the extern (C) function rt_init() would 
magically be exposed from the library but 'nm' showed no such symbol. 
So, I ended up exposing a my_init() function, which called rt_init() 
internally.


I've realized that rt_init() is sneaky: it returns 1 for success. WAT!? 
:p Then I discovered the more readable Runtime.initialize(), which is 
also sneaky by returning 'true' for success. WAT!? WAT!? :p


This worked:

import core.runtime;

extern (C)
int my_init() {
  return tried({
return Runtime.initialize ? 0 : 1;
  });
}

my_deinit() is similar...

Ali

P.S.'tried' is a function template that I wrote, which catches all 
throwables, logs the issue, and returns 1 as an error code.


Re: How to call 'shared static this()' code of a D shared library?

2020-01-18 Thread Ali Çehreli via Digitalmars-d-learn

On 1/18/20 6:14 AM, Guillaume Piolat wrote:

On Saturday, 18 January 2020 at 03:53:43 UTC, Adam D. Ruppe wrote:

Did you already try rt_init? That should trigger it


Indeed, this is done by runtime initialization.


Thank you, Adam and Guillaume. That tells me I've been using druntime 
without initializing it. :D I'm guessing the problem would be the lack 
of garbage collection? Otherwise, dynamic arrays seemed to work 
correctly (so far).


Ali

Aside: A tip for others who may need to call the Python C API from D, 
you have to call PyGILState_Ensure() and PyGILState_Release(): 
https://docs.python.org/3/c-api/init.html#non-python-created-threads


How to call 'shared static this()' code of a D shared library?

2020-01-17 Thread Ali Çehreli via Digitalmars-d-learn
Simply linking my D shared library with foreign code (Python with the 
help of ctypes in this case) does not work. What function should I call? 
What about 'shared static ~this()'? And would the answer be different 
for 'static this()' etc.?


Thank you,
Ali


Re: lambda alias import

2020-01-17 Thread Ali Çehreli via Digitalmars-d-learn
On 1/17/20 3:04 PM, Petar Kirov [ZombineDev] wrote:> On Friday, 17 
January 2020 at 21:40:05 UTC, JN wrote:


> I think the problem comes from the way you compile and link your code. I
> you compile both modules together like this it should work out:
>
> dmd -ofresult main.d stuff.d

If that's the solution, some people may find a relatively less known dmd 
command line switch useful: -i:


  -i[=]include imported modules in the compilation

Ali



Re: range algorithms on container class

2020-01-15 Thread Ali Çehreli via Digitalmars-d-learn
On 1/14/20 8:15 PM, Alex Burton wrote:> On Thursday, 9 January 2020 at 
10:26:07 UTC, Jonathan M Davis wrote:

>> On Wednesday, January 8, 2020 10:56:20 PM MST rikki cattermole via
>> Digitalmars-d-learn wrote:
>>> Slicing via the opSlice operator overload is a convention, not a
>>> requirement.
>>
>> It's not a requirement, but it's more than a convention. If you use
>> the container with foreach, the compiler will call opSlice on the
>> container to get a range. So, there's no need to implement opApply to
>> iterate over a container with foreach. You could choose to implement a
>> container with opApply and use a function other than opSlice for
>> getting a range, but the compiler understands enough to try to slice
>> the container for you automatically when using it with foreach.
>>
>> - Jonathan M Davis
>
> Implementing opApply allowed me to use foreach on the container.

However, that method does not allow you to have more than one iteration 
on the same container. Once opApply is running, the state of iteration 
is in function call stack. (opApply is calling out to the body of the 
foreach loop until the loop is over.)


In contrast, you can have multiple range objects over the same container:

  auto a = cont[];
  auto b = cont[];

Now the state of iteration are independently handled by a and b.

There is only one case that comes to mind where opApply is superior: 
When iteration involves recursion like tree traversal, then the way 
opApply takes advantage of function call stack is vastly easier (to me 
at least :) ). Even in that case, one can use fibers but it is a little 
bit more complication over opApply.


> I would expect that returning a slice would not be logically possible
> for many container types.

That is true if you're thinking about a slice as a RandomAccessRange, 
which is the case for arrays. However, if we think of slicing as 
"returning a range object over all elements" (i.e. an InputRange 
suffices), then it fits all containers.


> A slice cannot be a range either, otherwise
> you would need to call the array algorithm to assign a slice of an array
> to another array.

Part of this confusion (for me as well) is due to D's conflation of 
slices with dynamic arrays. When we see the slice as the range and think 
of the memory location as the sometimes anonymous container, then slice 
assignment may be valid for user-defined containers. The name of the 
operator is not clear (opIndexAssign):


  https://dlang.org/spec/operatoroverloading.html#slice_assignment_operator

I have two sections that show examples of its single-dimensional and 
multi-dimensional uses:



http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.opIndexAssign

The multi-dimensional use case shows how a container and its range types 
are different types:



http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.opIndexAssign%20template

That example was difficult for me to understand. :)

> So the compiler must be creating a forward iterating range to pass into
> the range algorithms in these cases.

Exactly and should do the same with user-defined types.

> That foreach, and range algorithms can work on a native array but only
> foreach can work on custom container type looks like a gap in the 
language.


I think there are some corner cases but not for most (all?) cases.

Ali



Re: books for learning D

2020-01-13 Thread Ali Çehreli via Digitalmars-d-learn

On 1/13/20 2:28 AM, mark wrote:

I'm just starting out learning D.

Andrei Alexandrescu's "The D Programming Language" is 10 years old, so 
is it still worth getting? (I don't know how much D has changed in 10 
years.)




Yes, Andrei's book is dated but it offers a great perspective on D and 
programming languages in general.


Unfortunately, my book is lagging behind as well. For example, I still 
have to replace post-blit with copy constructors.


I recommend Mike's book as well and Adam's book is a great complement to 
all the tutorials. Kai's book is great too but it is on vibe.d and I 
don't know how much vibe.d has changed since the book was written.


Ali


Re: Multi-threaded sorting of text file

2020-01-04 Thread Ali Çehreli via Digitalmars-d-learn

On 1/3/20 11:51 PM, MGW wrote:

Need help:
There' s a large text file (hundreds of thousands of lines).


How long are the lines? If 1K bytes, 100M would fit in memory just fine. 
There is a parallel quick sort example on the std.parallelism page:


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


The structure is as follows:
2345|wedwededwedwedwe ..
872625|rfrferwewweww .
23|rergrferfefer 
.

It is necessary to sort this file by the first field having received:
23|rergrferfefer...
2345|wedwededwedwedwe...
872625|rfrferwewweww...


Are you going to write the result back to a file? Then you would hardly 
notice any improvement from parallelism because relative slowness of I/O 
would determine the overall performance.




There are also N CPU (from 4 to 8) and 16 Gb of Memory. Necessary
come up with an algorithm in D for fast sorting using multithreading.




Ali


Re: Simple casting?

2019-11-26 Thread Ali Çehreli via Digitalmars-d-learn
On 11/26/19 2:08 PM, Taylor R Hillegeist wrote:> On Tuesday, 26 November 
2019 at 16:33:06 UTC, Timon Gehr wrote:

>> int[][] y=x.chunkBy!((a,b)=>a==b).map!array.array;
>
>
> how did you know to do that?

Ranges don't have elements. They either generate elements according to 
an algorithm, provide access to elements (or copies of elements) that 
belong to other containers.


In this case, chunkBy() is like an engine that knows how to present the 
input range in chunks but does not start working automatically. This is 
a great feature because you can start accessing chunks, deciding it's 
enough, and stop; potentially avoiding a lot of eager work (potentially 
infinite).


std.array.array pulls all elemenst of a range and places them inside an 
array. That is eager but sometimes necessary work. For example, 
std.algorithm.sort cannot sort just any range because it needs the 
elements to be layed out as array elements:


  someAlgorithmRange.sort;  <-- Does not work
  someAlgorithmRange.array.sort <-- Works

Ali



  1   2   3   4   5   6   7   8   9   10   >