Re: Is there any generic iteration function that stops at first match?

2021-03-04 Thread mipri via Digitalmars-d-learn

On Friday, 5 March 2021 at 05:32:27 UTC, Jack wrote:

On Friday, 5 March 2021 at 02:43:36 UTC, H. S. Teoh wrote:
On Fri, Mar 05, 2021 at 02:13:39AM +, Jack via 
Digitalmars-d-learn wrote:
something like filter[1] but that stops at first match? are 
there any native functions for this in D or I have to write 
one? just making sure to not reinvent the wheel

[...]

Why not just .front?  E.g.:

int[] data = [ 1,2,3,4,5 ];
auto r = data.filter!(v => v % 2 == 0);
assert(r.front == 2);


T


it loops over the entire array then returns, I'd like to stop 
as soon as the predicate return true


  void main() {
  import std.stdio, std.algorithm, std.range;
  int[] data = iota(5).map!"a+1".array;
  auto r = data.filter!(function (v) { writeln(v); return v % 
2 == 0; });

  assert(r.front == 2);
  }

output:

  1
  2

'r' is an iterator. To force it to loop over the entire array that
would need a .array like I'm using for 'data'.


Re: vibe.d / experience / feedback

2020-10-01 Thread mipri via Digitalmars-d-learn
On Thursday, 1 October 2020 at 06:32:23 UTC, Robert M. Münch 
wrote:
5. One can't access the raw HTTP request body, things must be 
go through Vibe's JSON parser. To get access to the raw body, a 
lot of workarounds are necessary.


given an HTTPServerRequest req,
req.bodyReader.readAll for binary data and .readAllUTF8 for text.



Re: preset counter variable in a for loop

2020-02-28 Thread mipri via Digitalmars-d-learn

On Friday, 28 February 2020 at 12:44:52 UTC, Namal wrote:

Hello,

I don't understand why this simple code causes a compiler 
error..


import std.stdio;

void main(){

 int b = 0;

 for (b; b<3; b++){
   writeln(b);  
 }
}

$Error: b has no effect


Well, that's the error. b has no effect, so there's
no need for it, and it's likely written in error. It
has no effect in C++ either, and you may get a warning:

example.cc: In function 'int main()':
example.cc:7:8: warning: statement has no effect [-Wunused-value]
  for (b; b<3; b++){



Re: Call method if declared only

2020-02-28 Thread mipri via Digitalmars-d-learn

On Friday, 28 February 2020 at 08:08:59 UTC, Виталий Фадеев wrote:

Searching for beauty readable code...


The pattern throughout Phobos is static tests, like isInputRange!R

So something like this:

  import std.stdio;
  import std.traits;

  template canOnKey(T) {
  static if (__traits(hasMember, T, "onKey"))
  enum canOnKey = isCallable!(__traits(getMember, T, 
"onKey"));

  else
  enum canOnKey = false;
  }

  struct A { void onKey() { writeln("called A"); } }
  struct B { }
  struct C { bool onKey = false; }

  void maybeKey(T)(T o) if (canOnKey!T) {
  o.onKey();
  }
  void maybeKey(T)(T o) if (!canOnKey!T) { }

  void main() {
  auto a = A(), b = B(), c = C();
  maybeKey(a);
  maybeKey(b);
  maybeKey(c);
  }

output:

  called A

(and no other output)

Of course in this exact instance it would be simpler to write

  void maybeKey(T)(T o) {
  static if (canOnKey!T)
  o.onKey();
  }

And rather than lots of specific hasThisExactMethod!T tests, it
might be nice if in your actual program there's a 'class' of
grouped properties that you can test for all at once, again
like isInputRange!T and friends.


Re: Question about the $ sign in arrays and strings

2020-02-19 Thread mipri via Digitalmars-d-learn

On Wednesday, 19 February 2020 at 07:49:36 UTC, Namal wrote:

oooh... I used

str = std.readln();

to get my string and there must have been some other sign, line 
break or whitespace or something at the end  :(


Now I understand it, thx


That makes sense. readln includes the newline:

$ echo hello | rdmd --eval 'readln.map!(std.uni.isWhite).writeln'
[false, false, false, false, false, true]

You can use std.string.chomp to drop it:

$ echo hello | rdmd --eval 
'readln.chomp.map!(std.uni.isWhite).writeln'

[false, false, false, false, false]



Re: Question about the $ sign in arrays and strings

2020-02-18 Thread mipri via Digitalmars-d-learn

On Wednesday, 19 February 2020 at 07:04:48 UTC, Namal wrote:
Hello, I wanted to remove the lastchar in a string and figured 
that you can do that wit


str = str[0..$-2];

but why is

str = str[0..$] and str=str[0..$-1]

the same ?


Why do you think that they are the same?

$ rdmd --eval 'auto str = "hello"; writeln(str = str[0..$]); 
writeln(str = str[0..$-1])'

hello
hell



Re: How to iterate over range two items at a time

2020-02-16 Thread mipri via Digitalmars-d-learn

On Monday, 17 February 2020 at 05:04:02 UTC, Adnan wrote:
What is the equivalent of Rust's chunks_exact()[1] method in D? 
I want to iterate over a spitted string two chunks at a time.



[1] 
https://doc.rust-lang.org/beta/std/primitive.slice.html#method.chunks_exact


And, after actually reading the Rust doc, I see that you want
to iterate over a string two chars at a time while discarding
any remaining 1-length chunk.

There isn't an equivalent of that.

A quick one is

auto chunks_exact(R)(R r, size_t n) {
return r.take(r.length - r.length%n).chunks(n);
}

but to get the exact same behavior you'll want to return a
range type that stores the final chunk.


Re: How to iterate over range two items at a time

2020-02-16 Thread mipri via Digitalmars-d-learn

On Monday, 17 February 2020 at 05:04:02 UTC, Adnan wrote:
What is the equivalent of Rust's chunks_exact()[1] method in D? 
I want to iterate over a spitted string two chunks at a time.



[1] 
https://doc.rust-lang.org/beta/std/primitive.slice.html#method.chunks_exact


$ rdmd --eval '"hello world".chunks(2).each!writeln'
he
ll
o
wo
rl
d

$ rdmd --eval '"hello 
world".chunks(2).map!"a.array.length".each!writeln'

2
2
2
2
2
1

Note the .array; each chunk is a range type.

$ rdmd --eval 'typeid("hello world".chunks(2).take(1)).writeln'
std.range.Take!(Chunks!string).Take



Re: How the hell to split multiple delims?

2020-02-15 Thread mipri via Digitalmars-d-learn

On Saturday, 15 February 2020 at 11:32:42 UTC, AlphaPurned wrote:
I've tried 10 different ways with split and splitter, I've used 
all the stuff that people have said online but nothing works. I 
always get a template mismatch error.


Why is something so easy to do so hard in D?

auto toks = std.regex.split(l, Regex("s"));
auto toks = std.regex.splitter(l, Regex("s"));
auto toks = std.regex.splitter(l, ctRegex!r"\.");


Why do you think this doesn't work? I'm not just asking this to
be rude. Your problem is likely in the rest of your code.

$ rdmd --eval 'split("the quick,brown:fox",regex("[ 
,:]")).writeln'

["the", "quick", "brown", "fox"]

$ rdmd --eval 'typeid(split("the quick,brown:fox",regex("[ 
,:]"))).writeln'

immutable(char)[][]

$ rdmd --eval 'splitter("the quick,brown:fox",regex("[ 
,:]")).writeln'

["the", "quick", "brown", "fox"]

$ rdmd --eval 'typeid(splitter("the quick,brown:fox",regex("[ 
,:]"))).writeln'

std.regex.Splitter!(cast(Flag)false, string, Regex!char).Splitter

That final value is a range type. Consider the guides
at the top of https://dlang.org/phobos/std_range.html
Ranges take a while to get comfortable with.


Re: Filling an associated array of associated arrays

2020-01-14 Thread mipri via Digitalmars-d-learn

On Tuesday, 14 January 2020 at 23:23:51 UTC, Jamie wrote:
I'm trying to initialise an associated array of associated 
arrays with values, taking the same approach I would for an 
associated array:


This works:

  import std.stdio;

  void main() {
  string[string][string] table = ([
  "info" : [
  "equation" : "H2 + I2 <=> 2HI",
  "type" : "elementary",
  ],
  "frc" : [
  "A" : "1.2e9",
  "n" : "1.2e9",
  "C" : "1.2e9",
  ],
  ]);
  writeln(table);
  }

c.f. https://issues.dlang.org/show_bug.cgi?id=17607

I found that by searching the forums for your error.


Re: Reading a file of words line by line

2020-01-14 Thread mipri via Digitalmars-d-learn

On Tuesday, 14 January 2020 at 16:39:16 UTC, mark wrote:
I can't help feeling that the foreach loop's block is rather 
more verbose than it could be?





WordSet words;
auto rx = ctRegex!(r"^[a-z]+", "i");
auto file = File(filename);
foreach (line; file.byLine) {
auto match = matchFirst(line, rx);
if (!match.empty()) {
	auto word = match.hit().to!string; // I hope this assumes 
UTF-8?

if (word.length == wordsize) {
words[word.toUpper] = 0;
}
}
}
return words;
}



One thing I picked up during Advent of Code last year was
std.file.slurp, which was great for reading 90% of the input
files from that contest. With that, I'd do this more like

  int[string] words;
  slurp!string("input.txt", "%s").each!(w => words[w] = 0);

Where "%s" is what slurp() expects to find on each line, and
'string' is the type it returns from that. With just a list of
words this isn't very interesting. Some of my uses from the
contest are:

  auto input = slurp!(int, int, int)(args[1], "z=%d>")

  .map!(p => Moon([p[0], p[1], p[2]])).array;

  Tuple!(string, string)[] input =
  slurp!(string, string)("input.txt", "%s)%s");

Of course if you want to validate the input as you're reading
it, you still have to do extra work, but it could be in a
.filter!



Re: Finding position of a value in an array

2019-12-30 Thread mipri via Digitalmars-d-learn

On Monday, 30 December 2019 at 19:46:50 UTC, Ron Tarrant wrote:

Thanks, mipri. Got it sorted. Here's a working proof...

```
import std.stdio;
import std.algorithm;
import std.conv;

void main(string[] args)
{
MyObject[] objectArray;
MyObject newObject;
MyObject findPointer;
long index;

int lastObjectID = 7;
int foundObjectIndex;

for(int i; i < 12; i++)
{
lastObjectID++;
newObject = new MyObject(lastObjectID);
objectArray ~= newObject;

if(i is 5)
{
findPointer = newObject;
}
}

for(int i; i < objectArray.length; i++)
{
		writeln("object: ", cast(MyObject*)objectArray[i], ", ID: ", 
objectArray[i].objectID);

}

index = objectArray.countUntil(findPointer);
	writeln("findPointer: ", findPointer, ", at address: ", 
cast(MyObject*)findPointer, " is a MyObject pointer in the 
objectArray with an index of ", index, ", address: ", 
cast(MyObject*)objectArray[index], ", ID: ", 
objectArray[index].objectID);


} // main()


class MyObject
{
int objectID;

this(int ordinal)
{
objectID = ordinal;

} // this()

} // class MyObject

```


Compare:

  import std.stdio;
  import std.algorithm;
  import std.conv;

  void main(string[] args)
  {
MyObject[] objectArray;
MyObject newObject;
MyObject findPointer;
long index;

int foundObjectIndex;

for(int i; i < 12; i++)
{
newObject = new MyObject();
objectArray ~= newObject;

if(i is 5)
{
findPointer = newObject;
}
}

for(int i; i < objectArray.length; i++)
{
writeln("object: ", cast(MyObject*)objectArray[i]);
}

index = objectArray.countUntil(findPointer);
  	writeln("findPointer: ", findPointer, ", at address: ", 
cast(MyObject*)findPointer, " is a MyObject pointer in the 
objectArray with an index of ", index, ", address: ", 
cast(MyObject*)objectArray[index]);


  } // main()


  class MyObject {}

With output:

  object: 7F2DC37C3000
  object: 7F2DC37C3020
  object: 7F2DC37C3030
  object: 7F2DC37C3040
  object: 7F2DC37C3050
  object: 7F2DC37C3060
  object: 7F2DC37C3070
  object: 7F2DC37C3080
  object: 7F2DC37C3090
  object: 7F2DC37C30A0
  object: 7F2DC37C30B0
  object: 7F2DC37C30C0
  findPointer: x297.MyObject, at address: 7F2DC37C3060 is a 
MyObject pointer in the objectArray with an index of 5, address: 
7F2DC37C3060




Re: Finding position of a value in an array

2019-12-30 Thread mipri via Digitalmars-d-learn

On Monday, 30 December 2019 at 19:08:27 UTC, Ron Tarrant wrote:
On Monday, 30 December 2019 at 17:12:26 UTC, MoonlightSentinel 
wrote:


D disallows implicit conversion from integers to pointers and 
hence they cannot be compared. You would need to explicitly 
cast your ulong to an appropriate pointer type


I'm not trying to convert, just wade through an array of 
pointers to find a specific pointer using searchUntil().


I mean, it's not a big deal if I can't do it.


You can definitely do it:

  $ rdmd --eval 'int a, b, c; [, , ].countUntil().writeln'
  2

But you need to have an array of pointers.


Re: Concatenation/joining strings together in a more readable way

2019-12-30 Thread mipri via Digitalmars-d-learn

On Monday, 30 December 2019 at 10:23:14 UTC, Marcone wrote:

On Monday, 30 December 2019 at 09:41:55 UTC, mipri wrote:



This leaks too much.

  writeln("Helo {} {}".format("xx", "name")); // Helo xx name
  writeln("Helo {} {}".format("{}", "name")); // Helo name {}


This function replace {} for arguments received. You just need 
don't send {} as arguments.

I tested native function format() in Python:
print("Helo {} {}".format("{}", "name")) # Helo {} name
Nothing wrong, working same way.


It doesn't work the same way. These are not the same:

  Helo name {}
  Helo {} name

Python's implementation doesn't get confused if your format()
arguments include a {}.


Re: Finding position of a value in an array

2019-12-30 Thread mipri via Digitalmars-d-learn

On Monday, 30 December 2019 at 14:30:12 UTC, Ron Tarrant wrote:
On Sunday, 29 December 2019 at 09:44:18 UTC, MoonlightSentinel 
wrote:



int i = a.countUntil(55);



I was trying to do this with an array of pointers, but I get an 
error (which suggests to me that I don't know what data type a 
pointer is):


find_in_array_object.d(25): Error: cannot cast expression 
newObject of type find_in_array_object.MyObject to ulong


What's your code? 'find_in_array_object.MyObject' doesn't look
like a pointer.


Re: Concatenation/joining strings together in a more readable way

2019-12-30 Thread mipri via Digitalmars-d-learn

On Monday, 30 December 2019 at 06:47:37 UTC, Marcone wrote:

Use Python format() style:

import std;
import std: Format = format;

// format()
string format(T...)(T text){
string texto = text[0];
foreach(count, i; text[1..$]){
texto = texto.replaceFirst("{}", to!string(i));
		texto = texto.replace("{%s}".Format(to!string(count)), 
to!string(i));

}
return texto;
}


This leaks too much.

  writeln("Helo {} {}".format("xx", "name")); // Helo xx name
  writeln("Helo {} {}".format("{}", "name")); // Helo name {}



Re: Finding position of a value in an array

2019-12-29 Thread mipri via Digitalmars-d-learn
On Sunday, 29 December 2019 at 08:26:58 UTC, Daren Scot Wilson 
wrote:
Reading documentation... Array, Algorithms, ... maybe I've been 
up too late... how does one obtain the index of, say, 55 in an 
array like this


int[] a = [77,66,55,44];

I want to do something like:

int i = a.find_value_returning_its_index(55);
assert(i==2)

I'm sure it's obvious but I'm not seeing it right now.


int i = a.countUntil!(v => v == 55);
assert(i == 2);

It might not be an obvious application of countUntil, but it's
listed at https://dlang.org/phobos/std_algorithm_searching.html


Re: How create a function that receive a function and run it in another threading?

2019-12-26 Thread mipri via Digitalmars-d-learn

On Friday, 27 December 2019 at 06:08:16 UTC, Marcone wrote:

import std;
import core.thread;

auto threading(lazy void fun){ return 
task!fun().executeInNewThread(); }


void main(){
threading(writeln("Hello World!"));
}


I want to create a function threading() to run some function in 
other threading, but I get this error bellow. How can I get 
success?



Error: static function Programa.threading.Task!(fun).Task.impl 
cannot access frame of function Programa.threading
Error: template instance `Programa.threading.Task!(fun)` error 
instantiating


This works:

import std;
import core.thread;

auto threading(void function() fun){ return 
task(fun).executeInNewThread(); }


void main(){
writeln("Main: ", thisTid);
threading({ writeln("Hello, ", thisTid); });
}



Re: Concatenation/joining strings together in a more readable way

2019-12-25 Thread mipri via Digitalmars-d-learn

On Wednesday, 25 December 2019 at 12:39:08 UTC, BoQsc wrote:

Are there any other ways to join two strings without Tilde ~
character?
I can't seems to find anything about Tilde character 
concatenation easily, nor the alternatives to it. Can someone

share some knowledge on this or at least point out useful
links/resources?


Huh?

For clarity I'm going to respond to some potential rewrites of
your question.


I don't think "foo" ~ "bar" is very readable. Can I use a
different syntax?


No. That's the syntax. Even if you customize it in your own
code, by overloading addition or the like, you'll still come
across it in other people's code. So I can only recommend that
you find some way to make it readable for you. Maybe use a
different or larger font? Maybe just get more familiar with it?

I don't think the syntax is likely to change.


Where can I find documentation for the ~ operator?


It's under 'expressions' in the spec:

https://dlang.org/spec/expression.html#cat_expressions


Is ~ the best way to join strings together? Can I use
something else?


You can use it to join arrays in general, including strings.
Depending on your use case you might prefer joiner()

https://dlang.org/phobos/std_algorithm_iteration.html#.joiner

in usage like

  assert(["many", "strings"].joiner("").array == "manystrings");

Or Appender, for many mutating appends to the same array:

https://dlang.org/phobos/std_array.html#Appender



Re: What would it take to bring preinstalled D language compiler in the major Linux Distributions?

2019-12-23 Thread mipri via Digitalmars-d-learn

On Monday, 23 December 2019 at 13:34:55 UTC, BoQsc wrote:
I would love to see D language available out of box in major 
Linux distributions and use without much care of installation. 
Anyone have a though about it? Was there any serious efforts to 
bring D language to Major distributions?


What do you consider to be a major distribution?

Fedora has all three compilers in default repositories.
The install script at https://dlang.org/download.html has
a dated version of gdc but is otherwise fairly painless.


Re: range code doesn't work for multi-array

2019-12-16 Thread mipri via Digitalmars-d-learn

On Tuesday, 17 December 2019 at 07:40:28 UTC, AlphaPurned wrote:


if arr is a single array the follow code works(removing [i]) 
but if it is a double array it fails. arr as type double[A][B]. 
arr[i] has type double[A].

v ~= arr[i].map!(a=>to!string(a)~",").join;

  with `Range = double[21]`
  must satisfy the following constraint:
`   isInputRange!(Unqual!Range)`


The problem isn't that it's a multi-array but that it's a
fixed-size array. As the error suggests: it complains about a
double[21], and not about a double[][]

Fixed size arrays you need to slice to make them valid input
ranges. (std.container.array is the same.)

At a terminal:

  $ rdmd --eval 'int[3] x; x.map!"a+1".writeln'
  ...
with Range = int[3]
whose parameters have the following constraints:

> isInputRange!(Unqual!Range)

Tip: not satisfied constraints are marked with >

  $ rdmd --eval 'int[3] x; x[].map!"a+1".writeln'
  [1, 1, 1]

Note the [] in x[].map



Re: D's equivalent List Comprehension

2019-12-13 Thread mipri via Digitalmars-d-learn

On Friday, 13 December 2019 at 15:20:02 UTC, Jesse Phillips wrote:

I had mentioned my take on list comprehension here:

https://forum.dlang.org/post/qslt0q$2dnb$1...@digitalmars.com#post-ycbohbqaygrgmidyhjma:40forum.dlang.org

However someone put together a more comprehensive tutorial of 
its power. So I took the opportunity to demonstrate the 
parallel in D.


https://dev.to/jessekphillips/list-comprehension-in-d-4hpi

D is like writing English. Wait I thought that was supposed to 
be Python, maybe I am thinking ruby.


It might help your blog posts to use drepl in your examples:

https://code.dlang.org/packages/drepl

A session:

$ dub -q run drepl
Welcome to D REPL.
D> import std;
std
D> iota(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
D> [2,45,21,45]
[2, 45, 21, 45]
D> [2,45,21,45].enumerate.assocArray
[0:2, 3:45, 2:21, 1:45]
D> iota(10).filter!(i => i % 2 == 0)
[0, 2, 4, 6, 8]
D>

Lines without a semicolon are expressions, whose values are
printed automatically. Lines with semicolons can import stuff,
declare variables, define new functions, etc. Serious current
limitations are: it's not aware of dub and can't import dub
packages, and it can't parse dstyle braces.



Re: How add "version.txt" Version File by Command Line or by resources.res using dmd.exe

2019-12-08 Thread mipri via Digitalmars-d-learn

On Sunday, 8 December 2019 at 20:50:05 UTC, Marcone wrote:

I want to add version to my program.
I have configurated my version file "version.txt",  but I dont 
know how link this file to my program. If Need spec file, 
please send the exemple code of spec. Or is is possible add 
version file by dmd command line or resources. Thank you.


I'm not sure I know what you're asking, but maybe this is
the answer.

In version.txt:

  0.1.0 - a version example

In version.d:

  import std.string : chomp;

  immutable Version = import("version.txt").chomp;

  void main() {
  import std.stdio : writeln;
  writeln("Version: ", Version);
  }

To compile and run with both files in the current directory:

  dmd -J. -run version

With output:

  Version: 0.1.0 - a version example

The corresponding dub setting is probably stringImportPaths


Re: Are there any DUB packages for displaying an ascii table?

2019-12-08 Thread mipri via Digitalmars-d-learn

On Sunday, 8 December 2019 at 08:01:32 UTC, Soulsbane wrote:
Been playing with Golang lately and it has quite a few modules 
for terminal tables. For example this one: 
github.com/brettski/go-termtables.


Is there a D equivalent package? Can't seem to find any via 
search(which by the ways seems to give bad results or I just 
can't find the right word to search with).


Thanks!


This exists and was updated as recently as the first of December:

https://code.dlang.org/packages/asciitable

I don't see any other dub packages that look related.


Re: Populating nested AAs; "This wouldn't be so verbose in Ada 2020"

2019-12-07 Thread mipri via Digitalmars-d-learn

On Sunday, 8 December 2019 at 06:42:22 UTC, Paul Backus wrote:

You can use the `require` function [1] for this:

with (userHistory.require(host).require(user)) {
if (isOk) ++ok; // renamed to avoid shadowing
else ++evil;
}

Many "methods" for built-in AAs are located in the `object` 
module. It makes them a bit tricky to find in the 
documentation, if you don't already know they're there.


https://dlang.org/phobos/object.html#.require


Thanks! I wasn't aware of the 'object' doc. Looks like the
language documentation does mention require() in "Inserting if
not present", but combining it with 'with' is a neat trick.



Populating nested AAs; "This wouldn't be so verbose in Ada 2020"

2019-12-07 Thread mipri via Digitalmars-d-learn

Hello,

I've got this code:

  struct UserStats {
int ok, evil;
  }

  // module-level variable
  UserStats[string][string] userHistory;

and this code that populates it:

  // loop over DB query

  if (host !in userHistory)
  userHistory[host] = typeof(userHistory[host]).init;

  if (user !in userHistory[host])
  userHistory[host][user] = 
typeof(userHistory[host][user]).init;


  if (ok) ++userHistory[host][user].ok;
  else ++userHistory[host][user].evil;

The joke of the thread title is that in pseudo-Ada2020, those
assignments would look like

  User_History (host) = typeof (@).init;
  User_History (host) (user) = typeof (@).init;

as @ is a shortcut for the left hand side of an assignment.
It's what Ada has instead of += and friends.

Of course, I don't propose that @ be added to D; I just want to
know if there's a good idiom for new assignments to nested AAs
like this. A nice alternative for my specific use is

  struct UserStats {
static int[Tuple!(string, string)] ok, evil;
  }

and

  // loop over DB query
  if (ok) ++UserStats.ok[tuple(host, user)];
  else ++UserStats.evil[tuple(host, user)];

But of course this would be less convenient if f.e. I wanted to
pattern my data structures after a JSON production result.



Re: Using map result type

2019-12-07 Thread mipri via Digitalmars-d-learn

On Sunday, 8 December 2019 at 01:10:21 UTC, AA wrote:

I'd like to accept the return type of map. From some previous
questions that I should accept a template?


In general this is what you want to do with any kind of range
code, because you're not working with definite types, but with
types that have certain properties. And an advantage of this is
that you can decide to do more or less efficient things at
compile time based on additional properties of the types you're
working with. Just open up phobos and look for 'static if':

https://github.com/dlang/phobos/blob/master/std/algorithm/searching.d#L3858

So if you you give minPos an array, it'll just foreach() over
the array and return a slice. In which case minPos is exactly
as efficient as the code you would've written by hand instead
of using minPos, because it expands to that same code.

And if you give minPos something else, it'll still work.


So for something like:

```
void mapAccepter(Range)(Range r)
{
import std.array : array;
import std.stdio : writeln;

auto collected = r.array;
writeln(collected);
}

void main()
{
import std.algorithm.iteration : map;

int[] nums = [1, 2, 3];
auto evenness = map!(n => n % 2 == 0)(nums);
mapAccepter(evenness);
}
```



1) Is there any way I can make `mapAccepter` not a templated
function?


Not really. Even if you try to use typeof() to get the
(internal) type that std.alogorithm.map returns, you'll run
into errors like

Error: function x253.mapAccepter(MapResult!(__lambda5, int[]) r) 
is not callable using argument types (MapResult!(__lambda1, 
int[]))


when you try to use it.


2) Is there any way if I need to make `mapAccepter` templated
to constrain Range to be a range of booleans.


Certainly. Static reflection's what this kind of generic code
is all about. See all the constraints in the std.algorithm pages
in the library documentation?  Just look at this one, randomly
picked:
https://dlang.org/phobos/std_algorithm_searching.html#.endsWith

  if (isBidirectionalRange!Range
  && (Needles.length > 1)
  && is(typeof(.endsWith!pred(doesThisEnd, 
withOneOfThese[0])) : bool)
  && is(typeof(.endsWith!pred(doesThisEnd, 
withOneOfThese[1..$])) : uint));


So for your code:

  void mapAccepter(Range)(Range r)
  if (is(ElementType!Range == bool))
  {
  import std.array : array;
  import std.stdio : writeln;

  auto collected = r.array;
  writeln(collected);
  }

Or if you do this often, maybe something like this would do:

  enum RangeOfBools(T) = is(ElementType!T == bool) && 
isInputRange!T;


  void mapAccepter(Range)(Range r) if (RangeOfBools!Range)
  {
  import std.array : array;
  import std.stdio : writeln;

  auto collected = r.array;
  writeln(collected);
  }



Re: How to invert bool false/true in alias compose?

2019-12-06 Thread mipri via Digitalmars-d-learn

On Saturday, 7 December 2019 at 04:00:53 UTC, Marcone wrote:

import std;

alias cmd = compose!(to!bool, wait, spawnShell, to!string);

void main(){
writeln(cmd("where notepad.exe"));
}


Result:

C:\Windows\System32\notepad.exe
C:\Windows\notepad.exe
false


The result show "false" because good spawnshell command return 
0 and 0 to bool is false. But I want to invert false to true to 
get true or false if command success.


These all work:

alias cmd = compose!(unaryFun!"!a", to!bool, wait, spawnShell, 
to!string);


alias cmd = compose!("!a", to!bool, wait, spawnShell, to!string);

alias cmd = compose!(b => !b, to!bool, wait, spawnShell, 
to!string);




Re: Unexpectedly nice case of auto return type

2019-12-06 Thread mipri via Digitalmars-d-learn

On Friday, 6 December 2019 at 23:25:30 UTC, Johannes Loher wrote:

On Tuesday, 3 December 2019 at 10:06:22 UTC, Mike Parker wrote:

On Tuesday, 3 December 2019 at 10:03:22 UTC, Basile B. wrote:



That's interesting details of D developement. Since you reply 
to the first message I think you have not followed but in the 
last reply I told that maybe we should be able to name the 
type of null. I think this relates to TBottom too a bit.


https://github.com/dlang/DIPs/blob/40352337053998885fbd0fe2718c300a322d3996/DIPs/DIP1NNN-DK.md


This is everything I wished for. It basically exactly resembles 
the results of the lengthy discussion H. S. Theo and I had in 
the review thread for Walter‘s original bottom type suggestion. 
And it even covers a few additional details we had not thought 
about. I can’t wait for this DIP to go into review. Thanks a 
lot to the DIP author. You have my biggest respect for writing 
a fleshed out proposal of this!


nice.

Kotlin has this as well, with Unit as void and Nothing as
noreturn.

So for example this compiles without complaint:

  fun infinite(f: () -> Unit) {
  while (true) {
  f()
  }
  }

  fun main() {
  infinite { println(".") }
  println("goodbye")
  }

Where 'infinite' has an implcit Unit return type, but this
warns that the "goodbye" will never happen:

  fun infinite(f: () -> Unit): Nothing {
  while (true) {
  f()
  }
  }

  fun main() {
  infinite { println(".") }
  println("goodbye")
  }

This might be more important for resources that never get
closed, or secrets are never scrubbed from memory, due to
someone putting those tasks after a function like 'infinite'
without noticing.

... noreturn local variables are pretty gross, though.



Re: Unexpectedly nice case of auto return type

2019-12-03 Thread mipri via Digitalmars-d-learn

On Tuesday, 3 December 2019 at 10:13:30 UTC, mipri wrote:

Speaking of nice stuff and aliases, suppose you want to
return a nice tuple with named elements?

Option 1: auto

  auto option1() {
  return tuple!(int, "apples", int, "oranges")(1, 2);
  }

Option 2: redundancy

  Tuple!(int, "apples", int, "oranges") option2() {
  return tuple!(int, "apples", int, "oranges")(1, 2);
  }

Option 3: an alias

  alias BadMath = Tuple!(int, "apples", int, "oranges");

  BadMath option3() {
  return BadMath(1, 2);
  }


Option 4: typeof(return)

  Tuple!(int, "apples", int, "oranges") option4() {
  return typeof(return)(1, 2);
  }



Re: Intersection of two sets

2019-12-03 Thread mipri via Digitalmars-d-learn

On Tuesday, 3 December 2019 at 18:45:18 UTC, Jan Hönig wrote:

On Tuesday, 3 December 2019 at 13:55:51 UTC, Alex wrote:


This depends on the available accesses on your sets. In terms 
of ranges:

Are your sets InputRanges, ForwardRange, ... ?



2) Are there some build-in function for handling such sets?


This is maybe what you are looking for: 
https://dlang.org/phobos/std_algorithm_setops.html


In terms of ranges, i need to understand ranges properly first.


The top of https://dlang.org/phobos/std_range.html has some
talks and tutorials to consider.

The std.algorithm.setops have definitely the functionality i 
need.

I guess my current implementation would be a simple array.
I just need to make sure delete, or not create double entries.


A problem with the unittest examples is that they assume the
reader is very familiar with the language :) Here are some
things to keep in mind with setIntersection:

1. setIntersection expects its inputs to be sorted. If they
aren't, it doesn't notice; you just don't get the behavior you
want.

  int[] a = [4, 2, 3, 1], b = [8, 4, 2, 6];

  assert(setIntersection(a, b).array == []); // !
  assert(setIntersection(a.sort, b.sort).array == [2, 4]);

2. setIntersection returns a range, not an array. This probably
lets you return the infinite intersections of two infinite
ranges, for example. If you're looking at this for Advent of
Code you'll probably want to pass the intersections through
some other operators that will accept a range.

(Also, sort mutates *and* returns the array. if you're
depending on the positions of 2 and 4 in the original arrays,
you should get the intersection of a sorted copy of them.)

In general, pay attention to the static constraints:

  if (Rs.length >= 2 && allSatisfy!(isInputRange, Rs) &&
  !is(CommonType!(staticMap!(ElementType, Rs)) == void));

In English:

1. if you're getting an intersection of ranges, you need to
provide at least two ranges.

2. all of the ranges need to be input ranges

3. the ranges' element types need to have a common type that
isn't 'void'.

You can use these same constraints in your code if you're not
sure if they apply

static assert (isInputRange!(typeof(a)));
assert(setIntersection(a, b).array == []);

or you can test them interactively:

  $ rdmd --eval 'isInputRange!(typeof([1, 2, 3])).writeln'
  true

And you can also check on their documentation and see if it's
what you expect:

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

D doesn't have 500+ line errors for the simplest template
misuse like C does, but its much shorter template error
messages still could be friendlier. Usually they're in terms of
these constraints, or you've a more basic error like having a
range type (like the SetIntersection struct that
setIntersection actually returns) where some other code expects
a simple array, or vice versa.



Re: Unexpectedly nice case of auto return type

2019-12-03 Thread mipri via Digitalmars-d-learn

On Tuesday, 3 December 2019 at 10:02:47 UTC, Andrea Fontana wrote:

On Tuesday, 3 December 2019 at 09:48:39 UTC, Basile B. wrote:
You see what surprises me here is that we cannot express the 
special type that is `TypeNull` and that can only have one 
value (`null`) so instead we have to use `auto` or 
`typeof(null)`.


You can still create an alias anyway :)

alias TypeNull = typeof(null);


Speaking of nice stuff and aliases, suppose you want to
return a nice tuple with named elements?

Option 1: auto

  auto option1() {
  return tuple!(int, "apples", int, "oranges")(1, 2);
  }

Option 2: redundancy

  Tuple!(int, "apples", int, "oranges") option2() {
  return tuple!(int, "apples", int, "oranges")(1, 2);
  }

Option 3: an alias

  alias BadMath = Tuple!(int, "apples", int, "oranges");

  BadMath option3() {
  return BadMath(1, 2);
  }

It wasn't obvious to me that BadMath(...) would work.
It *should* be obvious since this also works:

  ...
  return Tuple!(int, "apples", int, "oranges")(1, 2);

But the convenience of tuple() helped to  mask that.

I was going with silly stuff like

  ...
  return cast(BadMath) tuple(1, 2);



Re: Floating-Point arithmetic in dlang - Difference to other languages

2019-12-03 Thread mipri via Digitalmars-d-learn

On Tuesday, 3 December 2019 at 09:22:49 UTC, Jan Hönig wrote:
Today i have stumbled on Hacker News into: 
https://0.30004.com/


I am learning D, that's why i have to ask.

Why does

writefln("%.17f", .1+.2);

not evaluate into: 0.30004, like C++
but rather to: 0.2

Many other languages evaluate to 0.30004 as well.


You can get this result in D as well:

  $ rdmd --eval 'double a = .1, b = .2; writefln("%.17f", a+b)'
  0.30004

https://dlang.org/spec/float.html explains it: real (80bit,
'long double' in C) floats are used in your first calculation,
and doubles are used in my revised example.

Most other languages give you the double result for very
reasonable historical reasons, described here:
https://retrocomputing.stackexchange.com/questions/9751/did-any-compiler-fully-use-intel-x87-80-bit-floating-point/9760#9760

D's behavior is a minor 'miss': https://nwcpp.org/Oct-2019.html

... I wanted to include a C example that gives the D result,
but it seems to be trickier to force 80 bit intermediates.


Re: how to implement a function in a different D source file

2019-11-25 Thread mipri via Digitalmars-d-learn

On Tuesday, 26 November 2019 at 03:06:52 UTC, Omar wrote:

the page here https://dlang.org/spec/function.html
suggests you can implement a function in a different file

...
mentioned the endeavour of no-bodied-functions as a way of 
presenting a black-box type of interface.


oh, that's what you were asking.

Consider:

  $ cat interface/references.d
  module references;

  string greeting();

  $ cat implementation/references.d
  module references;

  string greeting() {
  return "Hello, Dave";
  }

  $ cat main.d
  import references;

  void main() {
  import std.stdio: writeln;
  writeln(greeting);
  }

And trying to build it:

  $ dmd -c implementation/references.d
  $ dmd -Iinterface -c main.d
  $ dmd main.o references.o
  $ ./main
  Hello, Dave



Re: how to implement a function in a different D source file

2019-11-25 Thread mipri via Digitalmars-d-learn

On Tuesday, 26 November 2019 at 03:06:52 UTC, Omar wrote:
Hey, I'm very interested in this programming language, I 
already prefer it to C++ and if only i had adopted it years 
ago, but that's beside the point.


I read a bunch of tuts today and the only thing I'm really 
stuck on at the moment is how to actually implement a function 
in a different file.


the page here https://dlang.org/spec/function.html
suggests you can implement a function in a different file, and 
a different tutorial somewhere else (or maybe the same site or 
even same page idr) mentioned the endeavour of 
no-bodied-functions as a way of presenting a black-box type of 
interface.


But with the whole module namespace thing I'm a bit at a loss 
how to do this.
Say I have main.d ex.d and ex2.d and I want to import ex, and 
call a function it
declares, and implement the function in ex2.d and link the 
objects at the end so the linker is happy. I don't know how to 
do this and I can't find a straigh answer anywhere or any 
examples.


so ?


First, here's exactly what you're asking for:

  $ cat ex1.d
  enum string admin = "Dave";

  $ cat ex2.d
  import ex1;

  string greeting() {
  return "Hello, " ~ admin;
  }

  $ cat main.d
  import ex2;

  void main() {
  import std.stdio: writeln;
  writeln(greeting);
  }

Three files that all import what they need, and can be
compiled separately and then linked.

  $ dmd -c ex1
  $ dmd -c ex2
  $ dmd -c main
  $ dmd -ofmain main.o ex2.o ex1.o
  $ ./main
  Hello, Dave

And dmd isn't cheating, as you can see by skipping the first
two compiles:

  $ rm *.o
  $ dmd -c main
  $ dmd -ofmain main.o
  /usr/bin/ld: main.o: in function `_Dmain':
  main.d:(.text._Dmain[_Dmain]+0x5): undefined reference to 
`_D3ex28greetingFZAya'

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

But you could also just compile everything together:

  $ rm *.o
  $ dmd -ofmain *.d
  $ ./main
  Hello, Dave

If all of your code is in D, my received understanding is that
this is a completely reasonable option.

You could also use dub as your build system:

  Package recipe format (sdl/json) [json]:
  Name [main]:
  Description [A minimal D application.]:
  Author name [mipri]:
  License [proprietary]: MIT
  Copyright string [Copyright © 2019, mipri]:
  Add dependency (leave empty to skip) []:

This'll create a new directory named 'main', and you can build
and run a 'hello world' by running 'dub'.

After moving some files around...

  $ cat source/movie/references/names.d
  module movie.references.names;

  enum string admin = "Dave";

  $ cat source/movie/references/lines.d
  module movie.references.lines;

  string cantDoThat() {
  import movie.references.names: admin;
  return "I'm afraid I can't do that, " ~ admin;
  }

  $ cat source/app.d
  void main() {
  import movie.references.lines: cantDoThat;
  import std.stdio: writeln;
  writeln(cantDoThat);
  }

Building and running it:

  $ dub
  Performing "debug" build using dmd for x86_64.
  main ~master: building configuration "application"...
  Linking...
  Running ./main
  I'm afraid I can't do that, Dave




Re: Leak-detection of references to scoped class instances

2019-11-25 Thread mipri via Digitalmars-d-learn

On Monday, 25 November 2019 at 12:08:54 UTC, Per Nordlöw wrote:
On Monday, 25 November 2019 at 08:22:02 UTC, Jacob Carlborg 
wrote:

On Sunday, 24 November 2019 at 21:49:19 UTC, Per Nordlöw wrote:
I guess we need a builtin language qualifier for scoped 
classes for that to work, right?


We have that:

scope a = new Object;

—
/Jacob Carlborg


Ahh, nice.

Does/Will DMD/GDC/LDC (in release builds) make the allocation 
of `Object` happen on the stack?


class C {
int x;
this(int n) { x = n; }
}

int heap() {
auto x = new C(2); // vgc: `new` causes a GC allocation
return x.x;
}
/+
int example.heap():
sub rsp, 8
mov edi, OFFSET FLAT:example.C.__Class
call_d_newclass
mov DWORD PTR [rax+16], 2
mov eax, 2
add rsp, 8
ret
+/

int stack() {
scope x = new C(2); // (no vgc output)
return x.x;
}
/+
int example.stack():
sub rsp, 40
mov rdi, rsp
mov QWORD PTR [rsp], OFFSET FLAT:example.C.__vtbl
mov QWORD PTR [rsp+8], 0
mov DWORD PTR [rsp+16], 2
call_d_callfinalizer
mov eax, 2
add rsp, 40
ret
+/

gdc assembly. ldc eliminates the object entirely.


Re: How to wait for a shell process to finish on ctrl+c before exiting?

2019-11-24 Thread mipri via Digitalmars-d-learn

On Sunday, 24 November 2019 at 15:44:00 UTC, aliak wrote:
I'm writing some command line tooling stuff, and one of the 
command spins up a docker compose file (which in short, spins 
up some services and aggregates the output of each service to 
stdout).


When a user presses ctrl+c, i would like to pass on the ctrl+c 
to the spawned process and wait till it handles ctrl+c and then 
let go of the current process.


This might be useful:
---
#! /usr/bin/env rdmd
import std;
import core.stdc.signal;

int spawnedPid;

extern(C) int kill(int pid, int sig) nothrow @nogc @system;
extern (C) int waitpid(int pid, int* status, int options) nothrow 
@nogc @system;


extern(C) void interruptHandler(int sig) nothrow @nogc @system {
kill(spawnedPid, SIGTERM);
waitpid(spawnedPid, null, 0);
}

int spawnProcessAndWait(string[] cmd) {
auto pid = spawnProcess(cmd, stdin, stdout, stderr);
spawnedPid = pid.processID;
signal(SIGINT, );
int result = wait(pid);
return result;
}

void main() {
spawnProcessAndWait(["perl", "-le", "$SIG{INT} = sub { print 
'Ignoring interrupt' }; $SIG{TERM} = sub { print 'Got'; sleep 2; 
print 'Term' }; print 'Go'; sleep 10"]);

}
---

I don't just using this code, but running this and seeing how
it behaves. For example, you might be surprised by the output
if you hit control-C as soon as you see the "Go":

---
Go
^CIgnoring interrupt
Got
Term
---
with a 2s delay after 'Got'.

Or this output if you remove the Perl $SIG{INT} assignment:

---
Go
^C
---
with you dropped right back to the shell.


It's also possible to cause this code to exit with an exception
from the wait(), because there's no process for it wait for.


Re: What is the best way to program over "abstract" types in D?

2019-11-23 Thread mipri via Digitalmars-d-learn
On Saturday, 23 November 2019 at 21:52:40 UTC, Adam D. Ruppe 
wrote:
On Saturday, 23 November 2019 at 20:22:44 UTC, Ola Fosheim 
Grøstad wrote:

I guess it is possible to use introspection somehow?


Yeah, you have to write a function that checks it with 
introspection and then static assert on it somewhere.


This is a little bit better. What it's still missing is
a "there's a function with the same signature as this
other function, s/type1/type2/" kinda check.


abstract class Named {
string name();
}

template isNamed(alias T) {
import std.traits: hasUDA;

enum isNamed = hasUDA!(T, Named);
static if (isNamed) {
static foreach (f; __traits(getVirtualFunctions, Named, 
"name")) {

static assert(__traits(compiles, name(T(;
//static assert(__traits(compiles, f(T(;
}
}
}

string greet(T)(T x) if (isNamed!T) {
return "Hello " ~ x.name;
}
string greet(T)(T x) if (!isNamed!T) {
return "Hello?";
}

@Named struct World {};
struct Alice {};
@Named struct Bob {};

string name(World x) { return "World"; }
string name(Alice x) { return "Alice"; }
string name(Bob x) { return "Bob"; }

void main() {
import std.stdio: writeln;

writeln(greet(World()));
writeln(greet(Alice()));
writeln(greet(Bob()));
}



Re: What is the best way to program over "abstract" types in D?

2019-11-23 Thread mipri via Digitalmars-d-learn
On Saturday, 23 November 2019 at 11:21:32 UTC, Ola Fosheim 
Grøstad wrote:

...


I read your question as "can I have typeclasses in D?"

I'll refer to typeclasses in a language other than Rust. You
don't need to know the language. I think you knowing Rust at
all might be clouding your vision, actually.

First, you have some definition of the typeclass:

  :- typeclass named(T) where [
  func name(T) = string
  ].

In English: a type T is a named(T) if there's a function
'name' that accepts a T and returns a string.

This definition might appear in a module with a bunch of
functions that operate on named(T), like

  :- func greeting(T) <= (named(T)).
  greeting(W) = "Hello, " ++ name(W).

This is a function that accepts a value of a type T (provided
that T is named) and then returns the concatenated string. This
looks an awful lot like OOP, but there's no runtime dispatch,
and there are no objects -- indeed, the type could be a
primitive type like int, or float. The exact 'name()' function
that gets called is statically determined.

Finally, there are declarations that some types are, in fact,
instances of the typeclass.

  :- type world ---> world.

  :- instance named(world) where [
  name(world) = "World"
  ].

  :- instance named(int) where [
  name(X) = "Anonymous Integer".
  ]. % (yes, all ints have the same name)

These might appear in completely different modules with their
own unrelated code, written by other people, at a later time,
and with this instance declaration, when the whole program is
compiled together, some integers or the 'world' abstract type
might be handled by a lot of code that only knows that it can
call some name() function to get a string. This code did not
need to be edited to add a 'world' case to a switch to provide
this functionality.

If you're thirsty when by a river you might drink from the
river. If you're thirsty when by a soda machine you might buy a
Coke. But rivers are not made of soda. People using FP
languages reach for typeclasses and people using OOP languages
reach for class hierarchies in the same kinds of situations,
even if there are enormous differences in the exact outcome.

One difference as you noted is that none of the name() calls
is virtual in the typeclass case.

So, what would you need for typeclasses in D? You need all the
same parts: a static declaration of some kind of typeclass, a
static restriction of functions to apply to the typeclass, and
static registration of types to the typeclass.

At least, you need all these parts if you want the same kind of
nice user interface, where invalid registrations are rejected
in a timely manner. Here's a hack, instead:

Typeclass declaration? There isn't one.

Maybe there's documentation:

  /+ Named(T)

 string name(T x);  // define me
  +/

Typeclass restriction? It looks for a magic member. You let
people into the building because they each came in with their
own badge and the badge looks right; you didn't consult a
filing cabinet containing descriptions of all the people
allowed in the building. You still accomplished the goal.
With some caveats: the filing cabinet might've said "cats can
come in too", but cats cannot show a badge. Likewise primitive
types like ints and floats can't be given static members.

  template isNamed(alias T) {
  enum isNamed = hasStaticMember!(T, "secretlyIsNamed");
  }

As used:

  string greet(T)(T x) if (isNamed!T) {
  return "Hello " ~ x.name;
  }

Typeclass registration? Add the member to your types. These
types have no other information to them:

  struct World {
static char[0] secretlyIsNamed;
  }

  struct Bob {
static char[0] secretlyIsNamed;
  }

And then of course, define the required functions:

  string name(Bob x) { return "Bob"; }

  string name(World x) { return "World"; }

And then you can call them with static dispatch:

  void main() {
writeln(greet(World()));
writeln(greet(Bob()));
  }


This all really works. You get your static polymorphism. The
compiler doesn't let you forget a name() function (if you try
to use it). You have generic code in a library that can be
reused with different types provided by users of the library.

But because it's a hack, there are some unwanted outcomes.
First, other parts of the language can see these
secretlyIsNamed members, and that might cause problems.
They're not really secret. Second, negative typeclasses are not
possible in FP langs, but we have them here:

  string greet(T)(T x) if (!isNamed!T) {
return "Hello???";
  }

Third, not only can't we register primitive types into
typeclasses like this, we also can't register any type that
already exists or that's provided by third party code. In an FP
lang you could import a serialization module, import some kind
of special container from another module, and then in your own
code say, "special containers are serializeable too and this is
how they should be serialized", even though neither of the
module authors were aware of the 

Re: Spawning a process, then killing it on SIGINT

2019-11-23 Thread mipri via Digitalmars-d-learn

On Saturday, 23 November 2019 at 09:54:48 UTC, aliak wrote:
Is there a way to go about killing a process after spawning it 
on a SIGINT?


I can't do this for e.g. because kill is not @nogc.


Well, this works:

import std;
import core.stdc.signal;

extern(C) int kill(int pid, int sig) nothrow @nogc @system;

int currentSpawnedPid;
extern(C) void killCurrentPidHandler(int sig) nothrow @nogc 
@system {

  if (currentSpawnedPid > 1)
kill(currentSpawnedPid, sig);
}

int main() {
  auto pid = spawnProcess(["sleep", "50s"], stdin, stdout, 
stderr);

  currentSpawnedPid = pid.processID;
  signal(SIGINT, );
  return wait(pid);
}



Re: How to simulate Window's "Press any key to continue..."

2019-11-21 Thread mipri via Digitalmars-d-learn

On Friday, 22 November 2019 at 04:41:30 UTC, mipri wrote:

~this() { reset(); }


Oh, if you don't ever call raw() this will break your terminal.
I just copied some code from a toy program and adapted it, and
didn't notice that until I posted.





Re: How to simulate Window's "Press any key to continue..."

2019-11-21 Thread mipri via Digitalmars-d-learn
On Friday, 22 November 2019 at 04:22:07 UTC, FireController#1847 
wrote:
Right, but readln will only wait until the user presses the 
delimiter (by default Enter/Return). I want it to wait until 
ANY key is pressed, not a specific key


If curses is available you can use it, at the cost of completely
changing how you do I/O (in a good way if you need lots of
updates):

#! /usr/bin/env dub
/+ dub.sdl:
dependency "nice-curses" version="~>0.2.5"
+/
import std.stdio;
import nice.curses: Curses;

void main() {
auto curses = new Curses;
auto scr = curses.stdscr;

curses.setCursor(0);
scr.addstr("Press any key to continue...");
scr.refresh;
curses.update;
scr.getch;
}

If you really just briefly want getch-style input in a normal
terminal program, and still have a posix system, you can do that
with tcsetattr.

https://stackoverflow.com/questions/7469139/what-is-the-equivalent-to-getch-getche-in-linux

struct Terminal {
import core.stdc.stdio: getchar;
import core.sys.posix.termios:
tcgetattr, tcsetattr, termios,
ECHO, ICANON, TCSANOW, TCSAFLUSH;
private termios last;

int getch() { return getchar(); }

int getch_once() {
raw;
auto r = getchar;
reset;
return r;
}

void raw() {
termios term;
tcgetattr(0, );
term = last;
term.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0, TCSANOW, );
}

void reset() { tcsetattr(0, TCSAFLUSH, ); }

~this() { reset(); }
}

void main() {
import std.stdio: write, writeln;
Terminal term;

write("Press any key to continue:");
term.getch_once();
writeln;
}



Re: How to simulate Window's "Press any key to continue..."

2019-11-21 Thread mipri via Digitalmars-d-learn
On Friday, 22 November 2019 at 04:10:23 UTC, FireController#1847 
wrote:
I'm an extreme beginner to DLang (just started using it.. oh, 
an hour ago?), and I already can't figure out a, what I'd 
consider, fairly simplistic thing.


This is my current code:

module DTestApp1;

import std.stdio;

int main() {
write("Press any key to continue...");
stdin.read();
return 0;
}

I am using Visual Studio to write it, and no matter what I do I 
cannot get it to work. I attempted to import std.stream;, but 
it said that while it could find the file, it cannot be read. 
Am I using the wrong function?


For those who don't know, what I'm trying to do is pause the 
program until literally any key is pressed while in the console.


The error doesn't suggest the right replacement, but it still
tells you that the function you want isn't available:

./test.d(6): Error: no property read for type File, did you mean 
std.stdio.File.readf(alias format, Data...)(auto ref Data data) 
if (isSomeString!(typeof(format)))?


std.stdio's documentation is here: 
https://dlang.org/phobos/std_stdio.html


and readln is a function you can use for your purpose.

  stdin.readln();

Or just:

  readln;




Re: The effect of ref

2019-11-21 Thread mipri via Digitalmars-d-learn

On Friday, 22 November 2019 at 03:42:26 UTC, dokutoku wrote:
Is there a difference in the execution speed and stability when 
executing the program by rewriting the parameter of the 
function argument like this?



```d
void test1 (int * X)
{
// some processing
}

void test2 (ref int X)
{
// some processing
}
```


The Compiler Explorer supports D, so it's a good way to
ask these questions.

https://godbolt.org/z/gnR6Eu

int example.test1(int*):
mov eax, DWORD PTR [rdi]
imuleax, eax
add eax, 1
ret
int example.test2(ref int):
mov eax, DWORD PTR [rdi]
imuleax, eax
add eax, 1
ret


Re: How to get child class Type and members from parent class?

2019-11-20 Thread mipri via Digitalmars-d-learn

On Wednesday, 20 November 2019 at 10:05:11 UTC, zoujiaqing wrote:

import std.stdio;


class A
{
this(T)(T t)
{

}

void write()
{
T _this = cast(T) this;
writeln(this.v);


Here, class A knows that a 'v' member is present. So why not just
put that member in class A, and let B inherit it?  If this method
won't apply to some other child classes, you can have an
intermediate class that adds the v member and specializes this
method to use it, and all the v children can inherit from A 
through

that intermediary.

I think what you're wanting to do is a reversal of OO design.
Maybe you can use proper OO instead, or maybe you'd prefer a
discriminated union if different children will have different 
types

for v. Like in an FP lang: https://github.com/pbackus/sumtype


}
}

class B : A
{
string v = "hello";
}

void main()
{
auto b = new B;

writeln(b.write()); // print hello
}





Re: What is the replacement for deprecated array removal

2019-11-18 Thread mipri via Digitalmars-d-learn

On Monday, 18 November 2019 at 21:25:12 UTC, kerdemdemir wrote:
It is a bit weird that such a general case like removing list 
of elements does not work.


And I really do not know the real use of 
[0,1,2,3].remove(1,2,3). I mean in unit test it looks cool but 
in real life you will have dynamically calculated indexes.


Erdem


It seems like a defect in phobos to me as well. Fortunately phobos
is written in D so you can just copy this into your code:
https://github.com/dlang/phobos/blob/master/std/algorithm/mutation.d#L2160

however, it still doesn't return the same thing as 
x.remove(1,2,3).


... maybe it'd be simpler to drop down to C-style D?

// no checks for out-of-bounds or unsorted offsets
void myRemove(ref int[] array, int[] offsets) {
int from, to, offset;

while (from < array.length) {
if (offset < offsets.length && from == offsets[offset]) {
++offset;
++from;
} else if (from == to) {
++to;
++from;
} else {
array[to++] = array[from++];
}
}
array.length = to;
}

unittest {
int[] x = [1, 2, 3];
int[] y = x.dup, z = x.dup, q = x.dup;
myRemove(x, [0]);
myRemove(y, []);
myRemove(z, [2]);
myRemove(q, [1, 2]);
assert(x == [2, 3]);
assert(y == [1, 2, 3]);
assert(z == [1, 2]);
assert(q == [1]);
}

Perhaps it's nice to have the option?


Re: Strange double to uint conversion

2019-11-18 Thread mipri via Digitalmars-d-learn

On Monday, 18 November 2019 at 21:08:39 UTC, Luiz Silveira wrote:

double f;


If this is changed to `real f;`, you get the desired result.

real is also the type used for the comparison code:
https://dlang.org/spec/float.html#fp_const_folding



ints.choice vs. chars.choice

2019-11-18 Thread mipri via Digitalmars-d-learn

Howdy,

The following program fails to compile if the second line
is uncommented:

import std;

void main() {
writeln([1, 2, 3].choice);
//writeln(['a', 'b', 'c'].choice);
}

Error: template std.random.choice cannot deduce function from 
argument types !()(char[], MersenneTwisterEngine!(uint, 32LU, 
624LU, 397LU, 31LU, 2567483615u, 11LU, 4294967295u, 7LU, 
2636928640u, 15LU, 4022730752u, 18LU, 1812433253u)), candidates 
are:
/usr/include/dmd/phobos/std/random.d(2559):
std.random.choice(Range, RandomGen = Random)(auto ref Range 
range, ref RandomGen urng) if (isRandomAccessRange!Range && 
hasLength!Range && isUniformRNG!RandomGen)
/usr/include/dmd/phobos/std/random.d(2569):
std.random.choice(Range)(auto ref Range range)


What is going on here? I get it that choice() isn't simply an 
algorithm

over T[], that there are some additional constraints, but surely a
char[] is just as random acc...

...

Oh. It's because of emojicode.

This works:

import std;

void main() {
writeln([1, 2, 3].choice);
writeln(cast(char)(cast(uint8_t[])['a', 'b', 'c']).choice);
}

and this outputs false: writeln(isRandomAccessRange!(char[]));

I no longer have any questions but I wish the dlang.org docs were
much more generous with examples.


Re: Should I stop being interested in D language if I don't like to see template instantiation in my code?

2019-11-13 Thread mipri via Digitalmars-d-learn

On Wednesday, 13 November 2019 at 14:01:13 UTC, BoQsc wrote:
I don't like to see exclamation marks in my code in as weird 
syntax as these ones:

to!ushort(args[1])
s.formattedRead!"%s!%s:%s"(a, b, c);


I'd suggest learning to love it, or at least getting to it, vs.
to(args[1]) C++ syntax. Template *syntax* benefits are

1. D's is relatively quick to parse.

2. the ! is an attention getter so you can see that some special
action is taking place (although templates don't always require
this). Personally this is more of a comfort ("I'm *definitely*
doing some work at compile-time here, instead of at runtime like
other languages force me to") than an alert ("something weird is
happening!") though.

3. it's very clear what's a compile-time vs. a runtime parameter 
to

the template.

I'm not sure why, but template instantiation syntax is 
prevalent in the documentation examples of d lang libraries. It 
almost seems like every other example contains at least one or 
two  of them.


Templates are so beneficial that people put up with C++.

D uses them everywhere and if you persist in hating the
syntax you'll just hate a lot of the D syntax that you see.



Re: Running unittests of a module with -betterC

2019-10-29 Thread mipri via Digitalmars-d-learn

On Monday, 28 October 2019 at 08:51:02 UTC, Daniel Kozak wrote:
On Mon, Oct 28, 2019 at 9:40 AM Per Nordlöw via 
Digitalmars-d-learn  wrote:


Is it possible to run the unittests of a module with -betterC 
like


 dmd -D -g -main -unittest -betterC f.d

?

This currently errors as

/usr/include/dmd/druntime/import/core/internal/entrypoint.d:34: error: 
undefined reference to '_d_run_main'

for an empty file f.d


AFAIK no,

https://dlang.org/spec/betterc.html#unittests


-unittest sets the 'unittest' version identifier. So this works:

  unittest {
 assert(0);
  }

  version(unittest) {
  extern(C) void main() {
  static foreach(u; __traits(getUnitTests, 
__traits(parent, main)))

  u();
  }
  }

dmd -betterC -unittest -run module.d


Re: About the in expression, Why can't use with array.

2019-10-25 Thread mipri via Digitalmars-d-learn

On Friday, 25 October 2019 at 15:52:50 UTC, Paul Backus wrote:

On Friday, 25 October 2019 at 09:25:21 UTC, Dennis wrote:
I can overload the 'in' operator on my types to something that 
takes exponential time if I want, just like "+" can also be 
overloaded to a linear time operation on e.g. BigInt.


Worth noting that `opIn` is a D1 operator overload, and thus 
deprecated as of 2.088.0.


That wasn't mentioned though? Does it reverse the arguments so
that the writeln() examples below can be more naturally ordered?

  #! /usr/bin/env rdmd
  import std.stdio;

  struct X {
  string data;

  bool opBinary(string op)(char p) if (op == "in") {
  foreach (c; data)
  if (p == c) return true;
  return false;
  }
  }

  void main() {
  auto x = X("hi there");
  writeln(x in 'i');
  writeln(x in '?');
  }



Re: GtkD ListG Howto?

2019-10-11 Thread mipri via Digitalmars-d-learn

On Friday, 11 October 2019 at 19:53:33 UTC, Ron Tarrant wrote:
Pixbuf airportImage1, airportImage2, airportImage3, 
airportImage4;

void * image1, image2, image3, image4;

airportImage1 = new Pixbuf("images/airport_25.png");
airportImage2 = new Pixbuf("images/airport_35.png");
airportImage3 = new Pixbuf("images/airport_60.png");
airportImage4 = new Pixbuf("images/airport_100.png");
image1 = 
image2 = 
image3 = 
image4 = 

ListG listG = null;



I get the segfault to go away with

  ListG list = new ListG(null);

which is usage you can find in APILookupGLib.txt


listG = listG.append(image1);
listG = listG.append(image2);
listG = listG.append(image3);
listG = listG.append(image4);

setIconList(listG);




Re: Dynamic Arrays as Stack and/or Queue

2019-10-08 Thread mipri via Digitalmars-d-learn
On Tuesday, 8 October 2019 at 10:48:45 UTC, Jonathan M Davis 
wrote:

The result of this is that code like

stack.popBack();
stack ~= foo;
stack ~= bar;
stack.popBack();
stack ~= baz;

will end up allocating all over the place. Every time you
append to the array after shrinking it, you're going to end up
with the GC allocating a new block of memory instead of
appending in place.



Thanks as well! I thought the code I posted would only allocate 
when
the array ran out of capacity. And I see how, even if that's 
worked

around with assumeSafeAppend, it becomes a bad idea to define the
stack functions against `ref T[]` as this makes it too easy for 
other

code to slice the array and cause the bugs that assumeSafeAppend
allows.


Re: Dynamic Arrays as Stack and/or Queue

2019-10-07 Thread mipri via Digitalmars-d-learn

On Monday, 7 October 2019 at 19:16:31 UTC, IGotD- wrote:
On Monday, 7 October 2019 at 17:36:09 UTC, Ferhat Kurtulmuş 
wrote:


I'm not talking about memory deletion. I'm talking about 
push, pop, enqueue, and dequeue behavior. I'd assume in a 
garbage collected language letting the reference float off 
should be picked up by the GC.
I'm sorry. Writing on my mobile phone. Maybe this is what you 
are looking for

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


I think what he is looking for are the general pop_front, 
push_front, pop_back and push_back that you would find in 
virtually any C++ STL container algorithms like list, vector or 
map.


I think this is a good question as I don't really see any good 
example in the documentation of the dynamic arrays about this. 
This is very common use case for arrays. Is there any D 
equivalent?


With the performance that you'd expect, I believe:

#! /usr/bin/env rdmd
import std.stdio;
import std.algorithm : moveAll;

void push_front(T)(ref T[] xs, T x) {
++xs.length;
moveAll(xs[0 .. $-1], xs[1..$]);
x[0] = x;
}
T pop_front(T)(ref T[] xs) {
T x = xs[0];
moveAll(xs[1 .. $], xs[0 .. $-1]);
--xs.length;
return x;
}
void push_back(T)(ref T[] xs, T x) {
xs ~= x;
}
T pop_back(T)(ref T[] xs) {
T x = xs[$ - 1];
--xs.length;
return x;
}

void main() {
int[] xs;
foreach (i; 0 .. 10)
xs.push_back(i);
writeln(xs.pop_back());  // output: 9
writeln(xs.pop_front()); // output: 0
writeln(xs.pop_front()); // output: 1
writeln(xs); // output: [2, 3, 4, 5, 6, 7, 8]
}



Re: Dynamic Arrays as Stack and/or Queue

2019-10-07 Thread mipri via Digitalmars-d-learn

On Monday, 7 October 2019 at 17:11:08 UTC, Just Dave wrote:
I need a stack and a queue and I noticed that the standard 
library doesn't appear to have one. Which is ok. I just need 
something that can logically behave as a stack and queue, which 
I think the dynamic array should be able to do (if I understand 
correctly this is effectively the equivalent of vector in 
C++ or List in C#). However, I'm having a hard time figuring 
out the best way to push, pop, enqueue and dequeue using D.


I'm not seeing here: https://dlang.org/spec/arrays.html, anyway 
to remove from the array. What's the correct syntax/method call 
for this? I see you can easily concatenate with '~', but I see 
no corresponding delete.


Sorry for the newbie question, but I'm just unsure where to 
look for this.


if the top of the stack is the last element, --stack.length works
as a simple pop.


Re: Blog Post #75: Cairo X - Noodling with the Mouse

2019-10-04 Thread mipri via Digitalmars-d-learn

On Friday, 4 October 2019 at 20:56:31 UTC, Greatsam4sure wrote:

On Tuesday, 1 October 2019 at 09:58:42 UTC, Ron Tarrant wrote:
Here's the second installment of the Nodes-n-noodles coverage 
in which we get the mouse involved: 
https://gtkdcoding.com/2019/10/01/0075-cairo-x-mouse-noodle.html


Pls sir can you make a pdf of the tutorials. that can be easily 
downloaded once and for all. So that I need to be online. Not 
everybody have cheap internet.


The github repo at https://github.com/rontarrant/gtkDcoding
includes the blog posts as a jekyll site under docs/

So you can clone the repo and then follow the instructions at
https://jekyllrb.com/ to view the site locally.

If you don't use Ruby at all you'll probably get a series of
errors with those instructions actually, but each one will
suggest a fix that worked for me.



Re: What is the extension of ".pdf"

2019-10-04 Thread mipri via Digitalmars-d-learn

On Friday, 4 October 2019 at 19:58:16 UTC, Andre Pany wrote:

Hi,
I try to solve the puzzle 
https://www.codingame.com/training/easy/mime-type but have some 
issue because std.path:extension returns null for file name 
".pdf" while the puzzle (test case 3) expects that the 
extension is ".pdf".


Is the puzzle wrong or the phobos extension implementation?



The implementation is very likely thinking of Unix dotfiles, like
.bash_profile, where the intent is to hide the file from normal
displays rather than suggest an extension.

I don't see a mention of dotfiles in the source, but it has these
tests:

assert(extension(".foo".dup).empty);
assert(extension(".foo.ext"w.dup) == ".ext");


Kind regards
Andre





Re: Using algorithms with ranges

2019-10-03 Thread mipri via Digitalmars-d-learn

On Thursday, 3 October 2019 at 08:52:22 UTC, Andrea Fontana wrote:

On Thursday, 3 October 2019 at 05:33:04 UTC, mipri wrote:

void main() {
import std.range : iota;

foreach (x; iota(1, 10).withHistory)
writeln(x);
}



This doesn't work as expected, I think.

auto r = iota(1,10).withHistory;

writeln(r.front);
writeln(r.front);


Oops. That output should be the same, since popFront hasn't been 
called.

I made this mistake in my other ranges as well...

The code's also bad for preserving the entire history when only 
the

latest is needed for what it's doing.


Re: Using algorithms with ranges

2019-10-03 Thread mipri via Digitalmars-d-learn

On Thursday, 3 October 2019 at 08:52:22 UTC, Andrea Fontana wrote:

On Thursday, 3 October 2019 at 05:33:04 UTC, mipri wrote:

void main() {
import std.range : iota;

foreach (x; iota(1, 10).withHistory)
writeln(x);
}



This doesn't work as expected, I think.

auto r = iota(1,10).withHistory;

writeln(r.front);
writeln(r.front);


Oops. That output should be the same, since popFront hasn't been 
called.


The code's also bad for preserving the entire history when only 
the

latest is needed for what it's doing.


Re: Using algorithms with ranges

2019-10-02 Thread mipri via Digitalmars-d-learn

On Thursday, 3 October 2019 at 05:20:47 UTC, mipri wrote:

It'd be nicer to do compose a range over iota, as in

  iota(1, 10).newThingWithHistory

but I don't know how to do that yet. I guess c.f. 
std.range.retro


This is a bit better:

#! /usr/bin/env rdmd
import std.stdio;

auto withHistory(Range)(Range r) {
import std.traits : Unqual;
import std.range.primitives : ElementType;

static struct Result {
private:
alias R = Unqual!Range;
alias T = ElementType!R;

R source;
T[] history;

public:
bool empty() {
return source.empty;
}

void popFront() {
source.popFront;
}

T front() {
T x = source.front;
history ~= x;
if (history.length > 1) {
return x + history[$-2];
} else {
return x;
}
}
}

return Result(r);
}

void main() {
import std.range : iota;

foreach (x; iota(1, 10).withHistory)
writeln(x);
}



Re: Using algorithms with ranges

2019-10-02 Thread mipri via Digitalmars-d-learn

On Thursday, 3 October 2019 at 04:33:10 UTC, Brett wrote:
I routinely have to generate data using points sequentially and 
refer to previous points in the data set, maybe even search 
them. I also may have to break up the algorithm in to parts.


I'd like to get more in to ranges but I simply do not use them 
much because I don't know all the fancy stuff that makes them 
more useful over just doing it manually(usually for loop or 3).



Is there a way to express an algorithm that generates a data 
point that may depend on previous data points and "rangify" 
them?


One usually starts with some integer range: iota(-5,5,1)

The idea then is to be able to generates points off the range 
but have access to the previous generated points without having 
to regenerate them(very inefficient).


so if P_k is our kth point then we need to have access to P_j 
for j < k.



...
Again, if the range code is very complicated and one has to 
jump through a lot of hoops then it is easier to just do it 
manually. The main thing I'm interested in is the "History" 
feature and maybe a way to easily partition the range(range of 
ranges).


Basic use (which is all I know) of ranges is easy-peasy.  You just
define empty/front/popFront and use it as a range.  You can keep
whatever state you want in addition to that.  I've got a range 
that
internally has an open file handle and PCRE pointers in it. The 
only

complication is that I have to put my destructor code in a normal
function so that both the destructor (in case of unintended use 
that

leaves the GC cleaning things up) and exhausting the range (in the
intended case) can both call it.

Here:

  #! /usr/bin/env rdmd
  import std.stdio;

  struct iotaPlus(T) {
  import std.range : iota;

  typeof(iota(0,0)) r;
  T[] history;

  this(T a, T b) {
  r = iota(a, b);
  }

  bool empty() {
  return r.empty;
  }

  void popFront() {
  r.popFront;
  }

  T front() {
  T x = r.front;
  history ~= x;
  if (history.length > 1) {
  return x + history[$-2];
  } else {
  return x;
  }
  }
  }

  void main() {
  foreach (x; iotaPlus!int(1, 10))
  writeln(x);
  }

Output:

  1
  3
  5
  7
  9
  11
  13
  15
  17

It'd be nicer to do compose a range over iota, as in

  iota(1, 10).newThingWithHistory

but I don't know how to do that yet. I guess c.f. std.range.retro



Re: Struct initialization has no effect or error?

2019-10-02 Thread mipri via Digitalmars-d-learn

On Thursday, 3 October 2019 at 04:33:26 UTC, Brett wrote:
I was trying to avoid such things since X is quite long in 
name. Not a huge deal... and I do not like the syntax because 
it looks like a constructor call.


It is a constructor call, though. You can define your own as well:

  #! /usr/bin/env rdmd
  import std.stdio;

  struct X {
  int a;

  this(int x) {
  a = x * 2;
  }
  }

  void main() {
  auto test = X(22);
  writeln(test.a);
  }

output: 44



Re: Why is it difficult to reference arrays in structs?

2019-10-02 Thread mipri via Digitalmars-d-learn

On Thursday, 3 October 2019 at 04:32:52 UTC, Brett wrote:

struct Y { double q; }
struct X { Y[] a; }

X x;

auto r = x.a;

r is not a reference?!?!


Arrays are (ptr,length) pairs. r is a copy of them:

  #! /usr/bin/env rdmd
  import std.stdio;

  struct X { int[] a; }

  void main() {
  auto test = X([0]);
  test.a.reserve(10); // for later
  auto r = test.a;
  writeln(test.a.ptr == r.ptr); // true
  writeln(test.a.length == r.length); // true
  }

Mutate it and they're still using the same ptr:

  r ~= [1];
  writeln(test.a.ptr == r.ptr); // true
  writeln(test.a.length == r.length); // false

But r is still a copy of the ptr,length pair, and
its length is updated separately.

Consider:

  #! /usr/bin/env rdmd
  import std.stdio;

  struct X { int[] a; }

  void main() {
  X test;
  test.a.reserve(3);
  auto a = test.a;
  a ~= [1, 2, 3];
  auto r = test.a.ptr[0..3];
  writeln(r); // output: [1, 2, 3]
  }

I have to slice the ptr directly as array operations are aware
of all this. Consider:

  #! /usr/bin/env rdmd
  import std.stdio;

  struct X { int[] a; }

  void main() {
  X test;
  test.a.reserve(3);
  auto a = test.a;
  a ~= [1, 2, 3];
  test.a.length = 3;
  writeln(test.a); // [0,0,0]
  writeln(a); // [1,2,3]
  }

What you can do copy the (ptr,length) pair, do what you want with
it, and then assign it back to the struct. Don't worry about 
tricky

stuff.


auto r = 

Now r is a reference, great!.


look at it:

writeln(typeid(a)); // output: int[]*

It's a pointer to an int[]. It behaves like a pointer.

I want to have a slice of an array that I can append to as a 
sort of temporary and have it append to the main array(the end 
of the slice always is the end of the main array)..


I've tried assumeSafeAppend but it does nothing to help.


Learning D goes into tons of detail about slices and appending to
copies and when you'd want assumeSafeAppend and so on.



Re: Struct initialization has no effect or error?

2019-10-02 Thread mipri via Digitalmars-d-learn

On Wednesday, 2 October 2019 at 17:37:57 UTC, Brett wrote:

X y = {3};

works fine.

So one has to do

x[0] = y;


You could initialize x all at once. Complete example:

  import std.stdio;

  struct Point {
  int x, y;

  string toString() {
  import std.format : format;

  return format("(%d, %d)", x, y);
  }
  }

  void main() {
  Point[2] ps = [{0,0}, {4,4}];
  foreach (p; ps) writeln(p);
  }



Re: Struct initialization has no effect or error?

2019-10-02 Thread mipri via Digitalmars-d-learn

On Wednesday, 2 October 2019 at 17:54:20 UTC, H. S. Teoh wrote:
On Wed, Oct 02, 2019 at 05:37:57PM +, Brett via 
Digitalmars-d-learn wrote:

struct X { int a; }

X[1] x;

x[0] = {3};

or

x[0] = {a:3};

fails;


This works:

x[0] = X(123);



I'd knew I'd gotten the impression from somewhere that this was 
the
recommended way to initialize structs, but it took me a while to 
find

it.

Learning D:

  auto ms1 = MyStruct(10, 11);// struct literal
  MyStruct ms2 = {10, 11};// C-style, not preferred
  MyStruct ms3 = {b:11, a:10};// Named initializers

  ..

  Struct literals are convenient for simple types ...
  but they only allow for direct initialization of member
  variables. If more complex initialization is required, struct
  constructors should be used.

And then the impression was probably just from every single 
example

using the first form.

https://dlang.org/spec/struct.html#static_struct_init doesn't say 
that
this is dispreferred in any way, nor does it emphasize that you 
can't
use initialization syntax to assign to an already initialized 
variable
(this is probably obvious to C types). But there are 'Best 
Practices'
notes elsewhere in the page. This section could have one of 
those, to

say to just use the constructors.