Re: Template pattern delegate?

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

On 10/25/20 4:30 AM, frame wrote:
Is there a possibility to write templated code / custom trait pattern 
with usage like a delegate?


I have a try-catch block with different types and don't want to repeat 
myself in every method again. It's always the same, just what's tried 
changes, eg.:


pseudo code:

template myStuff(mixin code)
{
     try {
     code();
     }
     catch (X e) {
     ...
     }
     catch (Y e) {
     ...
     }
     ...
}

static myStuff!({
    writeln("...");
});



That's one of my DConf Onlide slides but for a limited use case! :)

int tried(Func, string functionName = __FUNCTION__, string file = 
__FILE__, size_t line = __LINE__)(Func func) {

  static if (!is (ReturnType!Func == int)) {
pragma(msg, format!"\n%s(%s): Error: %s must return int error 
code"(file, line, functionName));

static assert(false);
  }

  void printError(T)(T err) {
stderr.writefln!"\n%s(%s): Failed to execute %s: %s"(file, line, 
functionName, err);

  }

  try {
return func();

  } catch (Exception exc) {
printError(exc.msg);
return 1;

  } catch (Error err) {
printError(err);
import core.stdc.stdlib : abort;
abort();
  }

  assert(false);
}

Then, all extern(C) functions would be written the same way:

extern(C) int foo() {
  return tried({
// ...
return 0;
  });
}

Ali



Re: toStringz lifetime

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

On 10/25/20 3:19 AM, rikki cattermole wrote:

On 25/10/2020 11:03 PM, Ali Çehreli wrote:
Does the GC see that local variable 'name' that is on the C side? What 
I don't know is whether the GC is aware only of the stack frames of D 
functions or the entire thread, which would include the C caller's 
'name'.


The thread stack frame that is registered with the D GC will know about 
the D side and may know about the C side.


It depends on what the C side is doing.

If the C side went ahead and made a new stack frame via a fiber... it 
won't know about it. But even if it did, the D stack frame is still 
alive and pinning that bit of memory.


Ultimately, if the C side puts that pointer some place like a global or 
send it to another thread, there are no guarantees that things will play 
out well.


Thanks. That's reassuring. :) So, as long as the D function documents 
that the C side should make a copy if they want to extend the string's 
lifetime it's their responsibility. And from your description I 
understand that they have time to make that copy.


Ali



toStringz lifetime

2020-10-25 Thread Ali Çehreli via Digitalmars-d-learn
toStringz documentation is clear on why, when, and how to extend the 
lifetime of a D string:


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

Assume foo is a D library function that passes a "string" result to e.g. C:

extern(C)
void foo(ref const(char) * name) {
  name = format!"file%s.txt"(42).toStringz;  // Allocates from GC memory
}

This may be fine for "immediate use" on the C side because at first 
glance no garbage collection can take place between our returning the 
result and their using it:


// C caller:
  const char * name = NULL;
  foo(); // Calls us
  printf("%s", name); // Uses 'name' immediately

Is it really safe? Imagine a multi-threaded environment where another D 
function is executed that triggers a GC collection right before the printf.


Does the GC see that local variable 'name' that is on the C side? What I 
don't know is whether the GC is aware only of the stack frames of D 
functions or the entire thread, which would include the C caller's 'name'.


Ali


Re: Two ways of receiving arrays on the C ABI

2020-10-20 Thread Ali Çehreli via Digitalmars-d-learn
On 10/19/20 6:28 PM, Nicholas Wilson wrote:> On Tuesday, 20 October 2020 
at 00:16:48 UTC, Ali Çehreli wrote:

>> On the D side, both of the following extern(C) functions take the same
>> arguments.
>
> https://github.com/dlang/dmd/pull/8120
>
> there are issues with structs. Not sure about length/ptr.

Thank you, Nic.

I see that doing the following is undefined behavior:

extern(C)
void dFunc(int[] arr) {// <-- Takes slice
  assert(arr.equal(3.iota));
}

// A C function
void dFunc(size_t length, int * ptr);  // <-- Passes length+pointer

  int arr[] = { 0, 1, 2 };
  dFunc(3, arr);

C does not define an ABI. So, length+pointer can be passed in any way 
from there. The good thing is that D is aware of the "C Application 
Binary Interface of the target system"[1] but that means D would support 
taking length+pointer as well. Slice arguments are still strictly in 
length+pointer order for D.


So, it works on my Linux system by chance.

Ali

[1] https://dlang.org/spec/abi.html




Two ways of receiving arrays on the C ABI

2020-10-19 Thread Ali Çehreli via Digitalmars-d-learn
On the D side, both of the following extern(C) functions take the same 
arguments.


1) func1 takes .length and .ptr implicitly as parts of a D array:

extern(C)
void func1(int[] arr) {
  assert(arr.equal(3.iota));
}

2) func2 takes .length and .ptr separately and then makes a slice 
explicitly:


extern(C)
void func2(size_t length, int * ptr) {
  auto arr = ptr[0..length];
  assert(arr.equal(3.iota));
}

C side declares and calls both of them the same way:

void func1(size_t length, int * ptr);
void func2(size_t length, int * ptr);

  int arr[] = { 0, 1, 2 };
  func1(3, arr);
  func2(3, arr);

Everything works at least on Linux. Is this kosher, or am I using some 
internal knowledge?


Here is the ABI spec:

  https://dlang.org/spec/abi.html

One of the DConf Online 2020 slides thanks you! ;)

Ali


Re: Forward referencing functions in D

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

On 10/17/20 8:28 AM, NonNull wrote:

On Friday, 16 October 2020 at 21:28:18 UTC, Steven Schveighoffer wrote:

Inner functions have benefits:

1. They are only accessible inside the function. Which means you only 
have to worry about correctness while INSIDE that function.

2. inner functions have access to the outer function's stack frame.

Often, I use inner functions to factor out a common piece of code that 
I don't want to have to write multiple times in the same function.


-Steve


How can you write two inner functions that call each other? (Recursively)


I thought of the following method just now. Yes, there are lambdas but 
who cares? :) (Besides, 'a' can be defined as a proper function below.)


import std.range;

void foo(string s) {
  // b is not initialized yet
  void delegate() b;

  // a is initialized
  auto a = {
while (!s.empty) {
  s.popFront();
  b();
}
  };

  // Set b to a lambda
  b = {
while (!s.empty) {
  s.popBack();
  a();
}
  };

  a();
}

void main() {
  foo("hello");
}

Ali


Re: why do i need an extern(C): here?

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

On 10/16/20 4:12 PM, WhatMeWorry wrote:

> Isn't dlopen() for Linux

More like dlopen() is for Posix, which means it should be available on 
Windows as well.


However, as I've discovered, a D shared library cannot be loaded with 
dlopen() because the main program and the shared library would do their 
own garbage collection (presumably with separate GC states) without 
being aware of each other and this won't work. Runtime.loadLibrary() 
knows to do the right thing and both sides are aware of each other.


> and LoadLibrary() for Windows?

Yes, but I am talking about core.runtime.Runtime.loadLibrary, which 
should call appropriate functions depending on the operating system.


> Or are you
> running Windows

I run Windows with mild disgust :p only for work-related applications. 
Otherwise, it's all Linux.


Ali



Re: How can I convert Hexadecimal to RGB Color and vice-versa?

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

On 10/16/20 1:10 PM, Marcone wrote:

How can I convert Hexadecimal to RGB Color and vice-versa?


On 10/16/20 1:10 PM, Marcone wrote:

> How can I convert Hexadecimal to RGB Color and vice-versa?

Do you mean from a string like "#123456" to the values of red, green, 
and blue? I am having more fun with D than usual. So, I wrote the 
following without understanding your requirements. :)


I am sure this already exists in various libraries.

import std.exception;
import std.range;
import std.format;
import std.stdio;
import std.traits;

struct RGB {
  ubyte red;
  ubyte green;
  ubyte blue;

  this(const(char)[] s) {
enforce(s.length < 8, format!`Invalid RGB string: "%s"`(s));

if (s.front == '#') {
  s.popFront();
}

 uint value;
 s.formattedRead!"%x"(value);
 this(value);
  }

  this(T)(T value)
  if (isIntegral!T) {
enforce(value >= 0 && value < 0x100_,
format!"Invalid RGB value: %s (0x%,*?x)"(value, 2, '_', 
value));


ubyte popLowByte() {
  ubyte b = value & 0xff;
  value >>= 8;
  return b;
}

this.blue = popLowByte();
this.green = popLowByte();
this.red = popLowByte();

assert(value == 0);
  }

  string asHex() {
return format!"%02x%02x%02x"(red, green, blue);
  }
}

void main() {
  auto a = RGB("#a0a0a0");
  writeln(a);

  auto b = RGB(0x10ff20);
  writeln(b);
  writeln(b.asHex);
}

Ali


Re: Forward referencing functions in D

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

On 10/16/20 1:47 PM, wilcro wrote:

> would
> there be any reason to avoid placing the majority of code for a program
> outside of the main function?

Keeping scopes of symbols as small as possible is a general guideline in 
D and elsewhere but I wouldn't crowd my main() function with details of 
program logic either. (Aside: There is no global name scope in D; 
everything belongs to a module.)


One thing I love about D is that there are no strong principles like 
that. I code in a way that is comfortable and change things later on as 
a needs arise. :)


Ali



Re: Packing of Struct Fields

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

On 10/16/20 1:32 PM, Per Nordlöw wrote:
Why is `T.sizeof` 12 instead of 8 when `U.sizeof` is 8 in the following 
example?


struct S
{
     int i;
     bool b;
}

struct T
{
     S s;
     char c;
}

struct U
{
     int i;
     bool b;
     char c;
}

?


I have a function that dumps member layout of structs, which someone may 
find useful:


  http://ddili.org/ders/d.en/memory.html#ix_memory..offsetof

It prints the following for these types:

=== Memory layout of 'S' (.sizeof: 8, .alignof: 4) ===
   0: int i
   4: bool b
   5: ... 3-byte PADDING
=== Memory layout of 'T' (.sizeof: 12, .alignof: 4) ===
   0: S s
   8: char c
   9: ... 3-byte PADDING
=== Memory layout of 'U' (.sizeof: 8, .alignof: 4) ===
   0: int i
   4: bool b
   5: char c
   6: ... 2-byte PADDING

Copied here:

struct S
{
int i;
bool b;
}

struct T
{
S s;
char c;
}

struct U
{
int i;
bool b;
char c;
}

void printObjectLayout(T)()
if (is (T == struct) || is (T == union)) {
import std.stdio;
import std.string;

writefln("=== Memory layout of '%s'" ~
 " (.sizeof: %s, .alignof: %s) ===",
 T.stringof, T.sizeof, T.alignof);

/* Prints a single line of layout information. */
void printLine(size_t offset, string info) {
writefln("%4s: %s", offset, info);
}

/* Prints padding information if padding is actually
 * observed. */
void maybePrintPaddingInfo(size_t expectedOffset,
   size_t actualOffset) {
if (expectedOffset < actualOffset) {
/* There is some padding because the actual offset
 * is beyond the expected one. */

const paddingSize = actualOffset - expectedOffset;

printLine(expectedOffset,
  format("... %s-byte PADDING",
 paddingSize));
}
}

/* This is the expected offset of the next member if there
 * were no padding bytes before that member. */
size_t noPaddingOffset = 0;

/* Note: __traits(allMembers) is a 'string' collection of
 * names of the members of a type. */
foreach (memberName; __traits(allMembers, T)) {
mixin (format("alias member = %s.%s;",
  T.stringof, memberName));

const offset = member.offsetof;
maybePrintPaddingInfo(noPaddingOffset, offset);

const typeName = typeof(member).stringof;
printLine(offset,
  format("%s %s", typeName, memberName));

noPaddingOffset = offset + member.sizeof;
}

maybePrintPaddingInfo(noPaddingOffset, T.sizeof);
}

void main() {
  printObjectLayout!S();
  printObjectLayout!T();
  printObjectLayout!U();
}

Ali



Re: Struct field destructor not called when exception is thrown in the main struct destructor

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

On 10/16/20 9:05 AM, Steven Schveighoffer wrote:

> The destruction of members is outside the destructor's purview. It can't
> turn the destruction off, so it should logically be considered part of
> an enclosing function.

Thank you. Makes sense.

Ali



Re: why do i need an extern(C): here?

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

On 10/15/20 2:42 PM, Ali Çehreli wrote:

> I've recently done the same by calling dlopen() and dlsym()
> directly. Runtime.loadLibrary documentation says "If the library
> contains a D runtime it will be integrated with the current runtime."
> That would explain why my program seg-faults for my first tester with
> the garbage collector signatures in the function call stack.

Replacing dlopen() with Runtime.loadLibrary() did solve the segfault 
issue for me.


Ali




Re: Struct field destructor not called when exception is thrown in the main struct destructor

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

On 10/16/20 6:12 AM, tchaloupka wrote:

> struct Foo {
>  Bar bar;
>  bool err;
>
>  ~this() {
>  // scope(failure) destroy(bar); // < this fixes the Bar
> destructor call
>  enforce(!err, "Test err");

Well, that check means "cannot continue", which means the compiler stops 
executing the destruction code because it can't. (It would a serious bug 
if it continued execution in a state that the program knows to be invalid.)


>  }

Conceptually, bar's destructor is called on that closing brace but we 
decided to abort mission earlier. Your calling destroy(bar) may or may 
not be wrong in case of 'err'. Only you know at that point.


> Is this behavior expected?

Yes.

Ali



Re: why do i need an extern(C): here?

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

On 10/15/20 2:29 PM, WhatMeWorry wrote:

> name wrangling?

Name mangling. :) I don't know the answer but I can hijack your thread.

>  import core.runtime;
>  auto mydll = Runtime.loadLibrary("mydll.dll");

Interesting. I've recently done the same by calling dlopen() and dlsym() 
directly. Runtime.loadLibrary documentation says "If the library 
contains a D runtime it will be integrated with the current runtime." 
That would explain why my program seg-faults for my first tester with 
the garbage collector signatures in the function call stack. Right? 
Thanks! :)


Ali



Re: malloc(s)[0..s] vs cast(T)malloc(s)

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

On 10/14/20 1:15 PM, Jack wrote:

>> auto x = malloc(s)[0..s];

> 
https://wiki.dlang.org/Memory_Management#Explicit_Class_Instance_Allocation


Note that 'x' is passed to emplace() at that link and emplace() requires 
a slice. That's why the a slice is made from the pointer returned by 
malloc().


Ali



Re: Passing pointer to extern(C++) templated function

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

On 10/13/20 4:11 PM, James Blachly wrote:

On 10/13/20 5:23 AM, Jamie wrote:

Building with:
g++ -c a.cpp
dmd main.d a.o

Throws the error:
/usr/bin/ld: main.o: in function `_Dmain':
main.d:(.text._Dmain[_Dmain]+0x31): undefined reference to `void 
func3(int*, int*)'
/usr/bin/ld: main.d:(.text._Dmain[_Dmain]+0x3e): undefined reference 
to `void func4(int const*, int const)'

collect2: error: ld returned 1 exit status
Error: linker exited with status 1



Is the template even instantiated? With just a template definition and 
an object file I am surprised you even have a symbol?


Yes, they all have explicit template instantiations on the C++ side.

I think the issue is with D's "turtles all the way down" style const. My 
workaround would be to define wrapper functions that may need to do 
casting on one or the other side.


Ali



Re: List of exceptions?

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

On 10/12/20 2:11 AM, Dominikus Dittes Scherkl wrote:

> - Throw exceptions only if you have a plan what to do with them if you
> catch them.

My thinking is different: Throw exceptions if you can't accomplish a 
task. My code is filled with enforce() and assert() checks, which do 
throw exceptions.


> - If you have no plan, better throw error, just to get an idea where and
> why the program crashed (and don't try to catch them)

In most cases, catching Exception (not Error) to print exc.msg is fine 
and is the correct thing to do. (Errors are not caught, the stack trace 
is printed, and that's helpful.)


Occasionally, exc.msg of an Exception doesn't give enough information. 
So, printing exc (not exc.msg) temporarily to look at the stack trace is 
helpful.


Ali



Re: Renaming Flag!"" in API

2020-10-12 Thread Ali Çehreli via Digitalmars-d-learn
It's amazing how things come together before each conference. Flag 
appears among my slides for an upcoming conference as well! :)


But I don't think there is any solution to your problem.

On 10/12/20 3:24 AM, FreeSlave wrote:

> Later I realize that 'myflagname' is a bad name and I want to change it
> to something else. But if I do so, I break the existing code using this
> API as Flag with different name will be a different type

This is essentially the same as one of the objections to named arguments.

Ali



Re: Range format specifiers in other languages?

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

On 10/11/20 5:44 PM, Max Haughton wrote:

> Possibly worth showing off (especially given that some people at first
> don't even know the templated format string exists)

This feature is already among my slides for an upcoming conference. ;)

Ali



Range format specifiers in other languages?

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

I find D's %( and %) range format specifiers very useful:

import std.stdio;
import std.range;

void main() {
  5.iota.writefln!"%(%s, %)";  // Prints 0, 1, 2, 3, 4
}

Are there similar features in other languages?

Thank you,
Ali


Re: List of exceptions?

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

On 10/10/20 12:51 PM, DMon wrote:

> I will copy that down.
>
> The idea for specific exceptions came from the online docs and
> Programing in D, 39.2 The try-catch statemet
>
> try
> { // the code block that is being executed, where an // exception may be
> thrown
> }
> catch (an_exception_type)
> { // expressions to execute if an exception of this // type is caught
> }
> catch (another_exception_type)
> { // expressions to execute if an exception of this // other type is
> caught // ... more catch blocks as appropriate ...
> }
> finally
> { // expressions to execute regardless of whether an // exception is 
thrown

> }

I don't have time right now to write longer but I see how that can be 
confusing and apologize for the confusion. :(


In general, forget all of that and just catch Exception. :) That's all 
you need. And 'finally' is almost never used in D.


Ali



Re: List of exceptions?

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

On 10/10/20 9:16 AM, DMon wrote:

> catch (Exception e) // implicit (any exception)
> catch (ConvException f) // explicit (conversion only)
>
> Or is that not correct?

I think in class hierarchies, "more general" and "more specific" are 
better terms. :)


The answer is, catch by the most general under the Exception hierarchy 
that you care about. It depends on the program. In most of my programs, 
catching Exception in main is sufficient because I just print the error 
message.


However, sometimes the error message does not make sense at that level:

void foo() {
  // The error thrown during this may not be meaningful to
  // the user of the program:
  // "Unexpected 'h' when converting from type string to type int"
  "hello".to!int;
}

So, you can augment that error with another one:

import std.conv;
import std.stdio;
import std.format;

class FooException : Exception {
  string msg;
  Exception actual;

  this (Exception e) {
this.msg = format!"Failed to do foo: %s"(e.msg);
super(this.msg);
this.actual = e;  // Store for more information later
  }
}

void foo() {
  try {
"hello".to!int;

  } catch (Exception e) {
// Convert to a more meanigful exception:
throw new FooException(e);
  }
}

int main() {
  try {
foo();

  } catch (Exception e) {
stderr.writefln!"ERROR: %s"(e.msg);
return 1;
  }

  return 0;
}

One cool thing about storing the 'actual' exception is, you can later 
debug it by catching the specific FooException and printing 'actual' as 
is, which contains the stack trace:


int main() {
  try {
foo();

  // Added for debugging:
  } catch (FooException e) {
// Printing as is contains the stack trace:
stderr.writeln(e.actual);
return 1;

  } catch (Exception e) {
stderr.writefln!"ERROR: %s"(e.msg);
return 1;
  }

  return 0;
}

But really, it all depends on your program. The simplest thing may to 
not catch at all. The default behavior is to dump the stack trace and it 
works for some programs.


Ali



Re: List of exceptions?

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

On 10/10/20 8:46 AM, DMon wrote:

On Saturday, 10 October 2020 at 14:56:31 UTC, Ali Çehreli wrote:

On 10/10/20 5:12 AM, DMon wrote:
Is there a list of a list of the exceptions or what can be used with 
catch?


Only Throwable and classes that are derived from it can be thrown and 
caught.


Ali


Thanks for the reply.

I am looking to catch exceptions explicitly and get that it does not 
have to be. Is explicite cathing the best practice or is implicite how 
its done?


I don't know implicit catching. I would like to learn from others.

I think the common rules are:

- Don't catch anything
- Unless you can do something about it (e.g. ask the user something to 
retry, augment it, etc.)


I almost always catch in main() (or a thread's main function) and only 
to print a clean error message:


void main() {
  try {
// ...

  } catch (Exception e) {
stderr.writefln!"ERROR: %s"(e.msg);
  }
}

That's it for me. :)

Ali



Re: List of exceptions?

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

On 10/10/20 5:12 AM, DMon wrote:

Is there a list of a list of the exceptions or what can be used with catch?

I'm thinking that I missed it and there is something easier than 
breaking old code, scouring the site, or hypnotic regression.


Only Throwable and classes that are derived from it can be thrown and 
caught.


It has two decendants:

   Throwable
/ \
 Error   Exception

Throwable and Error are caught very rarely in special situations. For 
example, a thread may catch all types of exceptions to report the reason 
why it's about to die.


So the only type that is and should be used in most programs is Exception:

void main() {
  try {
foo();

  } catch (Exception e) {
writefln!"Something bad happened: %s"(e.msg);

// You can continue if it makes sense
  }
}

So, programs base their exceptions on Exception:

class MyException : Exception {
  this(int i) {
import std.format;
super(format!"Bad int happened: %s"(i));
  }
}

void foo() {
  throw new MyException(42);
}

void main() {
  foo();
}

There are helpers in std.exception e.g.

class MyException : Exception {
  import std.exception;
  mixin basicExceptionCtors;
}

void foo() {
  throw new MyException("a problem happened");
}

void main() {
  foo();
}

I have some basic information here:

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

Ali


Re: Efficient sort function allowing own test and swap function as parameter

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

On 10/6/20 3:18 PM, Alaindevos wrote:
I have a large table consisting of two columns.One with words.Another 
with frequencies. I want to sort them efficiently according to the names 
or frequency.
For this I need an efficient sort function where I can plugin my proper 
test of order, and proper swap. Currently I do it using an own written 
bubble sort that doesn't scale well.




I had fun writing the following program. Note how makeIndex allows 
visiting elements in sorted order without actually sorting them.


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

struct S {
  string word;
  size_t frequency;
}

bool byWord(S a, S b) {
  return a.word < b.word;
}

bool byFrequency(S a, S b) {
  return a.frequency < b.frequency;
}

auto dump(R)(string title, R range) {
  writefln!"\n%s:\n%(%s\n%)"(title, range);
}

// A test function that makes an S
S makeS() {
  string makeWord() {
static letters = iota('a', 'z' + 1).map!(to!dchar).array;
return letters.randomSample(4).to!string; // Four-letter words! :p
  }
  size_t makeFrequency() {
return uniform(0, 100);
  }
  return S(makeWord(), makeFrequency());
}

// A test function that makes some S'es
S[] makeSs() {
  return 10.iota.map!(i => makeS()).array;
}

void main() {
  auto ss = makeSs();
  dump("Unsorted", ss);

  auto byWordIndexes = new size_t[ss.length];
  ss.makeIndex!byWord(byWordIndexes);
  dump("Still unsorted but visited by word order",
   byWordIndexes.map!(i => ss[i]));

  auto byFrequencyIndexes = new size_t[ss.length];
  ss.makeIndex!byFrequency(byFrequencyIndexes);
  dump("Still unsorted but visited by frequency order",
   byFrequencyIndexes.map!(i => ss[i]));

  ss.sort!byWord();
  dump("Actually sorted by words", ss);

  ss.sort!byFrequency();
  dump("Actually sorted by frequencies", ss);
}

Sample output:

Unsorted:
S("bfmp", 78)
S("imsx", 17)
S("kmwy", 60)
S("klpw", 92)
S("hnrt", 24)
S("aivz", 29)
S("prst", 24)
S("cdlm", 86)
S("alvz", 13)
S("mnxz", 52)

Still unsorted but visited by word order:
S("aivz", 29)
S("alvz", 13)
S("bfmp", 78)
S("cdlm", 86)
S("hnrt", 24)
S("imsx", 17)
S("klpw", 92)
S("kmwy", 60)
S("mnxz", 52)
S("prst", 24)

Still unsorted but visited by frequency order:
S("alvz", 13)
S("imsx", 17)
S("hnrt", 24)
S("prst", 24)
S("aivz", 29)
S("mnxz", 52)
S("kmwy", 60)
S("bfmp", 78)
S("cdlm", 86)
S("klpw", 92)

Actually sorted by words:
S("aivz", 29)
S("alvz", 13)
S("bfmp", 78)
S("cdlm", 86)
S("hnrt", 24)
S("imsx", 17)
S("klpw", 92)
S("kmwy", 60)
S("mnxz", 52)
S("prst", 24)

Actually sorted by frequencies:
S("alvz", 13)
S("imsx", 17)
S("hnrt", 24)
S("prst", 24)
S("aivz", 29)
S("mnxz", 52)
S("kmwy", 60)
S("bfmp", 78)
S("cdlm", 86)
S("klpw", 92)

Ali


Re: It is possible to substract 5 from 3 unsigned integer

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

On 10/6/20 5:24 AM, Alaindevos wrote:

Is that the expected behavior of the programmer?
Opinions can differ. Feel free to elaborate.


The following is even more "expected". ;) Subtract zero from -1 and you 
get size_t.max.


void main() {
  int[] arr;
  int i = -1;

  auto u = (i - arr.length);// -1 - 0

  assert(u == size_t.max);   // the surprise
  static assert (is (typeof(u) == size_t));  // the reason
}

Ali


Re: Deprecation in traits

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

On 9/29/20 10:08 AM, Frak wrote:

Hi folks,

I've this:

/Users/frak/dlang/ldc-1.23.0/bin/../import/std/traits.d(3711): 
Deprecation: function `std.typecons.Nullable!long.Nullable.get_` is 
deprecated - Implicit conversion with `alias Nullable.get this` will be 
removed after 2.096. Please use `.get` explicitly.


I'm trying to find out WHERE this is generated to fix it, dependency 
included, without success.


Suggestions?


I've just ported my code to 2.094 and had to clean up that issue. 
Luckily, in my case they were all in user code. I had to access my 
Nullable objects with .get:


  if (n) {
// n.foo();<-- from
n.get.foo();   <-- to
  }

So, look at all your Nullable objects maybe.

Ali


Re: Memory management

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

On 9/29/20 3:57 AM, novice3 wrote:> Naive newbie question:
>
> Can we have (in theory) in D lang memory management like V lang?
>
> Quote:
> https://github.com/vlang/v/blob/master/doc/docs.md#memory-management
>
> "V doesn't use garbage collection or reference counting. The compiler
> cleans everything up during compilation. If your V program compiles,
> it's guaranteed that it's going to be leak free."

I am not a language expert but I can't imagine how the compiler knows 
whether an event will happen at runtime. Imagine a server program 
allocates memory for a client. Let's say, that memory will be 
deallocated when the client logs out or the server times that client 
out. The compiler cannot know either of that will ever happen, right?


Ali



Re: How does alias exactly work

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

On 9/28/20 6:46 PM, Ruby The Roobster wrote:

I thought alias could work like this with classes:


That would work with template parameters:

alias A = Foo!(3, "hello");



alias test = MyClass(3,"H",9.1); //Assume the constructor parameters for 
MyClass are (int,string,double).


Can anybody fix this code?


You have to write a function (or a lambda):

class MyClass {
  this(int, string, double) {
  }
}

auto test1() {
  return new MyClass(3,"H",9.1);
}

auto test2 = () => new MyClass(4, "I", 10.1);

void main() {
  test1();
  test2();
}

However, I assumed each invocation would create a new object. If not, 
something like this:


MyClass test3;
static this() {
  test3 = new MyClass(5, "J", 11.1);
}

test3 is a single instance for each thread. A single instance for the 
whole program would be a different exercise. :)


Ali


Re: How to hide a function return type in order to wrap several functions into an associated array?

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

On 9/27/20 11:54 AM, tastyminerals wrote:

> I have a collection of functions that all have the same input, a string.
> The output however is different and depending on what the function does
> it can be ulong, double or bool.

The following approach overcomes the different return type issue by 
creating delegates that take string and return string:


auto numberOfPunctChars(string text) {
  return 42;
}

auto ratioOfDigitsToChars(string text) {
  return 1.5;
}

auto hasUnbalancedParens(string text) {
  return true;
}

struct FeatureSet {
  alias TakesString = string delegate(string);
  TakesString[] features;

  void register(Func)(Func func) {
// Here, we convert from a function returning any type
// to a delegate returning string:
features ~= (string s) {
  import std.conv : text;
  return func(s).text;
};
  }

  // Here, we apply all feature delegates and put the outputs
  // into the provided output range.
  void apply(O)(ref O outputRange, string s) {
import std.format : formattedWrite;
import std.algorithm : map;
outputRange.formattedWrite!"%-(%s\n%|%)"(features.map!(f => f(s)));
  }
}

void main() {
  auto featureSet = FeatureSet();

  featureSet.register();
  featureSet.register();
  featureSet.register();

  // lockingTextWriter() just makes an output range from
  // an output stream.
  import std.stdio;
  auto output = stdout.lockingTextWriter;
  featureSet.apply(output, "hello world");

  // As another example, you can use an Appender as well:
  import std.array : Appender;
  auto app = Appender!(char[])();
  featureSet.apply(app, "goodbye moon");
  writefln!"Appender's content:\n%s"(app.data);
}

Ali



Re: A scheduled control signal with fibers?

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

On 9/27/20 6:33 AM, Ferhat Kurtulmuş wrote:

> On Sunday, 27 September 2020 at 12:05:13 UTC, Ferhat Kurtulmuş wrote:
>> On Sunday, 27 September 2020 at 10:40:25 UTC, Ali Çehreli wrote:
>>> On 9/27/20 3:06 AM, Ferhat Kurtulmuş wrote:
>
> Oh, It will work fine if I imitate my time-consuming image processing
> like this.
> I think it is Ok now.
>
> import std.stdio;
> import std.concurrency;
> import core.thread;
>
> void main() {
>  foreach (v; 0..10){
>  auto childTid = spawn(, thisTid);

How many flame threads do you need? I thought one image processor and 
one flame thrower, no? Even if you have a dozen of each, main can start 
only the image processing threads and then each image processor can 
start its own flame thrower. Then, each pair will have an owner and a 
worker.


You don't need to send thisTid because every thread already has an 
ownerTid defined:


  auto childTid = spawn();

>  Thread.sleep(10.msecs); // imitate image processing
>  send(childTid, v);

UFCS makes it nicer:

  childTid.send(v);

>
>  }
>  writeln("main is done.");
> }
>
> static void spawnedFunc(Tid ownerTid)

To repeat, you already have a valid ownerTid in this thread. Just remove 
the parameter.


> {
>  receive((int v){
>  Thread.sleep(1500.msecs);

I think you should sleep less than that to work at the exact expected 
time. Otherwise, an unknown amount of time has already passed when this 
thread is woken up again.


Instead of sleeping 1500, something like this may be needed:

  - This thread looks at the time to figure out how long to sleep e.g. 
sometimes 1400 msecs

  - Sleeps that amount
  - Fires when it wakes up

However, you can not expect to be waken up exactly at 1400 msecs later. 
If timing precision is really important, I recommend running some 
statistics to see how much off your thread is when it wakes up. 
Depending on the statistics, I would sleep less than the expected amount 
and then burn the CPU until it's the exact time. But maybe precision is 
not that important; so, forget that idea. :)


>  writeln(v);
>  });
> }

One more thing: It is common for the workers to die with an exception 
(sometimes with Error). You must catch it (including Error) by the 
worker thread and report it somehow e.g. with a special exception. 
Otherwise, nobody will know what happened.


This reminds me: If you start the worker with spawnLinked() instead of 
spawn(), the owner will get a LinkTerminated message if a thread dies. 
That's another way of detecting that failure.


Ali




Re: A scheduled control signal with fibers?

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

On 9/27/20 3:06 AM, Ferhat Kurtulmuş wrote:

> __gshared DList!Entry queue;
> __gshared bool shouldRun = true;

Have you considered passing messages with std.concurrency.send() and 
std.concurrency.receive() and friends? You wouldn't need 'queue' because 
all of your threads already have mail boxes to send messages to each other.


> void worker() {
>  while(shouldRun){
>  auto r = queue[];
>  if(!r.empty && queue.back.st < Clock.currTime){
>  writeln(queue.back); // consume the value
> sendPWMSignalToValfe(pwmval)
>  queue.popLastOf(r);
>  }
>  }
> }

It's not clear whether it's only in your test code but busy-waiting like 
that will make your CPU very warm. :) Since requests cannot pass each 
other, your worker thread should have something like the following in 
that loop:


import core.thread;

  Thread.sleep(duration);

Depending on how accurate the operating system honors your sleep 
requests (e.g. is it real-time?), you may want to sleep less than 
'duration' and then busy-wait the rest of the duration. Similar to the 
difference between spinForce() and yieldForce() of std.parallelism (I 
understand that your solution should not involve std.parallelism):


  https://dlang.org/phobos/std_parallelism.html#.Task.spinForce

As an improvement when defining durations, you don't need to "hide" 
units in comments:


// enum afterNmilliseconds = 1500;

// Instead:
enum after = 1500.msecs;

msecs and friends are defined in core.time:

  https://dlang.org/phobos/core_time.html#.dur

Ali




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



<    4   5   6   7   8   9   10   11   12   13   >