Re: Slices and Dynamic Arrays

2017-12-31 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, January 01, 2018 05:06:46 Tony via Digitalmars-d-learn wrote:
> On Monday, 1 January 2018 at 02:10:14 UTC, Jonathan M Davis wrote:
> > The DLang Tour should probably be fixed to use the term dynamic
> > array though.
>
> Or embrace both terms but take care that it is clear that they
> are synonyms and one may be preferred depending on context. As a
> beginner, I had some confusion seeing both terms used.
>
> There is dual terminology in use outside of dlang.org. The book
> Programming In D says:
> 
> Slice: Another name for dynamic array.
>
> When I write slice I will specifically mean a slice; and when I
> write array, I will mean either a slice or a fixed-length array,
> with no distinction.
>
> Slices
>
> Slices are the same feature as dynamic arrays. They are called
> dynamic arrays for being used like arrays, and are called slices
> for providing access to portions of other arrays. They allow
> using those portions as if they are separate arrays.
> ---

A big problem with the term slice though is that it means more than just
dynamic arrays - e.g. you slice a container to get a range over it, so that
range is a slice of the container even though no arrays are involved at all.
So, you really can't rely on the term slice meaning dynamic array. Whether
it does or not depends on the context. That means that the fact that a
number of folks have taken to using the term slice to mean T[] like the D
Slices article talks about tends to create confusion when the context is not
clear. IMHO, the D Slices article should be updated to use the correct
terminology, but I don't think that the author is willing to do that.

- Jonathan M Davis



Re: Slices and Dynamic Arrays

2017-12-31 Thread Tony via Digitalmars-d-learn

On Monday, 1 January 2018 at 02:10:14 UTC, Jonathan M Davis wrote:



The DLang Tour should probably be fixed to use the term dynamic 
array though.


Or embrace both terms but take care that it is clear that they 
are synonyms and one may be preferred depending on context. As a 
beginner, I had some confusion seeing both terms used.


There is dual terminology in use outside of dlang.org. The book 
Programming In D says:


Slice: Another name for dynamic array.

When I write slice I will specifically mean a slice; and when I 
write array, I will mean either a slice or a fixed-length array, 
with no distinction.


Slices

Slices are the same feature as dynamic arrays. They are called 
dynamic arrays for being used like arrays, and are called slices 
for providing access to portions of other arrays. They allow 
using those portions as if they are separate arrays.

---




Re: How do you safely deal with range.front?

2017-12-31 Thread Ali Çehreli via Digitalmars-d-learn

On 12/30/2017 11:00 AM, aliak wrote:


Instead of this:
   auto result = range.op!f;
   if (!result.empty) {
     result.front.method();
   }

This:
   range.op!f.ifFront.method();


In the above scenario I only want method to be called if the pipeline 
resulted in any element left in the range.


If you're fine with specifying the function as a template argument, the 
following works. (As seen with 's => s.foo()' below, you have to use a 
lambda for member functions anyway.)


auto ifFront(alias func, R)(R range) {
import std.traits : isArray;
static if (isArray!R) {
import std.array : empty, front;
}
if (!range.empty) {
func(range.front);
}
}

unittest {
size_t executed;

struct S {
size_t *e;
this(ref size_t e) {
this.e = &e;
}

void foo() {
++(*e);
}
}

auto foo(int) {
++executed;
}

// Non-empty array; should be called
auto a = [1];
a.ifFront!foo;
assert(executed == 1);

// Empty array; should not be called
int[] b;
b.ifFront!foo;
assert(executed == 1);

// Non-empty S array; should be called
auto c = [ S(executed) ];
c.ifFront!(s => s.foo());
assert(executed == 2);

// Empty S array; should not be called
S[] d;
d.ifFront!(s => s.foo());
assert(executed == 2);
}

void main() {
}

Ali


Re: How do you safely deal with range.front?

2017-12-31 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, December 31, 2017 01:03:17 Tony via Digitalmars-d-learn wrote:
> For me, front() should throw a pre-defined exception when called
> on an empty range in order to eliminate undefined behavior. It
> does take some time to make a check, but D does array bounds
> checking by default. Ideally the front() check could be turned
> off somehow ("-boundschecks=off") by the user for those who want
> maximum speed, but I guess there is no way to do that when using
> pre-compiled functions in a library.

Except that the reason for arrays throwing RangeErrors when you try and
index them out-of-bounds is to avoid memory safety issues, which is not
necessarily the case at all when you're talking about ranges. Having ranges
in general be checking empty in front, popFront, back, etc. would add
unnecessary overhead - especially when you consider that ranges often wrap
other ranges. You'd be layering on check after check when the calling code
is already supposed to be checking empty when necessary to make sure that
the range isn't empty. You'd even be layering checks on top of the checks
that arrays already do, since many ranges are ultimately wrapped around a
dynamic array at their core.

The extra checks on arrays avoid nasty memory-related problems and don't
involve layering on extra checks all over the place, whereas ranges in
general do not pose a memory safety problem (those that do should do checks
like dynamic arrays do, but that's not the norm).

As for -boundschecks=off, that arguably shouldn't even exist. It can already
be gotten around using the ptr property if you really want that extra speed,
and the vast majority of programs shouldn't even consider using it, because
skipping the bounds checking in arrays is just begging for memory corruption
problems.

- Jonathan M Davis



Re: Slices and Dynamic Arrays

2017-12-31 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, December 31, 2017 14:49:40 Tony via Digitalmars-d-learn wrote:
> On Sunday, 31 December 2017 at 14:24:40 UTC, Jonathan M Davis
>
> wrote:
> > The D Slices article does an excellent job of explaining all of
> > this. It's just that it calls the GC-allocated memory buffer
> > the dynamic array instead of calling T[] the dynamic array like
> > the language and spec do. Regardless, all non-null dynamic
> > arrays are slices of memory.
>
> The DLang Tour also uses the term slice to refer to T[].
>
> "The type of arr is int[], which is also called a slice."
>
> "A slice consists of two members - a pointer to the starting
> element and the length of the slice:"

Presumably, because whoever wrote that preferred the terminology used in the
D Slices article. Regardless, it's not wrong to call them slices. It's just
less precise, since the term slice refers to more than dynamic arrays.

The DLang Tour should probably be fixed to use the term dynamic array
though.

- Jonathan M Davis



Re: take symbol as parameter

2017-12-31 Thread Marc via Digitalmars-d-learn

On Saturday, 30 December 2017 at 23:30:02 UTC, rjframe wrote:

On Sat, 30 Dec 2017 13:07:49 +, Marc wrote:


how do I take a symbol as parameter?

for example:


template nameof(alias S) {
import std.array : split;
enum nameof = S.stringof.split(".")[$-1];
}


Works fine for say a enum member such nameof!(myEnum.X) but 
this:



struct S { int v; }
S s;
writefln(nameof!(s.v)); // should return "v"


return the following error:

Error: template instance nameof!(v) cannot use local 'v' as 
parameter

to > non-global template nameof(alias S)


You can use the name of the struct rather than the instance.

writefln(nameof!(S.v));


How do I make it work when the symbol is defiend as following:


class C { int a() { return 0; }}


call to nameof!(C.a)

give compiler error:


Error: need 'this' for 'a' of type 'int()'
template instance foo.nameof!(a) error instantiating


Re: take symbol as parameter

2017-12-31 Thread Marc via Digitalmars-d-learn

On Sunday, 31 December 2017 at 22:50:12 UTC, Marc wrote:

On Saturday, 30 December 2017 at 23:30:02 UTC, rjframe wrote:

On Sat, 30 Dec 2017 13:07:49 +, Marc wrote:


how do I take a symbol as parameter?

for example:


[...]


Works fine for say a enum member such nameof!(myEnum.X) but 
this:



[...]


return the following error:


[...]


You can use the name of the struct rather than the instance.

writefln(nameof!(S.v));


it doesn't work for me:

Error: template instance nameof!(v) cannot use local 'v' as 
parameter to non-global template nameof(alias S)


Put it at global scope. Worked fine.


Re: take symbol as parameter

2017-12-31 Thread Marc via Digitalmars-d-learn

On Saturday, 30 December 2017 at 23:30:02 UTC, rjframe wrote:

On Sat, 30 Dec 2017 13:07:49 +, Marc wrote:


how do I take a symbol as parameter?

for example:


template nameof(alias S) {
import std.array : split;
enum nameof = S.stringof.split(".")[$-1];
}


Works fine for say a enum member such nameof!(myEnum.X) but 
this:



struct S { int v; }
S s;
writefln(nameof!(s.v)); // should return "v"


return the following error:

Error: template instance nameof!(v) cannot use local 'v' as 
parameter

to > non-global template nameof(alias S)


You can use the name of the struct rather than the instance.

writefln(nameof!(S.v));


it doesn't work for me:

Error: template instance nameof!(v) cannot use local 'v' as 
parameter to non-global template nameof(alias S)


std.file and non-English filename in Windows

2017-12-31 Thread Domain via Digitalmars-d-learn
In Windows, exists, rename, copy will report file not exists when 
you input non-English filename, such as Chinese 中文.txt


Re: How do you safely deal with range.front?

2017-12-31 Thread ag0aep6g via Digitalmars-d-learn

On 12/31/2017 02:14 PM, aliak wrote:
Also, is going out of array bounds well defined behavior in D even with 
boundscheck off?


No. Without the checks you get undefined behavior. I.e., 
`-boundscheck=off` defeats the `@safe` attribute. For that reason, I'd 
advise against ever using it. Definitely don't think of it as a harmless 
optimization switch.


Re: Determine at compile time whether or not an alias is defined in a struct/class

2017-12-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On 12/31/17 10:01 AM, ktoast wrote:

Hello everyone,


I started to learn D a few weeks ago and have been stuck trying to solve 
the following problem :


- determine at compile time whether an alias is defined or not in a 
struct/class.


You'll find my attempt thereafter, something similar to how it's done in 
C++ (using the type void_t and partial specialization of a templated 
struct) :




alias void_t(T) = void;

struct define_default_type(T) {

     static struct test(U, V = void) {
     static const bool value = false;
     }

     static struct test(U, V : void_t!(U.default_type)) {
     static const bool value = true;
     }

     static const bool value = test!(T).value;
}

unittest {

     struct S {
     alias default_type = void;
     }

    assert(define_default_type!S.value); //define_default_type!S.value 
is false, not sure why

}



I can't tell what's wrong with the code above or if this is even the 
right way to go about it with D.


Would anyone have pointers to give me on how to solve this ?

Thanks a lot !



hm... what it looks like you are trying to do is find out if the struct 
has a member default_type, and if it is an alias to a type? It's hard to 
tell because of your C++-like attempt :)


This is how I would do it:

enum define_default_type(S) = is(S.default_type);

an isexpression has a lot of power: 
https://dlang.org/spec/expression.html#IsExpression


The default iexpression just returns true if the given symbol is a type.

So now:

assert(define_default_type!S);

or even better:

static assert(define_default_type!S); // check at compile-time

See if it fits your needs.

If it doesn't do quite what you want, there are a lot of goodies here: 
https://dlang.org/spec/traits.html


and here: https://dlang.org/phobos/std_traits.html

-Steve


Re: How do you safely deal with range.front?

2017-12-31 Thread Tony via Digitalmars-d-learn

On Sunday, 31 December 2017 at 13:14:10 UTC, aliak wrote:

On Sunday, 31 December 2017 at 01:03:17 UTC, Tony wrote:
For me, front() should throw a pre-defined exception when 
called on an empty range in order to eliminate undefined 
behavior. It does take some time to make a check, but D does 
array bounds checking by default. Ideally the front() check 
could be turned off somehow ("-boundschecks=off") by the user 
for those who want maximum speed, but I guess there is no way 
to do that when using pre-compiled functions in a library.


That sounds like a good idea. Wouldn't the same apply to array 
bounds checking for precompiled functions though?


Yeah, seems like the standard library must be doing one or the 
other (bounds checking array indexes or not bounds checking them) 
all the time, depending on how it was compiled.


Also, is going out of array bounds well-defined behavior in D 
even with bounds check off?


I'm no expert, but I can't think of how it could be.


And any links to docs on UB in D?


This thread was the first time I have heard it used with regard 
to D.





Determine at compile time whether or not an alias is defined in a struct/class

2017-12-31 Thread ktoast via Digitalmars-d-learn

Hello everyone,


I started to learn D a few weeks ago and have been stuck trying 
to solve the following problem :


- determine at compile time whether an alias is defined or not in 
a struct/class.


You'll find my attempt thereafter, something similar to how it's 
done in C++ (using the type void_t and partial specialization of 
a templated struct) :




alias void_t(T) = void;

struct define_default_type(T) {

static struct test(U, V = void) {
static const bool value = false;
}

static struct test(U, V : void_t!(U.default_type)) {
static const bool value = true;
}

static const bool value = test!(T).value;
}

unittest {

struct S {
alias default_type = void;
}

   assert(define_default_type!S.value); 
//define_default_type!S.value is false, not sure why

}



I can't tell what's wrong with the code above or if this is even 
the right way to go about it with D.


Would anyone have pointers to give me on how to solve this ?

Thanks a lot !



Re: Slices and Dynamic Arrays

2017-12-31 Thread Tony via Digitalmars-d-learn
On Sunday, 31 December 2017 at 14:24:40 UTC, Jonathan M Davis 
wrote:




The D Slices article does an excellent job of explaining all of 
this. It's just that it calls the GC-allocated memory buffer 
the dynamic array instead of calling T[] the dynamic array like 
the language and spec do. Regardless, all non-null dynamic 
arrays are slices of memory.


The DLang Tour also uses the term slice to refer to T[].

"The type of arr is int[], which is also called a slice."

"A slice consists of two members - a pointer to the starting 
element and the length of the slice:"







Re: Slices and Dynamic Arrays

2017-12-31 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, December 31, 2017 01:57:58 Tony via Digitalmars-d-learn wrote:
> On Friday, 29 December 2017 at 23:13:20 UTC, Jonathan M Davis
>
> wrote:
> > The term "slice" is a bit overused in D, meaning a variety of
> > things. It doesn't help that some folks dislike the official
> > terminology. In general, a slice is a contiguous group of
> > elements. A slice of memory would be a contiguous block of
> > memory. A dynamic array therefore refers to a slice of memory
> > and could be called a slice, but it's also the case that using
> > the slice operater on a container is called slicing - e.g.
> > rbt[] would give you a range over the container rbt, and that
> > range is a slice of the container, but it's not an array at all.
>
> For me, it is confusing to use "slice" and "dynamic array" as
> synonyms. My initial impression was that they must have different
> code underlying them, and different behavior. I would pick one or
> the other. It should be:
>
> D Arrays
>- Static
>- Dynamic
>
> or
>
> D Arrays
> - Static
> - Slice
>
>
> The DLang Tour has a section on Slices that says in bold "Slices
> and dynamic arrays are the same". I think that sentence deserves
> an explanation as to why there are two terms being utilized for
> the same thing. I would prefer that "slice" as a noun was used
> only for the time when a dynamic array was initialized from a
> slice of another array. Or better yet - slice was never used as a
> noun - only a verb or adjective: took a slice of array A to form
> a slice dynamic array B (or slice-intialized dynamic array B).
>
> D Arrays
> - Static
> - Dynamic
>- Slice-Initialized Dynamic

All dynamic arrays are slices of memory. What changes is what memory they're
sliced from. There is no master dynamic array that controls the memory that
backs all of these dynamic arrays. They're the same whether they were
allocated via new or slices from a static array or sliced from pointers or
whatever. _All_ a dynamic array is a pointer and a length - e.g.

struct DynamicArray(T)
{
size_t length;
T* ptr;
}

It has no mechanism for managing memory or tracking who owns it. All of that
is handled by whatever allocated the memory in the first place. In most
cases, that's the GC, but it doesn't have to be. The dynamic array doesn't
even have a way to keep track of its capacity. All of that is handled by the
GC.

Yes, appending to a dynamic array or calling reserve on it can cause memory
to be allocated by the GC, but that's because the GC looks at the capacity
of the array (which it calculates based on extra stuff it keeps track of)
and sees whether it can increase the length of the array in place (which it
can do only if the array is backed by GC-allocated memory, and the capacity
is greater than its current length). The GC then may allocate a new block of
memory and copy the contents of the array to the new memory, and the runtime
will adjust the two members of the dynamic array so that they point to the
new block of memory, but the dynamic array itself does none of this - and it
all works exactly the same if the dynamic array is backed by
non-GC-allocated memory. It's just that the GC will determine that since
it's not backed by GC-allocated memory, its capacity is 0, and any operation
that would need to increase the length or capacity of the array will need to
reallocate (after which, the dynamic array will be backed by GC-allocated
memory regardless of what backed it before).

In no case does the dynamic array itself manage its own memory, and there is
no concept of the "original" dynamic array that the others come from. As
confusing as that may seem at first, that simply isn't how dynamic arrays in
D work. Rather than being a container which you can get ranges over, they're
a weird hybrid between the two. They have operations that act like they own
and manage their own memory, but they really don't.

The D Slices article does an excellent job of explaining all of this. It's
just that it calls the GC-allocated memory buffer the dynamic array instead
of calling T[] the dynamic array like the language and spec do. Regardless,
all non-null dynamic arrays are slices of memory.

- Jonathan M Davis



Re: Slices and Dynamic Arrays

2017-12-31 Thread Jonathan M Davis via Digitalmars-d-learn
On Sunday, December 31, 2017 04:42:01 Tony via Digitalmars-d-learn wrote:
> On Sunday, 31 December 2017 at 04:20:28 UTC, codephantom wrote:
> > On Sunday, 31 December 2017 at 03:57:17 UTC, Tony wrote:
> >> On Sunday, 31 December 2017 at 03:08:05 UTC, Ivan Trombley
> >>
> >> wrote:
> >>> double[] D = [3.14159];
> >>>
> >>> Can you guess what D is?  :D
> >>
> >> It took me a while but I finally came up with "a slice of pi"
> >
> > a slice of pi is irrational.
>
> Even on special occasions?

Of course. Cake is so much better. ;)

- Jonathan M Davis



Re: static if and early exit from function doesn't seem to work?

2017-12-31 Thread Adam D. Ruppe via Digitalmars-d-learn

On Sunday, 31 December 2017 at 13:32:03 UTC, aliak wrote:
So it seems it tries to compile the statements below the check 
on V.length even though it's guaranteed to be true and there's 
a return statement inside the if.


Yeah, static if includes or excludes code independently at 
compile time.


So what you wrote there would be like, assuming the first to 
static ifs pass:


auto concat(R, V...)(R range, V values) if (isInputRange!R) {
import std.range: chain, ElementType;
return range;
return range.chain(values[0]).concat(values[1..$]);
}


The code is still there, even if it isn't reached due to an early 
return, and thus still must compile.



Using else static if means it won't be generated.


Re: static if and early exit from function doesn't seem to work?

2017-12-31 Thread Colin via Digitalmars-d-learn

On Sunday, 31 December 2017 at 13:32:03 UTC, aliak wrote:
Alo! I'm making a recursive concat function that is similar to 
chain. The following code works:


[...]


I suspect it's because you've no 'else static if'.


static if and early exit from function doesn't seem to work?

2017-12-31 Thread aliak via Digitalmars-d-learn
Alo! I'm making a recursive concat function that is similar to 
chain. The following code works:


import std.range: isInputRange;

auto concat(R, V...)(R range, V values) if (isInputRange!R) {
import std.range: chain, ElementType;
static if (V.length) {
static if (isInputRange!(V[0])) {
return range.chain(values[0]).concat(values[1..$]);
} else static if (is(V[0] == ElementType!R)) {
return range.chain([values[0]]).concat(values[1..$]);
} // add an else assert here.
} else {
return range;
}
}

But the following does not:

auto concat(R, V...)(R range, V values) if (isInputRange!R) {
import std.range: chain, ElementType;
static if (!V.length) {
return range;
}
static if (isInputRange!(V[0])) {
return range.chain(values[0]).concat(values[1..$]);
}
static if (is(V[0] == ElementType!R)) {
return range.chain([values[0]]).concat(values[1..$]);
}
}

You get a:

Error: tuple index 0 exceeds 0
Error: template instance range.concat.concat!(Result) error 
instantiating


So it seems it tries to compile the statements below the check on 
V.length even though it's guaranteed to be true and there's a 
return statement inside the if.


Is it a current limitation of static if? or a bug? or is 
something like this just not possible because of something I'm 
not seeing?


Cheers



Re: How do you safely deal with range.front?

2017-12-31 Thread aliak via Digitalmars-d-learn

On Sunday, 31 December 2017 at 01:03:17 UTC, Tony wrote:
For me, front() should throw a pre-defined exception when 
called on an empty range in order to eliminate undefined 
behavior. It does take some time to make a check, but D does 
array bounds checking by default. Ideally the front() check 
could be turned off somehow ("-boundschecks=off") by the user 
for those who want maximum speed, but I guess there is no way 
to do that when using pre-compiled functions in a library.


That sounds like a good idea. Wouldn't the same apply to array 
bounds checking for precompiled functions though?


Also, is going out of array bounds well defined behavior in D 
even with boundscheck off? And any links to docs on UB in D?


Re: Avoiding GC in D and code consistancy

2017-12-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On 12/31/17 7:50 AM, Steven Schveighoffer wrote:


Note, you can use a "sink" version of toString as well, and avoid the gc:

void toString(void delegate(const(char)[]) sink) @nogc
{
     // use formatValue to push into the sink
}


I guess I'm missing some parameters here, go with what Seb linked to :)

-Steve


Re: Avoiding GC in D and code consistancy

2017-12-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On 12/31/17 6:16 AM, Tim Hsu wrote:

On Sunday, 31 December 2017 at 07:32:50 UTC, Ali Çehreli wrote:

On 12/30/2017 11:16 PM, Tim Hsu wrote:

> Struct version of Vector3f can't derive toString
> method. writeln() prints unformated struct members. I know I
can use
> helper function here. But is there any other way?

The normal way that I know is to insert a function like the following 
into Vector3f:


    string toString() {
    import std.string : format;
    return format("%s,%s,%s", x, y, z);
    }

> class version of Vector3f. Require new operator in
opBinary(). scoped!
> won't work here.
>
> Is there a better to write vector3f class while avoiding GC?

Yeah, it doesn't make sense that a type of x, y, z should be a class. 
I would stay with a struct here.




Sorry I am a bit disappointed. It seems writeln itself will check if the 
struct to be printed has toString. If not, it use default struct printer.


Note, you can use a "sink" version of toString as well, and avoid the gc:

void toString(void delegate(const(char)[]) sink) @nogc
{
// use formatValue to push into the sink
}

-Steve


Re: Slices and Dynamic Arrays

2017-12-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On 12/30/17 10:08 PM, Ivan Trombley wrote:

double[] D = [3.14159];

Can you guess what D is?  :D



An approximation of a slice of pi.

-Steve


Re: Slices and Dynamic Arrays

2017-12-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On 12/30/17 8:57 PM, Tony wrote:
For me, it is confusing to use "slice" and "dynamic array" as synonyms. 
My initial impression was that they must have different code underlying 
them, and different behavior.


As stated in the slices article, I think of them as separate -- the 
slice is the public type that is used to operate on dynamic arrays, the 
dynamic array is a nameless type that only exists in the runtime. It 
helped me immensely when rewriting the array runtime to think of it that 
way. All the feedback I received when publishing the article was along 
the lines of "Wow, thinking of it that way helps a lot", so I think it's 
a good mental model.


But in terms of D types, the slice *is* the dynamic array type, it 
behaves in all the ways you would expect a dynamic array type to behave. 
The only difference is that a slice does not own the memory it 
references. Normally you would consider a dynamic array to own its 
memory (i.e. be responsible for allocation and destruction). Because we 
have the GC, ownership can be fuzzy.


The DLang Tour has a section on Slices that says in bold "Slices and 
dynamic arrays are the same". I think that sentence deserves an 
explanation as to why there are two terms being utilized for the same 
thing. I would prefer that "slice" as a noun was used only for the time 
when a dynamic array was initialized from a slice of another array. Or 
better yet - slice was never used as a noun - only a verb or adjective: 
took a slice of array A to form a slice dynamic array B (or 
slice-intialized dynamic array B).


The question really is, what is the name of the type T[]? If you give it 
a different name depending on how it was created, then you have all 
sorts of confusion. In fact, there was a proposal by Walter and Andrei a 
long long time ago to have a type T[new] which would be the dynamic 
array type, and T[] be the slice type. This failed, because in Andrei's 
words, "Explaining two very similar but subtly different types to 
newcomers is excruciatingly difficult."


IMO, T[] is a slice, because it may not be GC-backed dynamic array data 
underneath. Some people prefer to think of it as a dynamic array, 
because you can use it like a dynamic array no matter what it points at. 
Either way works, and fits the implementation. It's really a matter of 
preference.


-Steve


Re: Avoiding GC in D and code consistancy

2017-12-31 Thread Seb via Digitalmars-d-learn

On Sunday, 31 December 2017 at 07:16:46 UTC, Tim Hsu wrote:
I came from C++ looking forward to D. Some languages require 
programmers to use GC all the time. However, A lot of time we 
don't really need GC especially when the time of destruction is 
deterministic in compile time.


[...]


You can use a custom toString method which doesn't do any 
allocations:


https://wiki.dlang.org/Defining_custom_print_format_specifiers

However, the building blocks (formattedWrite and writeln) aren't 
"@nogc" at the moment.


Re: Avoiding GC in D and code consistancy

2017-12-31 Thread Tim Hsu via Digitalmars-d-learn

On Sunday, 31 December 2017 at 07:32:50 UTC, Ali Çehreli wrote:

On 12/30/2017 11:16 PM, Tim Hsu wrote:

> Struct version of Vector3f can't derive toString
> method. writeln() prints unformated struct members. I know I
can use
> helper function here. But is there any other way?

The normal way that I know is to insert a function like the 
following into Vector3f:


string toString() {
import std.string : format;
return format("%s,%s,%s", x, y, z);
}

> class version of Vector3f. Require new operator in
opBinary(). scoped!
> won't work here.
>
> Is there a better to write vector3f class while avoiding GC?

Yeah, it doesn't make sense that a type of x, y, z should be a 
class. I would stay with a struct here.


Ali


Sorry I am a bit disappointed. It seems writeln itself will check 
if the struct to be printed has toString. If not, it use default 
struct printer.