Re: recursive definition error

2014-07-04 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 4 July 2014 at 16:28:48 UTC, Frustrated wrote:

On Friday, 4 July 2014 at 15:42:36 UTC, bearophile wrote:

Frustrated:



I'm not using 2.066 though...

I will revert back to the dmd version I was using when it 
worked... Hopefully someone can make sure this is not a 
regression in the mean time... (seems like it is and I don't 
want to get bit again later on when I upgrade)


That template and its instantiation work fine for me on both 
2.065 and 2.066b1.


Re: Use of "T"

2017-04-12 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 12 April 2017 at 22:56:25 UTC, solidstate1991 wrote:

I know the existence of those and I'm frequently using them, 
however I need a two-way one. (Might be using two hash-tables 
instead if I can't find a better solution)


So, you're looking for a generic way to store objects of 
arbitrary types in a file, and later retrieve those objects from 
that file? If that's the case, try looking at some existing 
serialization solutions (i.e. 
https://wiki.dlang.org/Serialization_Libraries).




Re: Can't pass data from filter to each

2017-04-17 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 17 April 2017 at 10:02:22 UTC, Suliman wrote:
New question. Can I put result of filtering in itself without 
creation of new variables like x:


auto x = 
MySQLTablesRange.array.filter!(a=>a[0].coerce!string.canFind("_"));


No. filter is simply a wrapper around the source range, it does 
not modify it.


As for the problems you are having with ranges seeming empty, 
they are all due to the fact that the ResultRange in mysql-native 
isn't designed to support such chaining of calls. It's probably 
best to first exhaust a ResultRange and put it into an array.


Re: Can we disallow appending integer to string?

2017-04-19 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 19 April 2017 at 14:36:13 UTC, Nick Treleaven wrote:
This bug is fixed as the code no longer segfaults but throws 
instead:

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

void main(){
string ret;
int i = -1;
ret ~= i;
}

Why is it legal to append an integer?


Because integrals implicitly convert to characters of same width 
(byte -> char, short -> wchar, int -> dchar).


Re: Can we disallow appending integer to string?

2017-04-20 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 20 April 2017 at 19:20:28 UTC, H. S. Teoh wrote:


Another pernicious thing I encountered recently, related to 
implicit conversions, is this:


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

It drew a very enunciated "WAT?!" from me.


Yeah, that one is annoying. I've dealt with this before with:

alias OpResult(string op, A, B) = typeof((){ A* a; B* b; return 
mixin("*a"~op~"*b"); }());




Re: Can we disallow appending integer to string?

2017-04-19 Thread Stanislav Blinov via Digitalmars-d-learn
On Wednesday, 19 April 2017 at 17:34:01 UTC, Jonathan M Davis 
wrote:


Personally, I think that we should have taken the stricter 
approach and not had integral types implicit convert to 
character types, but from what I recall, Walter feels pretty 
strongly about the conversion rules being the way that they are.


Yep, me too. Generally, I don't think that an implicit conversion 
(T : U) should be allowed if T.init is not equivalent to U.init.





Re: The app hanging after reach 1750MB of RAM

2017-04-19 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 19 April 2017 at 07:28:32 UTC, Suliman wrote:

1. You're measuring it wrong. Array length is already measured 
in terms of type size.


So should I do:
cargpspoints.length * cargpspoints[0].sizeof ?


No. .sizeof is the statically known size of a type, it can't take 
into account dynamically allocated memory.
cargpspoint.length * cargpspoints[0].sizeof will tell you the 
estimate size of the array, in bytes.
But each of the elements also has strings - dynamic arrays that 
are allocated elsewhere, their length is not included in that 
calculation.
So you could iterate over the array and sum up lengths of all 
strings to get an estimate.
Even then, that's just that: an estimate. Actual amount of memory 
allocated for a dynamic array T[] *may* be greater than length * 
T.sizeof. The only way to know that is to query the allocator 
used (in this case, GC).




Re: Can we disallow appending integer to string?

2017-04-19 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 19 April 2017 at 18:40:23 UTC, H. S. Teoh wrote:

A few extra keystrokes to type cast(int) or cast(char) ain't 
gonna kill nobody. In fact, it might even save a few people by 
preventing certain kinds of bugs.


Yup. Not to mention one could have

@property
auto numeric(Flag!"unsigned" unsigned = No.unsigned, C)(C c) 
if(isSomeChar!C)

{
return cast(IntOfSize!(C.sizeof, unsigned))c;
}

auto v = 'a'.numeric;

...or even have an equivalent as a built-in property of character 
types...


Re: Cleaning up Dub/Dmd builds

2017-04-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 18 April 2017 at 15:07:27 UTC, WhatMeWorry wrote:

When I try to upload these files to my new repo, GitHub 
(rightfully so) complains that
I have too many files. Since I'm using sdl and not json, can I 
safely delete all the files
that pertain to json?  Can I do this some way at the command 
line?



You shouldn't upload files from the .dub directory, that's local 
build cache that shouldn't  be published. You can simply add the 
.dub directory to your .gitignore file.


Re: The app hanging after reach 1750MB of RAM

2017-04-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 18 April 2017 at 13:28:57 UTC, Suliman wrote:
Also I can't understand why app take so much memory? I checked 
array of structures size with this code:


auto mymem = cargpspoints.length * 
typeof(cargpspoints[0]).sizeof;			

writeln(mymem);

And it's print: 16963440
it's about 16MB...

What is takes all other memory?


1. You're measuring it wrong. Array length is already measured in 
terms of type size. But remember that every call result.array 
will allocate, and very call coerce!string will also allocate.
2. Since you're iterating over every result once, there's no 
point in converting it to an array first.

3. Consider using the Row.toStruct() method for conversion.
4. Consider using std.array.appender instead of ~=.

void getSingleTrackInfo()
{

foreach(item; getTablesGPSSensorList)
{
ResultRange result = mysqlconnection.query(sqlquery);

carGPSPoint cargpspoint; // create struct
auto arr = appender!(carGPSPoint[]); // create array of 
structures


foreach(row; result)
{
arr ~= row.toStruct(cargpspoint);
}

// arr.data should hold the array of structures
}
}



Re: The app hanging after reach 1750MB of RAM

2017-04-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 18 April 2017 at 14:09:28 UTC, Stanislav Blinov wrote:


foreach(row; result)
{
arr ~= row.toStruct(cargpspoint);
}


Sorry, this should be

foreach(row; result)
{
row.toStruct(cargpspoint);
arr ~= cargpspoint;
}


Re: hidden passing of __FILE__ and __LINE__ into function

2017-04-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 18 April 2017 at 13:28:06 UTC, Solomon E wrote:


I tried to produce an example of calling a function with
variadic template arguments using special tokens __FILE__ and 
__LINE__.


This compiles and runs, producing the output shown, using the 
default gdc
provided by Ubuntu 17.04. This appears to be a workaround for 
Issue 8687...


There's a much more concise workaround, both in code written and 
generated ;)


import std.stdio;

template func(string file = __FILE__, int line = __LINE__)
{
auto func(T...)(auto ref T args)
{
writeln("called func with ", T.length, " args at ",
file, ":", line);
}
}

void main()
{
func();
func(1, 2, 3);
}



Re: Get name of current function

2017-04-23 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 23 April 2017 at 20:34:12 UTC, Mike B Johnson wrote:

I'd like to get the symbolic name of the current function I'm in

void foo()
{
writeln(thisFunc.stringof()); // prints foo
}

I need something short, elegant and doesn't require modifying 
preexisting code... I'm sure D has something along those lines?


__FUNCTION__ and __PRETTY_FUNCTION__

both will give qualified name though (e.g. module.foo), so, if 
necessary, that has to be stripped out manually.


Re: using shared effectively in a producer/consumer situation.

2017-04-23 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 23 April 2017 at 20:33:48 UTC, Kevin Balbas wrote:

I guess the follow up here is:  Is this the correct way to do 
it?

 cast to shared, send to main thread, cast away shared?


At the moment, pretty much yes. Either that or make the 
(unnecessary) immutable copies.
There are no ownership primitives in Phobos yet, and shared 
itself is still... not quite there.


Re: refRange with non copyable struct

2017-04-17 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 17 April 2017 at 19:00:44 UTC, Jonathan M Davis wrote:

Because otherwise, it's not acting like a reference to the 
original range, which is the whole point of RefRange. The 
correct solution would probably be to @disable opAssign in the 
case where the original range can't be overwritten by another 
range.


This doesn't look quite right. References in D are rebindable. 
That is, assigning a reference to a reference does not copy 
referenced object, only the reference itself.

It seems that RefRange is trying to impersonate a C++ reference.


Re: if auto and method call

2017-04-17 Thread Stanislav Blinov via Digitalmars-d-learn

Would be prettier as a language feature, but still:

template test(alias pred)
{
import std.functional : unaryFun;
alias P = unaryFun!pred;

auto test(R)(R r)
{
struct Test
{
R v;

string toString()
{
import std.conv : to;
return v.to!string;
}

bool opCast(B : bool)() const
{
return P(v);
}

ref inout(R) get() inout
{
return v;
}

alias get this;
}

import std.algorithm : move;
return Test(move(r));
}
}

void main()
{
import std.regex;
import std.stdio;
string s1 = "hello";
string s2 = "world";

if (auto x = test!"!a.empty"(match(s1, "hello")))
{
writeln(x.captures[0]);
}

if (auto x = test!"!a.empty"(match(s2, "hello")))
{
writeln(x.captures[0]);
assert(0);
}

// UFCS:

if (auto x = s1.match("world").test!"!a.empty")
{
writeln(x.captures[0]);
assert(0);
}

if (auto x = s2.match("world").test!"!a.empty")
{
writeln(x.captures[0]);
}

if (auto x = 3.test!"a == 3")
{
writeln(x, " equals 3, huh?");
}
}



Re: scoped classes

2017-04-27 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 27 April 2017 at 06:40:49 UTC, Alex wrote:

Hi all,
a short question about an example.
having read this:
https://dlang.org/library/std/typecons/scoped.html

There is a struct B defined in the middle of the example, with 
a scoped class member.
How to define an array of such members (and to put some items 
to it)?

So, I want to have something like

// Use as member variable
struct B
{
typeof(scoped!A())[] a; // note the trailing parentheses

this(int i)
{
// construct member
a.length = 5; // doesn't work, as the default 
constructor is disabled.
a ~= scoped!A(i); // doesn't work, as the type is not 
copyable

// ???
}
}


The only "possible" way would be like this:

typeof(scoped!A())[] a;
a = [ scoped!A(1), scoped!A(2), scoped!A(3) ];

But even so, you shouldn't do that. scoped isn't designed for it.


Re: scoped classes

2017-04-27 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 27 April 2017 at 15:47:38 UTC, Alex wrote:


struct S
{
@disable this();
@disable this(this);
this(size_t dummy){}
}

Given a struct with an explicit constructor and a postblit. How 
to make an array of it?


You mean with a disabled default ctor and postblit? You can't 
with built-in arrays. They expect that elements can be 
default-constructed and copied. Even std.container.Array in its 
current implementation won't help you there.
The only way to get around that is to devise your own array type 
that carefully deals with uninitialized storage and uses 
emplace/move/moveEmplace to store elements.




Re: scoped classes

2017-04-27 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 27 April 2017 at 17:07:05 UTC, Ali Çehreli wrote:
I haven't used it yet but it's worth noting that there is 
EMSI's container library as well:


  http://code.dlang.org/packages/emsi_containers


A brief glance at the source of dynamicarray there suggests that 
it won't help with non-copyables either.


Re: scoped classes

2017-04-27 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 27 April 2017 at 18:36:08 UTC, Alex wrote:

* I'm pretty sure that the code is going to be invalid when 
you're dealing with const/immutable data.
Ok... this is important... I tried this out, and the value of 
the immutable data even remains the same. But for safety 
reasons, I would reconstruct the structs inside the array 
anyway, so I can live with this, I think...


move() is only destructive if the type has custom postblit or 
destructor, otherwise it's just a bitwise copy. But, as 
mentioned, there's an issue with it at the moment: it doesn't 
really care if the type being moved has const/immutable members.


uninitializedArray is scary. If you do use it, probably best to 
localize the usage as much as possible and be very very VERY 
careful with it ;)


Here's a sketch of something that's a little bit more convenient: 
https://dpaste.dzfl.pl/ee472fd872a5

But I'm not going to pretend it'd survive a review.

Also note that, going back to your original question, docs for 
scoped state that it's illegal to move it, so that particular 
type you can't really store in any of these arrays.


Re: get parameters of a function

2017-04-29 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 28 April 2017 at 20:43:50 UTC, Alex wrote:

Hi all,
I have a question about the Parameters trait from
https://dlang.org/phobos/std_traits.html#Parameters

The following code does not compile. Why?
Is it mainly assumed to use it with functions without overloads?


Rather, it is to be used on a concrete overload.
If you want to check if two structs are callable with the same 
parameters, you'll need to iterate opCall overloads for both and 
look for a match, e.g. like this:


void main()
{
foreach(o1; __traits(getOverloads, S1, "opCall"))
{
alias P1 = Parameters!o1;
foreach(o2; __traits(getOverloads, S2, "opCall"))
{
alias P2 = Parameters!o2;
static if (is(P1 == P2))
{
pragma(msg, "Matching params: "~P1.stringof);
}
}
}
}


Re: get parameters of a function

2017-04-29 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 29 April 2017 at 06:18:34 UTC, Alex wrote:


The problem is another one: say I have something like this:

import std.traits;

struct A(alias T) if(isCallable!T)
{   
	auto opCall(U...)(U args) if(is(Parameters!T == U)) 
//if(__traits(compiles, T(args)))

{
return T(args);
}
}

void main()
{
S s;
A!s c;
assert(c(4) == 42);
}

struct S
{
auto opCall(){ return 42; }
auto opCall(int i){return 42; }
}

This doesn't work because of Parameters trait and the both 
opCalls defined.

However, I see the point...
If I take the compiles-trait, it works as expected:
In this case the constrained is fulfilled, and with the second 
opCall commented out - it isn't.


Thanks :)


Ah, that calls for something like a isCallableWith template. Pay 
extra care to how you pass parameters in that variadic opCall 
template though. Doing it like in the code above will pass 
everything by value, even though the original S.opCall might've 
expected a reference. To avoid that, auto ref + 
std.functional.forward can be used.

The following code illustrates the difference.

import std.traits;
import std.functional : forward;

/**
  Evaluates true if `func` is callable with arguments `args`.
  Can only be used as a function template constraint.
*/
enum isCallableWith(alias func, args...) = 
is(typeof(func(forward!args)));


// Your original A
struct A(alias func) if (isCallable!func)
{
auto opCall(Args...)(Args args) if (__traits(compiles, 
func(args)))

{
// all arguments are copied, any "ref/out" semantics are 
lost

return func(args);
}
}

// Modified to forward arguments
struct B(alias func) if (isCallable!func)
{
// auto ref: preserve lvalues
auto opCall(Args...)(auto ref Args args) if 
(isCallableWith!(func, args))

{
// forward: preserve lvalues
return func(forward!args);
}
}

struct S
{
auto opCall() { return 42; }
auto opCall(int i) { return 42; }
// Note: parameter passed by reference!
auto opCall(out float f) { f = 42.0f; }
}

void main()
{
S s;

{
A!s c;
int i = 4;
static assert(is(typeof(c(i;
static assert(is(typeof(c(4;
static assert(is(typeof(c(;

assert(c(i) == 42);
assert(c(4) == 42);
assert(c() == 42);
// Should pass but doesn't.
//static assert(!is(typeof(c(3.5f;
float f;
static assert(is(typeof(c(f;
c(f);
// Will assert:
assert(f == 42.0f);
}

{
B!s c;
int i = 4;
static assert(is(typeof(c(i;
static assert(is(typeof(c(4;
static assert(is(typeof(c(;

assert(c(i) == 42);
assert(c(4) == 42);
assert(c() == 42);
// Passes
static assert(!is(typeof(c(3.5f;
float f;
static assert(is(typeof(c(f;
c(f);
// Won't assert
assert(f == 42.0f);
}
}


Re: Equivalent to nullptr

2017-05-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 4 May 2017 at 03:59:36 UTC, Leonardo wrote:

On Thursday, 4 May 2017 at 02:45:30 UTC, Adam D. Ruppe wrote:

On Thursday, 4 May 2017 at 02:12:13 UTC, Leonardo wrote:

nullptr word. How I use this?


Does it work if you just use `null` ?


No.

First I got: source/app.d(45,69): Error: expression 
(*SDL_EnclosePoints)(& mousePos, 1, , null) of type 
void does not have a boolean value


then I change to:
  event.button.button == SDL_BUTTON_LEFT && SDL_TRUE == 
SDL_EnclosePoints(, 1,  , null)


and got:
source/app.d(45,81): Error: void has no value
source/app.d(45,52): Error: incompatible types for ((SDL_TRUE) 
== ((*SDL_EnclosePoints)(& mousePos, 1, , null))): 
'int' and 'void'


Ahh, looks to be a bug in DerelictSDL2. null will work for that 
last parameter, the problem is that the function should be 
returning an SDL_bool, but in Derelict it's declared as returning 
void: that's what the error message is saying.
I'll file a report, but with the conference underway, it may take 
a while to get fixed.


Re: avoid extra variable during void pointer cast

2017-05-14 Thread Stanislav Blinov via Digitalmars-d-learn

On the point of "not possible...", "only a symbol...", etc:

T* ptrCast(T, alias ptr)() { return cast(T*)ptr; }

void addInt(void* state, void* data)
{
alias _state = ptrCast!(int, state);
alias _data = ptrCast!(int, data);

static assert(!is(typeof(_state) == int*));
static assert(!is(typeof(_data) == int*));

*_state += *_data;
}

But take heed to the compiler optimization advice. DMD generates 
pretty horrendous code for this. LDC does rather well though. 
Since speed matters, always look at the assembly. Look at it even 
if it doesn't ;)


Re: avoid extra variable during void pointer cast

2017-05-14 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 14 May 2017 at 21:55:01 UTC, ag0aep6g wrote:

On 05/14/2017 11:35 PM, Moritz Maxeiner wrote:

On Sunday, 14 May 2017 at 21:16:04 UTC, Stanislav Blinov wrote:

[...]

T* ptrCast(T, alias ptr)() { return cast(T*)ptr; }

[...]

alias _state = ptrCast!(int, state);

[...]
That's a pretty cool workaround, but not an alias to the cast, 
but an

alias to a parametrized function template (a type),


Not sure if I'm reading that right, but `_state` is not an 
alias of a (parametrized function) template.


The template instantiation results in a function. `_state` is 
an alias of that function. `alias foo = ptrCast;` would make an 
alias of the template. Neither of them is a type.


Yep, it's an alias to template function instantiation, that is, 
concrete function - a symbol.


But of course, it *is* going to be called on every "dereference". 
GDC optimizes the call away starting at -O1, LDC needs -O2. DMD 
makes temporaries :)


Re: alias and UDAs

2017-05-11 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 11 May 2017 at 10:39:03 UTC, Andre Pany wrote:

Hi,

in this example, both asserts fails. Is my assumption right, 
that UDA on alias have no effect? If yes, I would like to see a 
compiler warning.


But anyway, I do not understand why the second assertion fails. 
Are UDAs on arrays not allowed?


import std.traits: hasUDA;

enum Flattened;

struct Foo
{
int bar;
}

@Flattened alias FooList = Foo[];

struct Baz
{
FooList fooList1;
@Flattened FooList[] fooList2;
}

void main()
{   
Baz baz;
static assert(hasUDA!(baz.fooList1, "Flattened")); // => false
static assert(hasUDA!(baz.fooList2, "Flattened")); // => false
}

Kind regards
André


It should've been

alias FooList = @Flattened Foo[];

which will generate a compile-time error (UDAs not allowed for 
alias declarations).


And then:

static assert(hasUDA!(baz.fooList2, Flattened));

No quotes, since Flattened is an enum, not a string


Re: How to avoid throwing an exceptions for a built-in function?

2017-05-10 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 10 May 2017 at 13:27:17 UTC, k-five wrote:

Thanks, but I know about what are you saying. The user_apply[4] 
has so many possibilities and I cannot use if-else


That doesn't sound right. Either you've already handled all the 
possible cases and thus expect the to! to not throw (can specify 
that i.e. via std.exception.assumeWontThrow), or, as you're 
saying, it's much more than an if-else, but in that case 
exception will be thrown on invalid input.


Re: Converting a string[] to char**

2017-05-09 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 9 May 2017 at 07:50:33 UTC, David  Zhang wrote:

If indeed there is no way to avoid allocation, do the 
allocations have to remain 'alive' for the duration of the 
instance? Or can I deallocate immediately afterwards? I can't 
seem to find it in the Vulkan spec.


2.3.1. Object Lifetime:

Application-owned memory is immediately consumed by any Vulkan 
command it is passed into. The application can alter or free 
this memory as soon as the commands that consume it have 
returned.


Re: How to avoid throwing an exceptions for a built-in function?

2017-05-13 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 13 May 2017 at 08:50:20 UTC, k-five wrote:


Way arguing when a simple code can clarify the subject? right?
If am not clear so consider me as an stupid man, no problem at 
all.


but CAN you please solve it for me?

import std.stdio:   writeln;
import std.conv:to;

void main( string[] args ){

string str = "10";
int index;
index = to!int( str );  // okay, no exception are thrown

str = "some-words";
index = to!int( str ); // problem, an exception is thrown

}

Please run this code and convert "some-words" to int by using 
to! function without facing any exception. Thanks


Please don't take it the wrong way. It just seems that Mike was 
as confused by your questions as I was initially. But it's clear 
that's just the language barrier, nothing more. See, you said:


Why I do not want to take care of that? Because I just need the 
value, if the string is valid, otherwise no matter what the 
value of string is.


...but it doesn't make sense to have an int "value" for a string 
like "some-words". *Unless* one defines a "not-a-number" 
equivalent for an int, i.e. 0 or some other value. That part was 
hard to infer from what you were saying :) It might've been 
obvious for you, but hard to understand from what you wrote.


This was what made things clear:


I just want to silent this exception...


Mostly, the source of the confusion was the "I don't want to 
handle the exception". But in fact what you were asking was was 
there a way to somehow ignore the exception and just return some 
predefined value in case of an error. So in fact, you did want to 
handle the exception (or rather, an exceptional case), you just 
wanted to do it without inserting control flow instructions 
(try/catch) into your code. I think the latter part already got 
covered in others' replies.


Nobody was trying to insult you. With this being a multi-lingual 
and multi-cultural community, remember that understanding goes 
both ways, and we're sometimes caught right in the middle, in the 
clash of mentalities.


Re: Do array literals still always allocate?

2017-05-13 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 13 May 2017 at 18:32:16 UTC, Lewis wrote:

import std.random;
import std.stdio;

int[4] testfunc(int num) @nogc
{
return [0, 1, num, 3];
}

int main()
{
int[4] arr = testfunc(uniform(0, 15));
writeln(arr);
return 0;
}

I've read a bunch of stuff that seems to indicate that array 
literals are always heap-allocated, even when being used to 
populate a static array.


On the contrary, when initializing static arrays, allocation is 
not needed.

Note that what's *conceptually* happening in testfunc is this:


int[4] testfunc(int num) @nogc
{
   typeof(return) result = [0, 1, num, 3];
   return result;
}


i.e. the type and size of the storage is known beforehand, all 
there is to do is copy the elements:


0044e528 <@nogc int[4] test.testfunc(int)>:
  44e528:   55  push   %rbp
  44e529:   48 8b ecmov%rsp,%rbp
  44e52c:   48 83 ec 10 sub$0x10,%rsp
  44e530:   48 89 7d f8 mov%rdi,-0x8(%rbp)
  44e534:   c7 07 00 00 00 00   movl   $0x0,(%rdi)  # 
0 goes at offset 0
  44e53a:   c7 47 04 01 00 00 00movl   $0x1,0x4(%rdi)   # 
1 at offset 4
  44e541:   89 77 08mov%esi,0x8(%rdi)   # 
parameter at offset 8
  44e544:   c7 47 0c 03 00 00 00movl   $0x3,0xc(%rdi)   # 
3 at offset 12

  44e54b:   48 8b 45 f8 mov-0x8(%rbp),%rax
  44e54f:   c9  leaveq
  44e550:   c3  retq


Is all the old stuff I was reading just out-of-date now?


Where exactly did you read that initialization of a static array 
requires an allocation? That source should be abolished... 
errrm... corrected!


Re: How to move append to an array?

2017-05-15 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 15 May 2017 at 21:38:52 UTC, Yuxuan Shui wrote:

Suppose I have a

struct A {
  @disable this(this);
} x;

How do I append it into an array?

Do I have to do

array.length++;
moveEmplace(x, array[$-1]);

?


moveEmplace is for moving an initialized object into an 
uninitialized one. Use the two-argument move() function:


move(x, array[$-1]);


Re: How to move append to an array?

2017-05-15 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 16 May 2017 at 01:22:49 UTC, Yuxuan Shui wrote:

Can I expand an array with uninitialized object? Or can I rely 
on the compiler to optimize the initialization away?


Built-in arrays always default-initialize their elements. If you 
need something that unsafe, there's std.array.uninitializedArray:


http://dlang.org/phobos/std_array.html#uninitializedArray

What are you trying to achieve?


Re: Structure of Arrays vs Array of Structures

2017-05-15 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 15 May 2017 at 06:50:04 UTC, Nicholas Wilson wrote:

On Monday, 15 May 2017 at 06:44:53 UTC, Nordlöw wrote:



Have anybody done this already?


Yes, https://maikklein.github.io/post/soa-d/


The code in that article is overly simplified. Concrete use cases 
would require more than just storing one POD type. Looking back 
at Jonathan Blow's example, what if you wanted to store this type 
in a SoA?



struct Entity {
   Vector3 position;
   Quaternion orientation;
}


This, obviously, gets more involved, as now the SoA code needs to 
flatten that whole type recursively, otherwise it'd just store 
vectors packed together and then quaternions packed together, i.e:


[vx0, vy0, vz0, vx1, vy1, vz1...][qx0, qy0, qz0, qw0, qx1, qy1, 
qz1, qw1...]


whereas it should store

[vx0, vx1...][vy0, vy1...][vz0, vz1...][qx0, qx1...][qy0, 
qy1...][qz0, qz1...][qw0, qw1...]


Then, if you need to occasionally reassemble PODs from SoA, you 
need to deal with member alignment. And then there's a matter of 
providing actual functions dealing with types that are sparsely 
stored.


Also, there is a... debatable assessment of viability there:

But sometimes you still want to access all components of your 
data. An example would be a >vector. [...]
Most operations will use all components anyways like add, 
subtract, dot, length and many >more. And even if you sometimes 
end up with


struct Vec3{
   float x;
   float y;
   float z;
}

Array!Vec3 positions;

positions[].filter!(v => v.x < 10.0f);

and you want to filter all vectors where the x component is less 
than 10.0f, you will >still only load two additional floats.


"You will still *only* load two additional floats": that is 
incorrect. The CPU (at least, x86/64) won't load "only" two 
floats. It first needs to fetch the whole cache line only to 
touch every third float in it. That's ~66% of access time wasted. 
(Imagine how severe  that is if it actually has to fetch from 
RAM. Scratch that, don't imagine, time it.). And if you not only 
read, but write data, it gets that much more wasteful. That is 
precisely the problem SoA is intended to solve: it would always 
visit 100% of data it needs to fetch. But of course, if you do 
need to reconstruct tightly packed PODs from SoA, you'll get a 
pretty severe penalty. So, once you commit to storing data this 
way, you have to organize the code accordingly, otherwise you're 
more likely to degrade performance rather than gain it.


I do have an ongoing code experiment to see how far D could take 
us with it, but at this point it's rather immature. Perhaps in a 
couple of weeks I'd get it to a state that I could publish, if 
you guys would like to pitch in.


Re: Scope checking on static array struct doesn't kick in

2017-05-09 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 9 May 2017 at 12:25:29 UTC, Nordlöw wrote:

On Tuesday, 9 May 2017 at 11:52:35 UTC, Nordlöw wrote:
I've tagged the ref-returning functions (in this case 
`opSlice`) with `return scope` for my statically allocated 
array struct at


Here's a simpler example

https://github.com/nordlow/phobos-next/blob/cf85f449d24981fbe6269f8096db23282e2fbb65/tests/test_scope.d


Looks like a bug, if you change "auto" to "int[]" it starts 
complaining in f(). I have a question though, why is the syntax 
like this:



auto opSlice() return scope;


?

I don't see such in the DIP, proposed there is simply "scope" to 
the left of the declaration, i.e.



scope auto opSlice();


Although with that syntax dmd complains about escaping 'this', as 
if it was scope { auto opSlice(); }.


Is 'return scope' the syntax that is supposed to be used and it's 
just not reflected in the DIP, or?..


Re: How to avoid throwing an exceptions for a built-in function?

2017-05-10 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 10 May 2017 at 15:35:24 UTC, k-five wrote:
On Wednesday, 10 May 2017 at 14:27:46 UTC, Stanislav Blinov 
wrote:

On Wednesday, 10 May 2017 at 13:27:17 UTC, k-five wrote:

Thanks, but I know about what are you saying. The 
user_apply[4] has so many possibilities and I cannot use 
if-else


That doesn't sound right. Either you've already handled all 
the possible cases and thus expect the to! to not throw (can 
specify that i.e. via std.exception.assumeWontThrow), or, as 
you're saying, it's much more than an if-else, but in that 
case exception will be thrown on invalid input.


--

I know. But I am saying that I do not want to take care of any 
exceptions.

I just wanted to write:

int variable = to!int( string-type );

In fact something like using "no throw" is a function:
void init( ... ) nothrow {
...
int variable = to!int( string-type );
...
}

but this is not valid.

Thanks anyway and I will test: Function 
std.exception.assumeWontThrow at this link:

https://dlang.org/library/std/exception/assume_wont_throw.html


I don't understand. If you don't want to take care of exceptions, 
then you just don't do anything, simply call to!int(str). If an 
exception is thrown, it'll propagate further up the stack, until 
you either handle it or abort the program. "nothrow" does not 
turn off exceptions, it simply forbids throwing them in the 
enclosing scope (i.e. calling anything that might throw is not 
allowed).
Or do you mean that you've already made sure that the user input 
is valid such that to!int() will never throw with it? In that 
case, yes, assumeWontThrow is a way to express that. But then, 
the only way you can be sure of that is if you've already parsed 
the input yourself, so I'm not clear on the intent.
Alternatively, if what you're calling still might throw but you 
don't want to deal with try/catch blocks, there's 
collectException function in std.exception that'll give you the 
exception if it was thrown and let you deal with it without using 
try/catch.


Re: Error writing file a *.obj

2017-05-10 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 9 May 2017 at 14:08:48 UTC, bachmeier wrote:

On Tuesday, 9 May 2017 at 02:33:06 UTC, dummy wrote:

On Monday, 8 May 2017 at 12:29:27 UTC, bachmeier wrote:

On Monday, 8 May 2017 at 11:56:10 UTC, dummy wrote:


When i build some application with dub, i got this error:


I'm not a Dub user, but it has its own forum, so you might 
want to try there:

http://forum.rejectedsoftware.com/


Oh, i solve this problem my self...
because, the 'Ransomeware Protection' feature of Bitdefender 
InternetSecurity 2017.

dub and dmd working pretty when i turn off this feature.

Very sorry for noob question :/


This is not really a noob question. Since it affects new users 
trying to run a Hello World program, I wonder if it would be 
worthwhile to add that information to the error message. Most 
of the people trying out D will simply give up and blame the 
language.


It's not. It's not the job of the linker to go rummaging through 
all user's processes to find out which one is locking the file, 
even if it's possible.
What could be improved is the clarity, i.e. "Could not write the 
file due to it being locked for writing/lack of space on 
device/etc.".


Re: how to disable inlining of ldc2 when 'dub build --build=release'?

2017-05-20 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 20 May 2017 at 08:02:26 UTC, lixiaozi wrote:

so, what should i do to disable inlining of ldc2 in release 
build?


As Stefan mentioned, a test case would be nice. But have you 
tried annotating the offending function with pragma(inline, 
false)?


http://dlang.org/spec/pragma.html#inline


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-20 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 20 May 2017 at 10:48:54 UTC, Gary Willoughby wrote:
In the following code, the `_foo` pointer (of the Foo struct) 
is null in the first call to the destructor. Why is this? I 
think it's got something to do with the foreach loop but I'm 
not sure. Any ideas?


Oof. Dangerous stuff. As Moritz pointed out, default opAssign 
will call the destructor on Foo. I should, however, elaborate 
further. You're dealing with uninitialized data. calloc() gives 
you zero-initialized block, which is not necessarily how Foo.init 
would look (it does in this case, but that's not true in general 
case).
malloc() gives you a potentially garbage-filled block, which is 
even more dangerous.


When filling an array of uninitialized values, use 
std.algorithm.moveEmplace(src, dst) instead of assignment. And, 
if you have destructors, you have to call the destructors 
manually when you free the array.
Furthermore, since Bar._data is an array of Foos, and Foo has a 
pointer in it, you might want to register the Bar._data array 
with the GC (GC.addRange, GC.removeRange). Unless you're willing 
to manually make sure that GC *never* sees those pointers.


Re: trait detecting anonymous union?

2017-05-22 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 22 May 2017 at 21:03:42 UTC, Bastiaan Veelo wrote:

`
void main()
{
import std.stdio;
struct S
{
int i;
union
{
int a;
double b;
}
}
S s;
writeln(s);  // S(10, #{overlap a, b})
import std.traits;
writeln([FieldNameTuple!S]); // ["i", "a", "b"]
}
`

Is there a way to detect at CT that S has overlapping data 
members, when an anonimous union is used as above?


Thanks,
Bastiaan.


There isn't a built-in one. The best I can muster at 1AM is 
finding all fields that have the same offset:


size_t[] memberOffsetsOf(T)()
{
size_t[] result;
foreach(i, _; typeof(T.tupleof))
result ~= T.tupleof[i].offsetof;
return result;
}

string[] overlappingFieldsOf(T)()
{
import std.traits : FieldNameTuple;
import std.range : array, enumerate;
import std.algorithm : map, filter, count;
enum offsets = memberOffsetsOf!T;
auto names = [FieldNameTuple!T];
bool isOverlapping(size_t i) {
return offsets.count(offsets[i]) > 1;
}
return names
   .enumerate
   .filter!(a => isOverlapping(a.index))
   .map!(a => a.value)
   .array;
}

void main()
{
import std.stdio;
struct S
{
int i;
union
{
int a;
double b;
}
int j;
union
{
struct { short n, m; }
float k;
}
}
S s;

writeln(overlappingFieldsOf!S); // ["a", "b", "n", "k"]
}

which is not quite the same as full overlap. This looks like a 
fun exercise, considering fields can also have arbitrary 
alignment...


Re: "if" is not evaluated for fields of Class.tupleof

2017-05-23 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 23 May 2017 at 06:42:55 UTC, Timoses wrote:

The easiest way is probably casting:

```
import std.traits;
import std.bitmanip;

class Test {
byte[4] marray;
byte mbyte;
}

void main() {
auto value = [0x12, 0x23, 0x34, 0x45, 0x56];
auto test = cast(Test*) value.ptr;
}
```


Don't cast arbitrary types to classes, you're going to stumble 
upon very nasty surprises :) I guess you meant struct?


Classes in D are quite fat, and don't start with data members 
right away, bookkeeping ClassInfo data comes first.


Re: templatized delegate

2017-05-23 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 23 May 2017 at 10:42:54 UTC, Nicholas Wilson wrote:

On Tuesday, 23 May 2017 at 10:30:56 UTC, Alex wrote:

On Monday, 22 May 2017 at 21:44:17 UTC, ag0aep6g wrote:
With that kind of variadics, you're not dealing with a 
template. A (run-time) variadic delegate is an actual 
delegate, i.e. a value that can be passed around. But the 
variadic stuff is a bit weird to use, and probably affects 
performance.


By the way, I'm not even sure, if variadics work in my case. I 
have a strange struct of a random generator, which cannot be 
copied, and I have no idea how to pass it to a variadic 
function:


import std.stdio;
import mir.random;

void main()
{
Random rndGen = Random(unpredictableSeed);
fun(rndGen);
}

void fun(...)
{

}

Yields "... is not copyable because it is annotated with 
@disable" :)


Random is copy @disabled to prevent incorrect use.
You need to pass it by ref or pointer. I dont know if you can 
pass variables as ref to a variadic, but you should be able to 
pass it by address.

fun();


void variadic(Args...)(auto ref Args args) { /* ... */ }

This infers whether you pass lvalues or rvalues. If passing 
further down the chain of such calls is needed, one can use 
std.functional : fowrard :


void variadic(Args...)(auto ref Args args) {
import std.functional : forward;
doStuff(forward!args);
}

void doStuff(Args...)(auto ref Args args) {
/* ... */
}

'forward' aliases ref arguments (i.e. passed lvalues) and moves 
value arguments (i.e. passed rvalues).


If a value is not copyable, it may be move-able (check the docs 
though, it may not be that either).


void fun(Args...)(auto ref Args args) { /*...*/ }

import std.algorithm : move;

auto a = NonCopyable(42);

fun(move(a));
// or:
func(NonCopyable(42));


Re: Structure of Arrays vs Array of Structures

2017-05-23 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 23 May 2017 at 16:48:31 UTC, Nordlöw wrote:

On Tuesday, 23 May 2017 at 16:46:18 UTC, Nordlöw wrote:

http://forum.dlang.org/post/wvulryummkqtskiwr...@forum.dlang.org


Correction; should be:

https://github.com/nordlow/phobos-next/blob/a324f16515bd1c3c1185ba0482dae2886d811bb1/src/soa.d


What if you instantiate it with a nested struct? What about 
structs that themselves aggregate other structs? What about 
custom operators on such structs?..


As I said earlier, generic solution is not easy. The 
implementation you have is very niche, certainly not "std.".


Re: templatized delegate

2017-05-23 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 23 May 2017 at 11:45:13 UTC, Alex wrote:

On Tuesday, 23 May 2017 at 11:05:09 UTC, Stanislav Blinov wrote:

void variadic(Args...)(auto ref Args args) { /* ... */ }

This infers whether you pass lvalues or rvalues. If passing 
further down the chain of such calls is needed, one can use 
std.functional : fowrard :


yes...



void variadic(Args...)(auto ref Args args) {
import std.functional : forward;
doStuff(forward!args);
}

void doStuff(Args...)(auto ref Args args) {
/* ... */
}

'forward' aliases ref arguments (i.e. passed lvalues) and 
moves value arguments (i.e. passed rvalues).


If a value is not copyable, it may be move-able (check the 
docs though, it may not be that either).


void fun(Args...)(auto ref Args args) { /*...*/ }


yes...


import std.algorithm : move;

auto a = NonCopyable(42);

fun(move(a));
// or:
func(NonCopyable(42));


the problem, that I have is, that I would like to use the 
templated approach, but I don't have the function, but only a 
delegate, so:


template(T, U...)
{
void delegate(ref T neededInput, ref U ignoredInput) dgPtr;
}

Not sure, if this is possible to handle at all...


Ah, now I think I get it. You want to store a single delegate 
that could be called with different sets of arguments? No, you 
can't do that: you need an actual delegate instance, and for 
that, you need to know the signature, at least when instantiating 
C.


Re: The syntax of sort and templates

2017-05-26 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 26 May 2017 at 11:27:19 UTC, zakk wrote:

I have a followup question: my background is C and in Wolfram 
Mathematica, so my knowledge of templates is limited to trivial 
examples in C++, like:


template 
const T& min(const T& lhs, const T& rhs)
{
return lhs < rhs ? lhs : rhs;
}

where the template argument is a type, and the function does 
the same job for different types.


It seems to me that when programming in D templates are 
something more powerful, is it correct of thinking of them as 
some argument which is known at compile time? Is this 
misleading?


It is :) Given your example above, 'template' doesn't mean just 
'type'. The whole definition is a template, i.e. that is a 
template function min. Or, in case of the original question, 
'sort' is a template. Not just it's arguments, but it itself.
But yes, templates are purely compile-time constructs. When you 
instantiate them with different arguments, you effectively get 
different functions in your code. Hence the name: compiler takes 
an existing definition (a template) and builds a whole new 
concrete function from it.


So if you were to call that C++ min function like this:

min(1, 2);

the compiler would generate a concrete function min, instantiated 
with T that is int, and then if you make this call:


min(1.5, 2.0);

then the compiler would generate *another* min, this time for 
type double. Note that double is of different size than int (i.e. 
usually int is 4 bytes, double is 8), and is also a 
floating-point type, not integral. So the compiler would have to 
issue different CPU instructions when generating code for it.


So now you get two different functions, but code for both of them 
has only been written once, the compiler takes care of the rest. 
Had 'min' not been a template, the programmer would have to write 
a new version by hand for every type needed, to get the most 
efficient code from the compiler.


Re: The syntax of sort and templates

2017-05-26 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 26 May 2017 at 09:59:26 UTC, zakk wrote:

Hello everyone,

I just started using D and I am a bit puzzled by the syntax of 
the sort function is std.algorithm.sorting, which is


sort!(comparingFunction)(list)

where comparingFunction is often a lambda expression. For 
instance in the Wolfram Language the equivalent function is


Sort[list,comparingFunction]

My questions are:

1) Why is D making using of the binary ! operator, which as far 
as I understand introduces a template?


The ! operator is needed to distinguish template arguments, 
passed and known at compile time, from actual function arguments, 
passed and known at run time. "!" doesn't "introduce" a template. 
The definition of 'sort' is a template, sort!(fn)(list) is an 
instantiation of that template with concrete arguments.


In C++, template arguments are denoted with <>, which is more 
verbose and introduces syntax ambiguity in complex templates. D 
avoids that by using the !.



2) Why is a template needed here?


Templates are a form of polymorphism that works at compile time. 
It allows the programmer to write, and the compiler to generate, 
the most efficient an/or the most practical code given the 
concrete use case. The net effect is that at runtime you get the 
sorting function that is tailored for the specific types and 
comparison predicate, as if it was written by hand.



3) It seems to me like the argument passed to the template is a 
lambda expression. I only know about templates taking types as 
argument. What's going on?


In D, depending on their definition, templates can take types, 
values or symbols as arguments. In this case, sort takes the 
comparison function and inserts it directly into the algorithm, 
which enables the compiler to inline it and/or perform various 
other optimizations, which would've been harder or impossible to 
do if the function was only known at runtime.
Also, this enables writing concise code: in Phobos, algorithms 
that take predicates allow to pass them as string literals 
instead of full-blown functions:


sort!"a < b"(list);

The "a < b" will be transformed at compile time into (a, b) => a 
< b.


Re: Out of memory error (even when using destroy())

2017-05-26 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 26 May 2017 at 18:06:42 UTC, Mike B Johnson wrote:

On Friday, 26 May 2017 at 14:05:34 UTC, ag0aep6g wrote:

On 05/26/2017 10:15 AM, realhet wrote:
But hey, the GC knows that is should not search for any 
pointers in those large blocks.
And the buffer is full of 0-s at the start, so there can't be 
any 'false pointers' in it. And I think the GC will not 
search in it either.


The issue is not that the block contains a false pointer, but 
that there's a false pointer elsewhere that points into the 
block. The bigger the block, the more likely it is that 
something (e.g. an int on the stack) is mistaken for a pointer 
into it.


Wow, if that is the case then the GC has some real issues. The 
GC should be informed about all pointers and an int is not a 
pointer.


What is a pointer if not an int? :)

That is not an issue. The GC holds off releasing memory if 
there's even a suspicion that someone might be holding on to it. 
In most problems, ints are small. Pointers are always big, so 
there's not much overlap there. Accidents do happen occasionally, 
but it's better to have a system that is too cautious than one 
that ruins your data.


Working with huge memory chunks isn't really a domain for GC 
though.


Re: Extern C and Symbol Mangling

2017-05-26 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 26 May 2017 at 12:49:27 UTC, Oleksii wrote:

Hi,

I'm trying to link against a DLL which exports a bunch of C 
functions. The issue is: C symbols do not have underscore 
prefix in Windows, but DMD sticks underscore in front of the 
symbol name. For example: `extern(C) void Foo()` becomes `_Foo`.


Is there a way to disable that underscore?



Use extern(Windows), or the more general extern(System), which 
will expand to either extern(C) or extern(Windows), depending on 
the OS you target.


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 21 May 2017 at 12:48:10 UTC, Adam D. Ruppe wrote:

On Saturday, 20 May 2017 at 10:48:54 UTC, Gary Willoughby wrote:

// Why is this._foo null here???


The others have answered why and what to do, but note that 
according to the spec, that any struct should be able to have 
its destructor called, so you should do a null check in there 
anyway.


Not if you either emplace() or blit Foo.init into all of the 
array elements.


Re: Multiple template variadic list not working

2017-05-21 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 21 May 2017 at 15:13:55 UTC, bastien penavayre wrote:
I've been trying to translate the following idea expressed here 
in c++:


template 
void func(Arguments... args) {}

so I tried

void func(UserArgs..., Arguments...)(Arguments args) {}

and then

void func(Args...)(Filter!(isType, Args) args) {}

but nothing works.
This seems like something simple to handle, why is it not then ?


In this case, eponymous template should do the trick:

template func(UserArgs...) {
void func(Arguments...)(Arguments args) {}
}


Re: Default class template parameter

2017-05-27 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 27 May 2017 at 19:23:59 UTC, Igor Shirkalin wrote:

Hi,

I try to make a class template with single template argument 
defaulted to some type.
Is it possible to use the name of class without specification 
of template argumet (no '!' operator)?


Example:

class ClassName(T=double) {
this(T value) { /// do some stuff here
}
/// some other stuff..
}


void main() {
a = ClassName(1.2); /// error:  cannot deduce function from 
argument types !()(int)

a = ClassName!double(1.2); /// OK
}

It seems the compiler treats 'ClassName' as function, but it is 
obvious that it should treat it as 'ClassName!double'.


No, you'd have to at least write

auto a = new ClassName!()(1.2);

Or you could define a make function:

auto makeClassName(T = double)(T value) {
return new ClassName!T(value);
}

auto a = makeClassName(1.2);


Re: Out of memory error (even when using destroy())

2017-05-27 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 27 May 2017 at 17:57:03 UTC, Mike B Johnson wrote:

And what if one isn't interfacing to C? All pointers should be 
known. You can't access memory by and int or any other 
non-pointer type! Hence, when pointers are created or ints are 
cast to pointers, the GC should be informed and then handle 
them appropriately


Eh? So *every* cast from and to a pointer should become a call 
into the runtime, poking the GC? Or rather, every variable 
declaration should somehow be made magically known to the GC 
without any runtime cost?


(then, instead of scanning a 100MB block of memory for 
"pointers" it should scan the list of possible pointers(which 
will generally be much much lower).


That's precisely what it does, it scans the possible suspects, 
nothing more. That is, the stack (it has no idea what's there, 
it's just a block of untyped memory), memory it itself allocated 
*only if* it needs to (e.g. you allocated a typed array, and the 
type has pointers), memory you've specifically asked it to scan. 
It won't scan that block of 500k ints the OP allocated, unless 
told to do so. It would scan it if it was a void[] block though.


Therefor, in a true D program(no outsourcing) with no pointers 
used, the GC should never have to scan anything.


No pointers used? No arrays, no strings, no delegates?.. That's a 
rather limited program. But thing is, you're right, in such a 
program the GC will indeed never have to scan anything. If you 
never allocate, GC collection never occurs either.


It seems the GC can be smarter than it is instead of just 
making blanket assumptions about the entire program(which 
rarely hold), which is generally always a poor choice when it 
comes to performance...


Unnecessary interaction with the GC, e.g. informing it about 
every cast, is a poor choice for performance.


After all, if we truly want to be safe, why not scan the entire 
memory of the system? Who knows, some pointer externally might 
be peeping in on our hello world program.


What?


Re: RAII pointers

2017-05-29 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 29 May 2017 at 23:39:17 UTC, Russel Winder wrote:
C++ allows one to create types that are pointer types but wrap 
a primitive pointer to give RAII handling of resources. For 
example:



class Dvb::FrontendParameters_Ptr {
private:
dvb_v5_fe_parms * ptr;
public:
	FrontendParameters_Ptr(FrontendId const & fei, 
unsigned int const verbose = 0, unsigned int const legacy = 0);
	FrontendParameters_Ptr(FrontendParameters_Ptr const &) 
= delete;
	FrontendParameters_Ptr & 
operator=(FrontendParameters_Ptr const &) = delete;

~FrontendParameters_Ptr() {dvb_fe_close(ptr); }
dvb_v5_fe_parms * c_ptr() const { return ptr; }
dvb_v5_fe_parms * operator->() const { return ptr; }
};


Has anyone any experience of doing the analogous thing 
idiomatically in D.


I just re-realised I manually constructed a C++ abstraction 
layer around some of libdvbv5, so I am going to do the same for 
D. However whilst I (sort of) understand doing the wrapping 
with C++, I am not sure I have seen anyone wrapping C pointers 
with RAII in D.


I've found this pattern works rather well:

module frontendparametersptr;

struct FrontendParametersPtr
{
// No constructors, initialization with parameters
// is done via the frontendParametersPtr function
@disable this(this);

~this()
{
// null check is often useful to detect e.g.
// if this object has been `move`d
if (_ptr) dvb_fe_close(_ptr);
}

// with DIP1000, could also return `scope`
inout(dvb_v5_fe_parms)* ptr() inout { return _ptr; }
alias ptr this;
package:

void construct(/*your args here*/) { /*...*/ }

private:
dvb_v5_fe_parms* _ptr;
}

/// Replaces constructor, i.e. can be called with no arguments for
/// replacing "default" construction of C++
auto frontendParametersPtr(Args...)(auto ref Args args)
{
import std.functional : forward;
FrontendParametersPtr result = void;
result.construct(forward!args);
return result; // moves result, no copy is made
}

///-

module app;

import frontendparametersptr;

void main()
{
auto ptr = frontendParametersPtr(/* your args here */);
}


The main idea is that construction is handled by the `construct` 
function (which could be overloaded), instead of `this(...)` 
constructors: this way client code would either get 
default-initialized (.init) pointers, or those constructed with 
appropriate arguments (even with no arguments, if such is needed).

Disabling copying is obvious.
The rest depends on taste and purpose.


Re: howto count lines - fast

2017-05-30 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 30 May 2017 at 23:41:01 UTC, H. S. Teoh wrote:

This little challenge piqued my interest.  So I decided to take 
a shot at seeing if I could beat my system's /usr/bin/wc -l.


First order of business: whenever it comes to performance, 
always choose the right compiler for the job...





Woohoo!!! Finally, we beat the system's wc -l!! And by a pretty 
fair margin, too.  Eat your heart out, wc!!!  (The large user 
time is because we're using all 6 cores at once. But the actual 
elapsed time is shorter.)



Hm... I cheated a little bit: took your program and compiled with 
`ldc2 -release -O3 -mcpu=skylake`. For data I took std.datetime 
concatenated 1000 times (35446000 lines). Results (minimum of 10 
runs each):


wc -l
real 0.50
user 0.40
sys 0.09

lineCount1
real 0.23
user 0.19
sys 0.04

lineCount2
real 0.29
user 0.17
sys 0.12

lineCount3
real 0.23
user 0.18
sys 0.04

lineCount4
real 0.22
user 1.52
sys 0.04

Seems like all of them beat wc, so machine and compiler matter a 
great deal in this comparison. Thing is, on small files wc is 
going to win pretty much always, due to D's clunky startup. But 
with larger ones - wc falls far behind.
Interestingly, both lineCount1 and lineCount3 on this machine are 
nearly even with lineCount4 :)


Re: difference between x = Nullable.init and x.nullify

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 08:01:14 UTC, Jonathan M Davis wrote:
On Saturday, June 03, 2017 06:41:44 Stanislav Blinov via 
Digitalmars-d-learn wrote:
On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis 
wrote:
> looking at what rt_finalize does, I don't see why it 
> couldn't be nothrow. So, unless I'm missing something, it 
> seems like that would be a good enhancement.

>
> - Jonathan M Davis

Presently, rt_finalize cannot be made nothrow, or un-made 
@system, because "reasons": 
http://forum.dlang.org/thread/aalafajtuhlvfirwf...@forum.dlang.org


Fixing that would require significant changes to the runtime, 
and probably the compiler. I don't think it qualifies as a 
simple "enhancement" :)


Well, as I said, I could be missing something, but all 
rt_finalize does is call rt_finalize2, and rt_finalize2 _is_ 
nothrow (it catches any Exceptions that are thrown by the 
destructor/finalizer). So, I have no idea why it would be the 
case that rt_finalize couldn't be nothrow, and I saw nothing in 
that thread which contradicts that, but I could have read it 
too quickly. Regardless, it's a perfectly valid enhancement 
request whether it's easy to implement or not.


- Jonathan M Davis


Whoops, my bad, I forgot it indeed swallows exceptions and does 
the onFinalizeError instead. So... yep, then it seems that 
rt_finalize probably should be marked nothrow too. Hmm... if 
throwing in a destructor is considered a runtime error, perhaps 
another valid enhancement would be to statically disallow 
throwing Exceptions in destructors, i.e. *require* them be 
nothrow?..


Re: difference between x = Nullable.init and x.nullify

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 06:19:29 UTC, Jonathan M Davis wrote:

looking at what rt_finalize does, I don't see why it couldn't 
be nothrow. So, unless I'm missing something, it seems like 
that would be a good enhancement.


- Jonathan M Davis


Presently, rt_finalize cannot be made nothrow, or un-made 
@system, because "reasons":

http://forum.dlang.org/thread/aalafajtuhlvfirwf...@forum.dlang.org

Fixing that would require significant changes to the runtime, and 
probably the compiler. I don't think it qualifies as a simple 
"enhancement" :)


Re: string to wchar*?

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 23:36:18 UTC, Mike B Johnson wrote:


https://dlang.org/phobos/std_utf.html#toUTF16z


This didn't work. More errors than the first.


Works for me:

void main()
{
import std.conv;
import std.stdio;
import core.stdc.wchar_;
import core.stdc.stdio;

auto f = fopen("hello.bin", "w,ccs=UTF16LE");
scope (exit) fclose(f);

import std.utf;
string hello = "Привет";
wchar bom = '\ufeff';
auto str = hello.toUTF16z;
fputwc(bom, f);
while (str && *str) {
fputwc(*str, f);
++str;
}
}

$ rdmd wchartest.d
$ file hello.bin
hello.bin: Little-endian UTF-16 Unicode text, with no line 
terminators


$ hexdump hello.bin
000 feff 041f 0440 0438 0432 0435 0442

$ iconv -f UTF-16LE hello.bin
Привет


In any case, it conv should work.


No, it shouldn't. char* et al. are not string types in D. 
to!(char*)(string) just doesn't make sense.


Re: RAII pointers

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 19:55:30 UTC, ag0aep6g wrote:

On 06/03/2017 09:37 PM, Moritz Maxeiner wrote:
Of course, but AFAIK you'd need to explicitly assign it to an 
object, so `ptr` won't null by accident, but only by explicit 
programmer intent (same as overwriting the memory the object 
lives in via things like `memcpy`); and you can always screw 
things intentionally (you could also assign some invalid value 
to the pointer via `memcpy`).


I'd say `.init` can easily happen accidentally. Especially when 
`@disable this(this);` is involved.


When you can't copy, you may have to move sometimes. But 
std.algorithm.move overwrites the old location with `.init`, 
assuming that `.init` can safely be destroyed.



struct S
{
void* ptr;
@disable this(this);
~this() { assert(ptr !is null); /* fails */ }
}

void f(S s) {}

void main()
{
auto a = S(new int);
import std.algorithm: move;
f(move(a)); /* overwrites `a` with `S.init` */
}



Yep, that's exactly why I added the null check in the example. If 
the struct has a postblit or a destructor, `move` will be 
destructive, and will overwrite the source with .init. Sometimes 
it doesn't matter (i.e. free() is allowed to take a null 
pointer), but in general, for things like smart pointers where 
you'd do arbitrary access in destructor, it's a good habit to 
check for .init values first, in case the object has been moved.


Re: RAII pointers

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 21:39:54 UTC, Moritz Maxeiner wrote:
On Saturday, 3 June 2017 at 21:16:08 UTC, Stanislav Blinov 
wrote:
On Saturday, 3 June 2017 at 20:53:05 UTC, Moritz Maxeiner 
wrote:


Quite, but if you backtrack to my initial statement, it was 
about ptr not being/becoming null (implicitly) in the first 
place, which *might* allow you to skip the check (if you 
don't set it to null via external means, such as memcpy, 
move, etc).


It's only true as long as you have full control of the source.
Once you're using libraries and generic code, it's possible 
that it's out of your hands:


It's always true, because I explicitly wrote *might*, not 
*will*, to indicate that it depends on your use case. Your 
example is a common use case where you can't skip the check.


Programmers and their tight-binding logic...

- Honey, please buy a loaf of bread. If there are eggs, buy a 
dozen.

...
- Hello, do you have eggs?
- Yes.
- Dozen loaves of bread, please.

;)


Re: string to wchar*?

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 22:54:22 UTC, Mike B Johnson wrote:


How to convert a string to wchar*?


C-style null-terminated wchar*?

https://dlang.org/phobos/std_utf.html#toUTF16z


Re: RAII pointers

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 20:53:05 UTC, Moritz Maxeiner wrote:
On Saturday, 3 June 2017 at 20:25:22 UTC, Stanislav Blinov 
wrote:
On Saturday, 3 June 2017 at 20:13:30 UTC, Moritz Maxeiner 
wrote:


Calling std.algorithm.move is explicit programmer intent, I 
consider that about as accidental as calling memcpy with a 
source full of zeroes.
In any case, having that check in the destructor is fairly 
cheap, so better safe than sorry (and include it).


Yes, it's explicit. Destructor call is still implicit though, 
and it better not be performing null dereference or something 
equally nasty :)


Quite, but if you backtrack to my initial statement, it was 
about ptr not being/becoming null (implicitly) in the first 
place, which *might* allow you to skip the check (if you don't 
set it to null via external means, such as memcpy, move, etc).


It's only true as long as you have full control of the source. 
Once you're using libraries and generic code, it's possible that 
it's out of your hands:


import core.stdc.stdio;
import std.exception;

// external library
struct RingBuffer(T,size_t size) {
T[size] values = T.init; // the culprit
// interface snipped...
}

// own code
struct FileWrapper {
FILE* file;

@disable this();
@disable this(this);

this(FILE* file) {
enforce(file);
this.file = file;
}

~this() {
fclose(file);
}
}

void main() {
// whoops, segfault
RingBuffer!(FileWrapper,8) container;
}



Re: How to Compare 2 objects of the same class

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 22:38:31 UTC, Mark wrote:

In the future I'll include a compilable example. I was having 
problems with a class I made which is about 45 lines, that 
might be a lot of code for a post.


You can use external resources such as:

https://d.godbolt.org/
https://dpaste.dzfl.pl

to paste code there and then just post a link to a paste here.



Re: difference between x = Nullable.init and x.nullify

2017-06-04 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 4 June 2017 at 09:04:14 UTC, Jonathan M Davis wrote:

if throwing in a destructor is considered a runtime error, 
perhaps another valid enhancement would be to statically 
disallow throwing Exceptions in destructors, i.e. *require* 
them be nothrow?..


My initial reaction would be that destructors should always be 
nothrow, though I vaguely recall there being some reason why it 
was supposed to be nice that destructors in D could cleanly 
deal with exceptions. And remember that when we're talking 
about rt_finalize, we're talking about finalizers, not 
destructors in general. When a destructor is in a GC 
heap-allocated object, it's treated as a finalizer and may or 
may not be run (since the object may or may not be collected),


It doesn't matter. The only thing that matters is that it may be 
run, and therefore rt_finalize has to count on that. And it sort 
of does, at the moment, by assuming the worst possible 
combination of attributes. Problem is, with current language 
rules, it cannot be any other way, as the runtime doesn't carry 
any information about attributes of finalized object, or the 
context in which finalization takes place (i.e. is it within a 
@safe function?), which, sadly, makes unsafe code silently 
executable in a safe context, in direct contradiction to language 
guarantees.


whereas when a destructor is on an object that's on the stack, 
it's really a destructor. So, while they use the same syntax,


It's worse than that. There are two "destructors": __xdtor that 
calls destructors of RAII members, and, on classes, __dtor that 
actually calls ~this() for the class. But only that class, not 
it's ancestors or descendants. Such segregation is, as it turns 
out, as useful as it is unwieldy.


and in the case of a struct, the same function could be either 
a destructor or a finalizer depending on where the struct is 
declared, they're not quite the same thing. And destroy muddies 
the water a bit, because it then explicitly calls the finalizer 
on a class, whereas it would normally be the GC that does it 
(and while calling GC-related functions in a finalizer is 
forbidden when called by the GC, it's fine when called via 
destroy, since the GC is then not in the middle of a 
collection).


So, I don't know whether it would be reasonable to require that 
destructors be nothrow. Certainly, it's _more_ likely for it to 
be reasonable for destructors on classes to be nothrow, since 
classes always live on the heap (and are thus finalizers) 
unless you're playing games with something like 
std.typecons.scoped, but I'd have to study the matter quite a 
bit more to give a properly informed answer as to whether it 
would be reasonable to require that all destructors be nothrow.


Scoped is not necessary. Classes may not necessarily exist in the 
GC heap, thanks to custom allocators and emplace(). But because 
the language does not enforce propagation of destructor 
attributes, destroy() is @system and not nothrow, which spills 
out into user code that would otherwise take advantage of static 
inference. Unfortunately, right now making it any other would 
impose certain restrictions on classes without real language 
support, and that is... scary.


Re: .sort vs sort(): std.algorithm not up to the task?

2017-06-07 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 8 June 2017 at 01:57:47 UTC, Andrew Edwards wrote:
Ranges may be finite or infinite but, while the destination may 
be unreachable, we can definitely tell how far we've traveled. 
So why doesn't this work?


import std.traits;
import std.range;

void main()
{
string[string] aa;

// what others have referred to as
// standard sort works but is deprecated
//auto keys = aa.keys.sort;

// Error: cannot infer argument types, expected 1 argument, 
not 2

import std.algorithm: sort;
auto keys = aa.keys.sort();

// this works but why should I have to?
//import std.array: array;
//auto keys = aa.keys.sort().array;

foreach (i, v; keys){}
}

If I hand you a chihuahua for grooming, why am I getting back a 
pit bull? I simply want a groomed chihuahua. Why do I need to 
consult a wizard to get back a groomed chihuahua?


aa.keys.sort() should just work as is: aa.keys returns a 
string[], and that's a random access range that can be sorted. 
What exactly is the error?


Re: .sort vs sort(): std.algorithm not up to the task?

2017-06-07 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 8 June 2017 at 02:25:17 UTC, Jonathan M Davis wrote:

Oh I see, the was error related to iteration, not sorting.

Ranges do not support iterating with an index. The workaround 
if you want to have an index with ranges and foreach, then you 
should use lockstep:


http://dlang.org/phobos/std_range.html#lockstep

e.g.

foreach(i, v; lockstep(iota!size_t(0), s))
{}

or

foreach(i, v; lockstep(iota(0), s))
{}


There's an enumerate(): 
https://dlang.org/phobos/std_range.html#enumerate


import std.algorithm : sort;
import std.range : enumerate;

foreach(i, k; aa.keys.sort().enumerate) {
/* ... */
}


Re: "Lazy" initialization of structs

2017-06-01 Thread Stanislav Blinov via Digitalmars-d-learn
On Thursday, 1 June 2017 at 12:04:05 UTC, Daniel Tan Fook Hao 
wrote:

Somehow this code works for me:

```D
auto error (int status, string description){
struct Error {
int status;
string description;
}
Error err = {
status,
description
};
return err.serializeToJson;
}
```

which is supposed to be the same as

```D
struct Error {
int status;
string description;
}
auto error (int status, string description){
Error err = {
status,
description
};
return err.serializeToJson;
}
```


It's not really the same, the structs will have a different type: 
in the first case, it'd be modulename.error.Error, while in the 
second case it's just modulename.Error. Furthermore, if Error 
declared inside the function had methods, it'd become a `nested` 
struct, which carries a context pointer.


If I'm reading this right, in the former, the struct is created 
when the function is called in run-time, and the type is then 
inferred after that? I don't really understand the behavior 
behind this.


No, nothing happens at run time, the type is known statically, it 
is inferred from the `return` statement in that function: 
https://dlang.org/spec/function.html#auto-functions.
If you omit the type or specify 'auto', the compiler will look at 
your `return`s (if any) and try to infer the type from them. If 
they clash (i.e. you're trying to return different types from the 
same function), it's a compile-time error. Otherwise, it's 
whatever type is being returned.


Re: .sort vs sort(): std.algorithm not up to the task?

2017-06-07 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 8 June 2017 at 04:07:22 UTC, Andrew Edwards wrote:

On Thursday, 8 June 2017 at 03:40:08 UTC, Jonathan M Davis


sort() returns a SortedRange so that other algorithms can 
know...


Yes, I understand that. Again, using "std.range: release" earns 
me nothing more than I already get from "std.array: array" or 
if you prefer "std.range: array".


Earns you nothing? How about not performing an allocation and 
copy?


I can understand if sort returns Range by default but can be 
instructed to return the original representation.




 aa.keys.sort!returnOriginalRepresentation; // or something 
to that effect


"Something to that effect" is exactly this:

aa.keys.sort().release;

No need to import anything but std.algorithm : sort.

But it doesn't, it decides what i'm gonna get like it or not. 
But the fact, a lot of times I just want to work with the 
underlying data after the operation is performed. And it should 
be noted that this applies to Ranges in general not just sort.


A crucial point of any good design is to *not rob the caller of 
useful information*. sort() follows that philosophy. If you don't 
need the extra information, you're free to get rid of it. The 
other way around that you seem to be proposing would require 
having a ton of overloads for sort() for any imaginable use case.


Re: RAII pointers

2017-06-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 3 June 2017 at 20:13:30 UTC, Moritz Maxeiner wrote:

Calling std.algorithm.move is explicit programmer intent, I 
consider that about as accidental as calling memcpy with a 
source full of zeroes.
In any case, having that check in the destructor is fairly 
cheap, so better safe than sorry (and include it).


Yes, it's explicit. Destructor call is still implicit though, and 
it better not be performing null dereference or something equally 
nasty :)


Re: byLine(n)?

2017-06-11 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 11 June 2017 at 05:36:08 UTC, helxi wrote:
I was writing a program that reads and prints the first nth 
lines to the stdout:


import std.stdio;

void main(string[] args)
{
import std.algorithm, std.range;
import std.conv;
stdin.byLine.take(args[1].to!ulong).each!writeln;
}

As far as I understand the stdin.byLine.take(args[1].to!ulong) 
part reads all the lines written in stdin.

What if I want to make byLine read only and only first nth line?

stdin.byLine(args[1].to!ulong).each!writeln;

Obviously the code above won't work. Is there any efficient 
workaround?


You need only the nth line? Then you'd need to `drop` the 
preceding ones:


void main(string[] args) {
import std.algorithm, std.range, std.stdio, std.conv;
stdin.byLine.drop(args[1].to!int-1).front.writeln;
}

Or if you need every nth line, combine `drop` and `stride`:

void main(string[] args) {
import std.algorithm, std.range, std.stdio, std.conv;
auto step = args[1].to!int;
stdin.byLine.drop(step-1).stride(step).each!writeln;
}



Re: Looking for an equivalent to C++ std::getline in D

2017-05-07 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 7 May 2017 at 10:33:25 UTC, k-five wrote:

On Sunday, 7 May 2017 at 09:46:22 UTC, Patrick Schluter wrote:

On Saturday, 6 May 2017 at 10:15:03 UTC, k-five wrote:


If you want to learn the basis of the range concept and their 
link to C++ Iterators, you should definitively read Andrei's 
article on them in the InformIT magazine. Here is the link

http://www.informit.com/articles/printerfriendly/1407357
required read for every aspiring D programmer ;-)


---

Thanks for the article.

Although I found D for being more better, nicer,and fun than 
C++ is, but there is a few questions on Stack-Over-Flow, videos 
on Youtube, and  some other forums in my country. So, why D is 
not popular?


Because everyone is asking this question instead of actually 
doing something about it :)
To be fair, D has a good amount of usage even today, it's just 
not being screamed about ecstatically.



I am a big fan of Perl-one-liner and after seeing
rdmd --evel='one-line-code'
I gasped! Oh, really? a one-liner with D!

Or even Unix Command Line, that D has Uniform Function Call 
Syntax.

line.sort.uniq.writeln();

It may you know about the future of D or may introduce some 
other articles about the future of D to me. Since after 
learning C++ I am not very comfortable with.


Today is the last day of the D Conference 2017, last three days 
it was livestreaming. There were quite a bit of talks on current 
developments and future progress. The videos from those streams 
should appear at https://www.youtube.com/user/sociomantic/videos 
hopefully early next week. They also have previous conference 
videos out there.


Re: The .obj file, what is it?

2017-05-03 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 3 May 2017 at 10:55:44 UTC, I Lindström wrote:
So, a question from a beginner. What is the .obj file that 
appears after the source is compiled into the executable? I 
can't find a good explanation on the Net for it. I take it the 
file has to accompany the executable for the program to 
function since the online explanations I've found say it 
contains instructions and is related to memory management? It's 
been bugging me from the start.


The source is not compiled into the executable. The source is 
compiled into a "object code", output into an "object file" - in 
this case, the .obj file. Afterwards, object files are linked by 
a linker (usually also taking other object files and/or 
libraries) to produce an executable or a library.
.obj files are not needed to be redistributed, they've served 
their purpose when the final target executable or library has 
been created. But it's useful to keep them in the development 
environment, as usually the build environment would not spend 
time recompiling the code when an up-to-date object files are 
present.


Re: Looking for an equivalent to C++ std::getline in D

2017-05-05 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 5 May 2017 at 09:54:03 UTC, k-five wrote:

Hi all.
I have a simple command-line program utility in C++ that can 
rename or remove files, based on regular expression.
After finding D that is more fun than C++ is, I want to port 
the code, but I have problem with this part of it:


std::getline( iss, match, delimiter );
std::getline( iss, substitute, delimiter );

I need to read from iss ( = std::istringstream iss( argv[ 1 ] ) 
and separate them by delimiter.


Since the program gets the input from a user, and it can be 
something like: 's/\d+[a-z]+@(?=\.)//g'  or '/[A-Za-z0-9]+//'


So for: s/\d+[a-z]+@(?=\.)//g
I need:
s
\d+[a-z]+@(?=\.)
g

and for: /[A-Za-z0-9]+/
It should be:
[A-Za-z0-9]+

---

I tired ( std.string: split or format ) or ( std.regex split ). 
In fact I need to read from a stream up to a delimiter.


Does someone knows a way to do this in D? Thanks


So, you need to consume input one element at a time (delimited), 
dropping empty elements? Try std.algorithm.iteration splitter and 
filter:


auto advance(Range)(ref Range r)
{
assert(!r.empty);
auto result = r.front;
r.popFront();
return result;
}

void main(string[] args)
{
import std.algorithm.iteration : splitter, filter;
import std.range : empty;

auto input = args[1].splitter('/').filter!"!a.empty"();

import std.stdio : writeln;
while (!input.empty)
writeln(input.advance());
}

The advance() function reads the next delimited element and pops 
it from the range.


Re: Looking for an equivalent to C++ std::getline in D

2017-05-06 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 6 May 2017 at 10:15:03 UTC, k-five wrote:

On Saturday, 6 May 2017 at 08:53:12 UTC, Jonathan M Davis wrote:
On Saturday, May 6, 2017 8:34:11 AM CEST k-five via 
Digitalmars-d-learn wrote:

On Friday, 5 May 2017 at 17:07:25 UTC, Stanislav Blinov wrote:
> On Friday, 5 May 2017 at 09:54:03 UTC, k-five wrote:


-

Although I am not sure but it may Range in D, has the same 
concept that C++ has on iterator, like InputIterator or 
OutputIterator, since I realized that the output of [ filter ] 
does not have RandomAccessRange so I can not use input[ 0 ]. 
But I can use input.front().


Also thank you @Stanislav Blinov, I am familiar with lambda but 
have never seen a lambda in shape of string :)


-

Solving the problem by using
split and empty in std.string
or splitter in std.algorithm or splitter in std.regex

plus
filter in std.algorithm,
and accessing the elements by:
input.front()
input.popFront()

-

for input:
import std.stdio : print = writeln;
import std.algorithm: filter;
import std.string: split, empty;

void main() {

immutable (char)[] str = "one//two//three";

	auto input = str.split( '/' ).filter!( element => 
!element.empty

 )();

print( input.front );
input.popFront();
print( input.front );
input.popFront();
print( input.front );

}

the output is:
one
two
three


str.split('/') is eager, that is, it will iterate the input and 
return the array of delimited elements. So in fact you're getting 
an array of all elements (even empty ones), and then filtering 
it, ignoring empty elements.
If you want to get the output as an array, it's better to use 
std.array as Jonathan mentioned:


import std.array : array;
auto inputArray = str.splitter('/').filter!(a => 
!a.empty)().array;


This will eagerly consume the results of filter and put them into 
an array.


Re: Looking for an equivalent to C++ std::getline in D

2017-05-06 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 6 May 2017 at 08:34:11 UTC, k-five wrote:


Also what is the parameter "a.empty" for template filter


Jonathan covered the type part. As for that last bit, the filter 
template takes a predicate as parameter. This predicate is called 
for each input element, and if returns false, the element is 
ignored. The predicate can be a function, or, for example, a 
lambda:


auto input = args[1].splitter('/').filter!((string s) { return 
!s.empty; })();


or a template lambda:

auto input = arga[1].splitter('/').filter!((s) => !s.empty)();

By convention, predicates in Phobos can also be compile-time 
strings. In that case, std.functional.unaryFun is used to turn 
that string into a function. By default, unaryFun names the 
argument 'a', so the "!a.empty" will be expanded by unaryFun into 
(a) => !a.empty.


Re: How to get field default value at CT

2017-05-06 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 6 May 2017 at 21:40:24 UTC, Mike B Johnson wrote:

I'd like to get the value assign to a field at CT.

struct
{
int x = 3434;

}

I'd like to get the assigned "value" 3434 for x at CT.


Use the .init property:

struct S
{
int x = 3434;
}

unittest
{
static assert(S.init.x == 3434);
}

void main()
{
enum xAtCT = S.init.x;

pragma(msg, xAtCT);
}



Re: Equivalent to nullptr

2017-05-03 Thread Stanislav Blinov via Digitalmars-d-learn
In the meantime, you can get around the issue by redeclaring the 
function with another name and loading it manually just after 
calling DerelictSDL2.load():



import derelict.sdl2.sdl;

__gshared SDL_bool function (const(SDL_Point)*, int, 
const(SDL_Rect)*, SDL_Rect*) SDL_EnclosePoints_;


void main()
{
   DerelictSDL2.load();
   DerelictSDL2.bindFunc(cast(void**)_EnclosePoints_, 
"SDL_EnclosePoints");

   // ...
}


Now you'd need to call SDL_EnclosePoints_ instead of 
SDL_EnclosePoints.


Re: site examples

2017-05-25 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 25 May 2017 at 15:41:47 UTC, crimaniak wrote:

It seems to me that examples on the site require additional 
work and in the current form are counterproductive in terms of 
attracting new users.


https://github.com/dlang/phobos


Re: Searching strings with indexOf vs countUntil

2017-05-25 Thread Stanislav Blinov via Digitalmars-d-learn

On Thursday, 25 May 2017 at 18:13:15 UTC, Anonymouse wrote:

Part of the strings I'm working with can be assumed to be only 
ASCII, yes. indexOf only wants strings or char[]s, but 
interestingly if I use the same benchmark but have countUntil 
work on raw ubyte[]s, it is faster. See 
https://dpaste.dzfl.pl/2e095f7d18be.


There's a less ugly cast in std.string:

import std.string : representation;

//(cast(ubyte[])line).countUntil(cast(ubyte[])" :");
line.representation.countUntil(" :".representation);


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 21 May 2017 at 23:59:08 UTC, Guillaume Piolat wrote:

On Sunday, 21 May 2017 at 12:48:10 UTC, Adam D. Ruppe wrote:

Any struct should be able to have its destructor called


Does this rule also applies to class objects?


Yes. If your destructor does modify the state, you should expect 
it to be called and have the state ready for it.


When you're using the GC, destructors *may* not be called under 
certain conditions:


http://dlang.org/spec/class.html#destructors

But there's no stopping you from destructing manually (via 
destroy() call), or by allocating classes manually via malloc or 
on the stack.


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 22 May 2017 at 00:23:26 UTC, Adam D. Ruppe wrote:

On Sunday, 21 May 2017 at 14:13:20 UTC, Stanislav Blinov wrote:
Not if you either emplace() or blit Foo.init into all of the 
array elements.


You especially need to be safe calling ~this on Foo.init.


How so? .init is supposed to be destructible without question. 
destroy() calls in the runtime also blit the initializer back 
over the destructed objects. std.algorithm.move et al. 
specifically take advantage of .init (blit it over the moved-from 
object, so it can either be destructed or assigned something 
else).


I can't think of any case where you'd want preconditions on 
destructor when the object is in .init state.


Re: Why would an initialised struct pointer field be null in the struct's destructor?

2017-05-21 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 22 May 2017 at 00:45:27 UTC, Adam D. Ruppe wrote:

On Monday, 22 May 2017 at 00:36:24 UTC, Stanislav Blinov wrote:
I can't think of any case where you'd want preconditions on 
destructor when the object is in .init state.


I think we're actually saying the same thing: I mean the 
destructor must be callable on .init so you might do like


struct Foo {
   int* ptr;
   ~this() {
  // might be called with ptr is null cuz of .init
  // so wanna check
  if(ptr !is null) free(ptr);
}
}


Ah, yes, exactly. The page is indeed the same one.

P.S. Though it's fine to call free with a null pointer :P


Re: Details on how aggregates are constructed with `new` and later destroyed by the GC

2018-10-08 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 8 October 2018 at 11:19:40 UTC, Per Nordlöw wrote:
And how this is related to the trait `hasElaborateConstructor` 
for both `classes` and `structs`.


There's no such trait as far as I'm aware. If there were, it'd 
likely be checking for the presence of a '__ctor' member. Thing 
is, it can't be generic because ctors may be templates, the best 
that can be done is checking if `T` is constructible with some 
arguments `Args`.


 And how this is related to the trait `hasElaborateDestructor` 
for both `classes` and `structs`.


It isn't. The trait literally just checks if the compiler has 
generated a '__dtor' member, and it doesn't do so for classes at 
all.


Re: LDC2 -I option results in unresolved externals

2018-10-12 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 12 October 2018 at 07:32:26 UTC, Mike Parker wrote:

DMD has the -i option which tells the compiler to automatically 
compile all imported modules. I don't know if LDC has anything 
similar.


It does, same option.


Re: ported a sortable list from my old C code

2018-10-13 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 13 October 2018 at 11:11:41 UTC, Codifies wrote:


Does anyone has any ideas on improving this sortable list


Yes. Use an array. No, really, use an array. Now, really, use an 
array.
If reallocations while building your paths become a problem, you 
can write a deque (bucket array) or a dlist. But still, 
afterwards just convert it to array and use that.


Re: Why is dynamic array length required here?

2018-10-18 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 19 October 2018 at 02:04:37 UTC, Samir wrote:
I am working my way through the exercises in the "Programming 
in D" tutorial (http://ddili.org/ders/d.en/arrays.html).  Why 
is the line assigning the length of the dynamic array required?


[...]



Without the line:

myArray.length = noValues;

I get the run-time error...


I would have thought that since this is a dynamic array, I 
don't need to pre-assign its length.


Even though the array is dynamic, it doesn't have infinite 
storage. So you either:


- preallocate required storage, like in that example code (note 
that it's not the same as making a fixed-size ('static') array: 
in your case you only learn what the required length is at 
run-time, as opposed to static arrays where you must know it at 
compile time)


- don't preallocate, but instead append new elements like this:

myArray ~= newValue;

The latter isn't a universally "good" advice: it may cause 
reallocation every time you do that. That's why it's almost 
always best to preallocate in advance if you do know the length, 
or use something like std.array.appender that attempts to reduce 
memory reallocation. I'm not familiar with Ali's tutorials, maybe 
he talks about the appender in some future examples.




Re: need help about get all public static function name

2018-10-22 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 22 October 2018 at 11:42:59 UTC, test wrote:

some how when I call "is(typeof(__traits(getMember, BaseType, 
name))) " in the template, my code report others error like:


Error: no property fromPointer for type void
Error: template instance TypeTemplate!(BaseType) is used as a 
type


Error: template instance `TypeTemplate!(BaseType)` error 
instantiating


That would be hard to diagnose without actually seeing the code, 
it seems there's something else going on.


Re: need help about get all public static function name

2018-10-22 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 22 October 2018 at 10:16:22 UTC, test wrote:
I try use traits get all public static function of a struct 
pass to template...



how to do this ?


void allFunctions(T)() {
import std.stdio;
foreach (name; __traits(allMembers, T)) {
static foreach (overload; __traits(getOverloads, T, 
name)) {
static if (__traits(getProtection, overload) == 
"public" && __traits(isStaticFunction, overload)) {
// 'overload' is an alias to a T's public static 
function

writeln(name, ": ", typeof(overload).stringof);
}
}
}
}



Re: need help about get all public static function name

2018-10-22 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 22 October 2018 at 10:49:10 UTC, test wrote:


test1.d
=
alias Fn1   = void function();
struct XX {
alias Fn= Fn1;
// ...
}


'Fn' is not a static function, it's a type. I.e. you can declare 
a function pointer with it:


Fn func;


test2.d
=
import test1;
void GetPub(BaseType)(){
// ...
}



My code works fine with your struct XX, with dmd 2.082.

std.traits.hasMember expects an aggregate *type*, but you're 
trying to pass as instance.


A revised GetPub:

void GetPub(BaseType)(){
static foreach (name; __traits(allMembers, BaseType)) 
static if( name[0] !is '_' && is(typeof(__traits(getMember, 
BaseType, name))) && __traits(getProtection, __traits(getMember, 
BaseType, name)) == "public" ) {

//static assert( hasMember!(BaseType.init, name));
static assert(hasMember!(BaseType, name));
static if( __traits(isStaticFunction, 
__traits(getMember, BaseType, name)) ) {
pragma(msg, BaseType.stringof ~ "." ~ 
name);

}
}
}

note the added check that the member is not a type: 
is(typeof(__traits(getMember, BaseType, name))).
You'll still need to iterate overloads if you want to get all 
static functions.


Re: need help about get all public static function name

2018-10-22 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 22 October 2018 at 12:03:22 UTC, test wrote:

On Monday, 22 October 2018 at 11:59:21 UTC, test wrote:

On Monday, 22 October 2018 at 11:42:59 UTC, test wrote:
I try made a simple example but it has no error:



I find the way to show the error:

https://run.dlang.io/is/f8cULz


import std.traits;

struct FiberS {
static auto getThis(){
return Fiber.getId();
}
}

struct Proxy(T){
T* ptr;
alias getPayload this;

@property ref auto getPayload() inout return {
return * ptr ;
}

static auto getId(){
return 1;
}
}
alias Fiber = Proxy!(FiberS);


extern(C) void main(){
   auto id = Fiber.getThis(); // work here
}

struct TcpStream {
void read(ubyte[] data){
   auto id = Fiber.getThis(); // not work here in my 
case

}
}


Let's analyze this call:

auto id = Fiber.getThis();

You're trying to call a static function 'getThis' on Fiber.
The type 'Fiber' is really a Proxy!FiberS. Proxy doesn't have a 
static getThis() function. So the compiler tries an 'alias this', 
which forwards to a non-static member function getPayload(). To 
call that function, you need an instance of 'Proxy', which you 
don't have.
I guess the first error message ("this for getPayload needs to be 
type Proxy not type TcpStream") just doesn't report that clearly.


Re: custom sorting of lists ?

2018-10-19 Thread Stanislav Blinov via Digitalmars-d-learn

On Friday, 19 October 2018 at 17:40:59 UTC, Carl Sturtivant wrote:

If we imagine an Ordered Range being a finite Range of some 
kind with the additional property that its values are ordered 
(--- exact definition needed ---)...


There's already a SortedRange: 
https://dlang.org/phobos/std_range.html#.SortedRange


Re: Can Scope Be Used for Anonymous Objects?

2018-10-17 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 17 October 2018 at 20:53:02 UTC, Vijay Nayar wrote:

This particular use of "scope" I overheard at the last DConf, 
and I believe it has been added to the official documentation 
here:  https://dlang.org/spec/expression.html#new_expressions


If a NewExpression is used as an initializer for a function 
local variable with
scope storage class, and the ArgumentList to new is empty, 
then the instance is
allocated on the stack rather than the heap or using the 
class specific allocator.


Class-specific allocators (aka overriding 'new') were deprecated 
a long time ago, and this particular use of 'scope' should 
follow. Unfortunately, as with many other things in D, 
allocators, 'scope', DIP1000 etc are somewhere between here and 
there...


I didn't know about the std.typecons scoped, it looks really 
useful, especially when you want to only create the object when 
short-circuiting fails, like in the middle of an "||" 
expression.


One drawback of "scoped", however, is that it doesn't appear to 
warn you if you accidentally let the reference escape out of 
the function, unlike a scope variable.


That's an artifact of it's implementation predating DIP25 and 
DIP1000, and those DIPs themselves not being realized fully.



Why, exactly, is a trivial thing like this even a class?


Porting C++ code which unfortunately makes heavy use of 
inheritance.  I originally had this as a struct until I much 
later stumbled into the other classes that were inheriting from 
it.


Ouch. If there aren't any virtual functions, you could "inherit" 
via struct inclusion and alias this. Or just take artistic... 
err... porting license and deviate from the original 
implementation :)


Re: Access program args outside of main

2018-10-17 Thread Stanislav Blinov via Digitalmars-d-learn
On Wednesday, 17 October 2018 at 22:30:31 UTC, Jordan Wilson 
wrote:



Ideally, I'd check args before I take the time to load up data.



https://dlang.org/phobos/core_runtime.html#.Runtime


Re: Can Scope Be Used for Anonymous Objects?

2018-10-17 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 17 October 2018 at 20:24:56 UTC, Vijay Nayar wrote:

I have a snippet of code like this:
scope chordAngle = new S1ChordAngle(_center, other._center);
return _radius + other._radius >= chordAngle;

The reason the "scope" temporary variable exists is to avoid a 
heap allocation and instead prefer a value be created on the 
stack.  Is there a way to do this inline?


Why, exactly, is a trivial thing like this even a class?



Re: how to get UDA only for methods

2018-10-17 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 17 October 2018 at 02:54:26 UTC, test wrote:
I need get the Route UDA only for method without (static 
methods, property, constructor, destructor), dont know how to 
do it.


1) Note that __traits(allMembers, T) gets you a tuple of names, 
not actual member aliases.

2) Remember there may be overloads
3) Filter the unwanted out:

import std.traits;
import std.meta : Alias, AliasSeq;
import std.stdio;
import std.string : startsWith;
import std.algorithm : among;

alias operatorNames = AliasSeq!("opUnary", "opIndexUnary", 
"opCast", "opBinary", "opBinaryRight",
"opIn", "opIn_r", "opEquals", 
"opCmp", "opCall", "opAssign",
"opIndexAssign", "opOpAssign", 
"opIndexOpAssign", "opSliceOpAssign",
"opIndex", "opSlice", "opDollar", 
"opDispatch");


void main() {
writeln(getRoutes!App);
}

struct Route { string r; }

Route[] getRoutes(T)(){
Route[] routes;
foreach (name; __traits(allMembers, T)) {
alias member = Alias!(__traits(getMember, T, name));
static if (__traits(isStaticFunction, member) ||
   name.startsWith("__")  ||
   name.among(operatorNames))
{}
else static if (is(typeof(member) == function)) {
foreach (overload; __traits(getOverloads, T, name)) {
pragma(msg, name);
static foreach(route; getUDAs!(overload, Route)) {
routes  ~= route;
}
}
}
}
return routes;
}

struct App {

@Route("xxx")
int field;

@Route("/blah")
this(this) {}

@Route("ggg")
~this() {}

@Route("/index")
void home() {}

@Route("/index2")
void home(bool overloaded) {}

@Route("/blog")
void blog(){}
}



Re: Error: non-shared method core.sync.condition.Condition.notify is not callable using a shared object

2018-10-18 Thread Stanislav Blinov via Digitalmars-d-learn
On Thursday, 18 October 2018 at 10:50:18 UTC, Paolo Invernizzi 
wrote:


There's a rational behind the fact that there's not a 'shared' 
version of notify/wait method in Condition?


They were implemented before complete `shared` spec existed, 
which is any time between it's conception and now.


Re: Dealing with ranges where front and popFront do the same logic / eager ranges

2018-10-17 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 17 October 2018 at 09:53:22 UTC, Dukc wrote:

Whatever iterates through the range could then throw an 
appopriate exception when it encounters an error token.


Exceptions in a parser? Monsieur knows his perversion.




Re: When does GC run?

2018-10-16 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 16 October 2018 at 09:38:44 UTC, John Burton wrote:

The information I have found indicates that it runs to free 
memory when the system runs out of memory to allocate.


No, that is incorrect. By default, here's what's happening:

1) At startup (or first 'new' or GC.malloc) the GC allocates a 
pool of memory.

2) Subsequent calls to 'new' or GC.malloc allocate from that pool.
3) If there isn't enough memory in the pool to allocate, it may 
either:
a) Pause all your threads and perform a collection sweep, 
unless collection is disabled. If there's still not enough 
contiguous address space in the pool after that, it'll go to b)

b) Ask the OS for more memory for the pool.

Therefore, implicit automatic collection only occurs when you 
allocate, and only if needed. Explicit collection can be 
requested by calling GC.collect().


But will this try to use all the system memory or some other 
amount before trying to garbage collect? If I have a _lot_ of 
garbage, will it try to collect that before allocating any more 
system memory? Is this configurable in any way?


If you have a lot of garbage, you should probably allocate in 
advance, disable/enable collection around hot paths and 
explicitly ask for collection in between, or just not use the GC, 
i.e. allocate a block and do your business inside of it.




Re: Who can stop it ? Help me,thank you.

2018-10-17 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 17 October 2018 at 13:48:04 UTC, FrankLike wrote:


What can I do?


Delete the bloatware that you downloaded.


Re: struggling to link against a C global in D (win/vs2017)

2018-10-28 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 29 October 2018 at 00:01:21 UTC, DanielG wrote:


In my D app I'm declaring it this way:

extern (C) {
extern __gshared int myIntValue;
int myIntFunc (int a, int b);
}

The function seems to link OK, but the C global will not.


Should it be extern(Windows), perchance?.. (I haven't D on 
Windows for ages).




Re: how to make '==' safe for classes?

2018-10-28 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 28 October 2018 at 12:38:12 UTC, ikod wrote:

and object.opEquals(a,b) do not inherits safety from class C 
properties, and also I can't override it.


Yep. Since Object is the base class and it defines opEquals as:
```
bool opEquals(Object);
```

the compiler rewrites `a == b` as 
`(cast(Object)a).opEquals(cast(Object)ob)`, i.e. it inserts a 
@system call into your code.


Is there clean way to use '==' here, or I have to convert this 
to a.opEquals(b) for classes, leaving '==' for structs?


Pretty much, yes. "Implicit" value comparison in general is 
somewhat alien for classes, since they're reference types.


Re: expanding variadic into format

2018-10-31 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 31 October 2018 at 12:13:57 UTC, Codifies wrote:
On Wednesday, 31 October 2018 at 12:09:04 UTC, Stanislav Blinov 
wrote:



```
void printValue(Args...)(Font fnt, float x, float y, string 
frmt, auto ref Args args) {

// ...
import std.functional : forward;
string message = format(frmt, forward!args);
// ...
}
```


thats fantastic thanks so much, can you explain a little more 
about whats going on here ?


As rikki already explained, std.format is a variadic template, 
which gets expanded into argument list at compile time. That's 
why it can't be used with C-syle variadics: when you passed 
_arguments, the expansion treated that as a single argument 
instead of a tuple.
Therefore, to forward arguments to std.format, your `printValue` 
must also be a variadic.


There are, broadly speaking, two ways to pass arguments to 
functions: by value and by reference.


When you make a template like this:

void foo(T)(T value) { /* ... */ }

it will take the argument by value, making copies when necessary:

struct S { /* ... */ }

S s;
foo(S.init); // calls foo without copying, argument is 
constructed directly

foo(s); // copies `s` and passes that copy to `foo`

If that template is defined like this:

void foo(T)(ref T value) { /* ... */ }

then it will *only* take argument by reference:

foo(S.init); // error, 'ref' cannot bind to rvalue
foo(s); // no copy is made, `foo` takes `s` by reference

There are more subtleties, especially when taking `const ref` 
arguments, but I won't get into those.


There's a special syntax for template functions: `auto ref` 
arguments. Those are deduced to be by-value or by-reference at 
compile time (see

https://dlang.org/spec/template.html#auto-ref-parameters):

void foo(T)(auto ref T value) { /* ... */ }

foo(S.init); // works, compiles as foo(S);
foo(s); // works, compiles as foo(ref S);

But, because inside of function definition all arguments are 
lvalues, you lose this additional information if you pass them to 
another function directly. To preserve that information, there's 
a `forward` template in std.functional. D doesn't have rvalue 
references, so that template will still copy the bits of 
non-`ref` arguments, but it will not call postblits, etc (it 
`move`s them using std.algorithm.mutation.move).


So, there are two possible ways to implement your print:

// Take all Args by value, i.e. copy everything first time
void printValue(Args...)(Font fnt, float x, float y, string frmt, 
Args args) {
// make copies of every argument in `args` (again) and pass 
those to `format`

auto message = format(frmt, args);
}

or

// Infer whether each argument is an lvalue or not
void printValue(Args...)(Font fnt, float x, float y, string frmt, 
auto ref Args args) {

import std.functional : forward;
// preserve lvalue/rvalue
string message = format(frmt, forward!args);
}

Both allow you to accomplish your goal, but the second one only 
copies the argument bits when necessary.


Getting into finer implementation nuances, conceptually this 
allows a function to even take and pass around non-copyable types 
as arguments. Sadly, this is not widely adopted by Phobos, which 
likes to make unnecessary copies. I.e. the `format` function 
itself takes Args by value, even though it probably should take 
advantage of this specific language feature. But at least calling 
it via `forward`, you only make necessary copies once, instead of 
twice.




  1   2   3   >