Re: cannot implicitly convert char[] to string
On 08/15/2015 04:45 AM, cym13 wrote: On Saturday, 15 August 2015 at 11:34:01 UTC, cym13 wrote: On Saturday, 15 August 2015 at 11:25:20 UTC, vladde wrote: I made a PR to phobos where I modified `std.format.format`. https://github.com/D-Programming-Language/phobos/pull/3528 However the auto builder fails, with the error message: runnable/test23.d(1219): Error: cannot implicitly convert expression (format(s = %s, s)) of type char[] to string The line which fails is `p = std.string.format(s = %s, s);` I don't understand why I can't convert a char[] to string. I think it has to do with the fact that string is an alias to immutable(char)[] and you can't implicitely cast an immutable to a regular variable. That's actually correct (for reference types). As long as there is no indirection, a value type can be casted implicitly: struct S { int i; } void main() { auto i = immutable(S)(); auto m = S(); m = i;// copied; fine } I phrased it completely wrong, an example will be better : import std.stdio; void fun(immutable(int)[] i) { i.writeln(); } void main() { int[] i = [42]; fun(i); } Will not compile because there is no certainty that fun() won't change the array Actually, that's the job of 'const'. Here, it is not fun's ability to mutate but the caller's. 'immutable' on a function interface means a requirement: The caller *must* provide immutable data so that the function can rely on it not being changed by anyone. Ali
Re: Template Collections of Different Types
On Sunday, 16 August 2015 at 02:42:18 UTC, BBasile wrote: --- enum Ti {tibyte, tiubyte, ...} Ti getTypeInfo(T)(T t){statif is(t == ubyte) return Ti.tibyte; else...} You could also just use D's own run time typeinfo with the typeid() thing. It returns an instance of class TypeInfo. (This is what std.variant does btw)
Re: Use members of a Named Enum without using Enum name?
On 08/15/2015 09:22 AM, QuizzicalFella wrote: On Saturday, 15 August 2015 at 15:53:23 UTC, Adam D. Ruppe wrote: On Saturday, 15 August 2015 at 15:37:42 UTC, QuizzicalFella wrote: I'd like to be able to call someFunc(TRIANGLE) rather than someFunc(PolygonT.TRIANGLE). Two options come to mind: alias TRIANGLE = PolygonT.TRIANGLE; // etc ...if I wanted to write a mixin that iterated over all the elements in an enum, how would I get a member to print its name without the type? And how do I get the type to print itself? foreach(member; enum) char[] output ~= alias ~member.name~=~enum.name~.~member.name~; Fundamentally, __traits(allMembers) and .stringof but the following enumMembers present them as a range: import std.stdio; enum PolygonT : byte { TRIANGLE, RECTANGLE, STAR } auto enumMembers(E)() { import std.conv : to; import std.algorithm : map; return [ __traits(allMembers, E) ].map!(a = a.to!string); } void info(E)() { writefln(The members of %s: %-(%s, %), E.stringof, enumMembers!PolygonT); } void main() { info!PolygonT(); } Ali
Re: Template Collections of Different Types
On Sunday, 16 August 2015 at 01:39:54 UTC, DarthCthulhu wrote: Say I want to do something like: Propertery!int pi = 42; PropertyCollection pc; pc.attach(Life_and_Everything, pi); assert(pc.Life_and_Everything == 42); Property!string ps = Hello World; pc.attach(text, ps); assert(pc.text == Hello World); How would one store the Property objects in the PropertyCollection? You can't use something like an array because the two Properties are of different types. Do you really need to do something like make a member of PropertyCollection for every type of Property you are interested in storing and using static ifs to determine which variable it goes into? I feel like there is an obvious solution here that I'm missing. You would need a kind of type info system: --- enum Ti {tibyte, tiubyte, ...} Ti getTypeInfo(T)(T t){statif is(t == ubyte) return Ti.tibyte; else...} pc.attach(Life_and_Everything, pi, getTypeInfo(pi)); pc.attach(BlaBlaBla, pi, getTypeInfo(pi)); pc.attach(zkfozekf, 42, getTypeInfo(42)); --- internally the container would store 3 infos (string, pointer to data and a Ti) and when you query a property from its identifier, it looks for the attached type info so that you can cast the result (let's say it would return a pointer). --- TypeInfo getTypeInfo(string identifier); void* getValue(string identifier); --- These kind of mechanism are really common in languages that have a poor/none compile time reflection features, but in D you would have to build your own run time type info system. My example is a bit shitty but you should get the idea.
Re: Attributes not propagating to objects via typeinfo?
On Friday, 14 August 2015 at 15:39:39 UTC, Timon Gehr wrote: I don't understand. It is evidently fixable. E.g. if TypeInfo was just a template without the mostly redundant additional compiler support, this would be a trivial fix. It appears that this was suggested already after a bit of digging but nobody cares to fix it. IMO, compiler handles far too much stuff that should be in the runtime.
Re: Template Collections of Different Types
On Sunday, 16 August 2015 at 01:51:36 UTC, Adam D. Ruppe wrote: On Sunday, 16 August 2015 at 01:39:54 UTC, DarthCthulhu wrote: How would one store the Property objects in the PropertyCollection? You don't, not like that anyway. The attach call is the ruin of it. If it was all one definition, you could use something like std.typecons.Tuple, but multiple calls to attach need to be a runtime function, which means what you attach will lose the compile time type when you get it. I see. Yeah, I thought that might be the case. Nice to know I wasn't just being ignorant. That would work. You could write a plain struct definition and then the attach could be implemented as a allMembers/getMember assignment loop, similarly to this: http://stackoverflow.com/questions/31993705/d-call-a-function-using-a-string-variable-with-its-name/31996526#31996526 but looking at data member assignments instead of method calls. Oh, neat! Thanks! Incidentally, I watched your dconf2015 talk Dynamic Types in D. That (along with Andrei's Generic Programming Must Go) actually inspired me to think about this particular problem. It's very appropriate that you would have the solution, then!
Re: using memset withing a pure function
On Saturday, 15 August 2015 at 19:50:56 UTC, Temtaime wrote: There's a problem with « dst[0 .. n] = val; ». It should be « dst[0 .. n][] = val; » No, you don't need the `[]`.
Template Collections of Different Types
Say I want to do something like: Propertery!int pi = 42; PropertyCollection pc; pc.attach(Life_and_Everything, pi); assert(pc.Life_and_Everything == 42); Property!string ps = Hello World; pc.attach(text, ps); assert(pc.text == Hello World); How would one store the Property objects in the PropertyCollection? You can't use something like an array because the two Properties are of different types. Do you really need to do something like make a member of PropertyCollection for every type of Property you are interested in storing and using static ifs to determine which variable it goes into? I feel like there is an obvious solution here that I'm missing.
Re: Template Collections of Different Types
On Sunday, 16 August 2015 at 01:39:54 UTC, DarthCthulhu wrote: How would one store the Property objects in the PropertyCollection? You don't, not like that anyway. The attach call is the ruin of it. If it was all one definition, you could use something like std.typecons.Tuple, but multiple calls to attach need to be a runtime function, which means what you attach will lose the compile time type when you get it. Best you could do is something like pc.text!string which checks at runtime and throws if you asked for the wrong type, which is basically just a Variant[string]. You can't use something like an array because the two Properties are of different types. Do you really need to do something like make a member of PropertyCollection for every type of Property you are interested in storing and using static ifs to determine which variable it goes into? That would work. You could write a plain struct definition and then the attach could be implemented as a allMembers/getMember assignment loop, similarly to this: http://stackoverflow.com/questions/31993705/d-call-a-function-using-a-string-variable-with-its-name/31996526#31996526 but looking at data member assignments instead of method calls. The attach would still check the type with a throw at runtime, since the member name you use is also a runtime thing.
Using replaceInPlace, string and char[]
Hi, A newbie question : I wrote this simple code : import std.array; import std.stdio; void main() { char[] a = mon texte 1.dup; char[] b = abc.dup; size_t x = 4; size_t y = 9; replaceInPlace( a, x , y, b ); writeln( a ); } But compilation fails : /usr/include/dmd/phobos/std/array.d(2052): Error: template std.algorithm.remove cannot deduce function from argument types !()(char[], Tuple!(immutable(uint), uint)), candidates are: /usr/include/dmd/phobos/std/algorithm.d(8542): std.algorithm.remove(SwapStrategy s = SwapStrategy.stable, Range, Offset...)(Range range, Offset offset) if (s != SwapStrategy.stable isBidirectionalRange!Range hasLvalueElements!Range hasLength!Range Offset.length = 1) /usr/include/dmd/phobos/std/algorithm.d(8623): std.algorithm.remove(SwapStrategy s = SwapStrategy.stable, Range, Offset...)(Range range, Offset offset) if (s == SwapStrategy.stable isBidirectionalRange!Range hasLvalueElements!Range Offset.length = 1) /usr/include/dmd/phobos/std/algorithm.d(8757): std.algorithm.remove(alias pred, SwapStrategy s = SwapStrategy.stable, Range)(Range range) if (isBidirectionalRange!Range hasLvalueElements!Range) inout.d(13): Error: template instance std.array.replaceInPlace!(char, char[]) error instantiating Don't understand why this doesn't work: it compiles fine and runs perfectly if I change char[] by string ... don't understand why since the documentation says : String literals are immutable (read only). How this function can change a type that is immutable ? Thanks for your help. TSalm
Re: Using replaceInPlace, string and char[]
On Saturday, 15 August 2015 at 08:07:43 UTC, Ali Çehreli wrote: This looks like a bug to me. The template constraints of the two overloads are pretty complicated. This case should match only one of them. Yes I understand. I've used ldc2. With DMD (v0.067.1) the error is more clear : inout.d(11): Error: std.array.replaceInPlace called with argument types (char[], uint, uint, char[]) matches both: /usr/include/dmd/phobos/std/array.d(2214): std.array.replaceInPlace!(char, char[]).replaceInPlace(ref char[] array, uint from, uint to, char[] stuff) and: /usr/include/dmd/phobos/std/array.d(2247): std.array.replaceInPlace!(char, char[]).replaceInPlace(ref char[] array, uint from, uint to, char[] stuff) Must create a ticket for it ? Don't understand why this doesn't work: it compiles fine and runs perfectly if I change char[] by string You mean, this: import std.array; import std.stdio; void main() { string a = mon texte 1;// -- now string writeln(a.ptr); // added char[] b = abc.dup; size_t x = 4; size_t y = 9; replaceInPlace( a, x , y, b ); writeln( a ); writeln(a.ptr); // added } The output: 4BC480 mon abc 1 7FC2AB867210-- different ... don't understand why since the documentation says : String literals are immutable (read only). How this function can change a type that is immutable ? It cannot change the characters of the original string. replaceInPlace takes its first parameter by reference. What changes is 'a' itself. As evidenced by the output of the program, 'a' is now a slice to a new set of immutable characters. If there were other slices to mon texte 1, they wouldn't see a change. Yes I understand, thanks. In the other hand using string is not efficient since this certainly make a copy of the original string. Right ? This is better to use replaceInPlace with char[], but this doesn't actually work :-(
Re: Using replaceInPlace, string and char[]
This looks like a bug to me. The template constraints of the two overloads are pretty complicated. This case should match only one of them. On 08/15/2015 12:43 AM, TSalm wrote: Don't understand why this doesn't work: it compiles fine and runs perfectly if I change char[] by string You mean, this: import std.array; import std.stdio; void main() { string a = mon texte 1;// -- now string writeln(a.ptr); // added char[] b = abc.dup; size_t x = 4; size_t y = 9; replaceInPlace( a, x , y, b ); writeln( a ); writeln(a.ptr); // added } The output: 4BC480 mon abc 1 7FC2AB867210-- different ... don't understand why since the documentation says : String literals are immutable (read only). How this function can change a type that is immutable ? It cannot change the characters of the original string. replaceInPlace takes its first parameter by reference. What changes is 'a' itself. As evidenced by the output of the program, 'a' is now a slice to a new set of immutable characters. If there were other slices to mon texte 1, they wouldn't see a change. Ali
Re: using memset withing a pure function
On Saturday, 15 August 2015 at 01:13:02 UTC, Adam D. Ruppe wrote: On Saturday, 15 August 2015 at 01:09:15 UTC, D_Learner wrote: When writting a pure fucntion involving C non pure functions like memcpy() and memset() Those functions are pure already, and marked so in the newest dmd (and I think older ones too, though I haven't confirmed. Your code compiled out of the box for me. BTW D also has some syntax sugar for them: arr[start .. end] = 0; // memset those bounds to 0 arr[start .. end] = arr2[start .. end]; // memcpy You could be surprised am still trying to get my head around this. Considering the code :- memcpy(skip[0], skip[0]+shift, (m-shift)*(int.sizeof)); memset(skip[0]+(m-shift),0, shift*(int.sizeof)) I was thinking conversion would be :- skip[0 .. size-1] = skip[shift .. size-1 ]; //For the memcpy(); skip[0 .. size-1] = 0;//For memset() But this doesn't seem to work for me as dmd(v2.066.1) gives the error slice [8..7] exceeds array bounds [0..8] .Sure am missing something.
Re: using memset withing a pure function
On Saturday, 15 August 2015 at 18:04:30 UTC, D_Learner wrote: memcpy(skip[0], skip[0]+shift, (m-shift)*(int.sizeof)); memset(skip[0]+(m-shift),0, shift*(int.sizeof)) I was thinking conversion would be :- skip[0 .. size-1] = skip[shift .. size-1 ]; //For the memcpy(); Those two slices have different lengths (when shift != 0). They must have equal lengths, and they must not overlap. skip[0 .. size-1] = 0;//For memset() But this doesn't seem to work for me as dmd(v2.066.1) gives the error slice [8..7] exceeds array bounds [0..8] .Sure am missing something. You can just do mechanical translations. memcpy(dst, src, n * T.sizeof); becomes dst[0 .. n] = src[0 .. n]; Then simplify. Original: memcpy(skip[0], skip[0]+shift, (m-shift)*(int.sizeof)); Identify the pieces: dst = skip[0] src = skip[0]+shift n = m-shift Substitute: (skip[0])[0 .. m-shift] = (skip[0]+shift)[0 .. m-shift]; Simplify: skip[0 .. m-shift] = skip[shift .. $][0 .. m-shift]; skip[0 .. m-shift] = skip[shift .. shift + m-shift]; skip[0 .. m-shift] = skip[shift .. m]; I sure hope I didn't mess anyting up. memset is very similar. memset(dst, val, n * T.sizeof); becomes dst[0 .. n] = val; Then simplify.
Re: cannot implicitly convert char[] to string
On Saturday, 15 August 2015 at 11:25:20 UTC, vladde wrote: I made a PR to phobos where I modified `std.format.format`. https://github.com/D-Programming-Language/phobos/pull/3528 However the auto builder fails, with the error message: runnable/test23.d(1219): Error: cannot implicitly convert expression (format(s = %s, s)) of type char[] to string The line which fails is `p = std.string.format(s = %s, s);` I don't understand why I can't convert a char[] to string. I think it has to do with the fact that string is an alias to immutable(char)[] and you can't implicitely cast an immutable to a regular variable.
Re: cannot implicitly convert char[] to string
On Saturday, 15 August 2015 at 11:34:01 UTC, cym13 wrote: On Saturday, 15 August 2015 at 11:25:20 UTC, vladde wrote: I made a PR to phobos where I modified `std.format.format`. https://github.com/D-Programming-Language/phobos/pull/3528 However the auto builder fails, with the error message: runnable/test23.d(1219): Error: cannot implicitly convert expression (format(s = %s, s)) of type char[] to string The line which fails is `p = std.string.format(s = %s, s);` I don't understand why I can't convert a char[] to string. I think it has to do with the fact that string is an alias to immutable(char)[] and you can't implicitely cast an immutable to a regular variable. I phrased it completely wrong, an example will be better : import std.stdio; void fun(immutable(int)[] i) { i.writeln(); } void main() { int[] i = [42]; fun(i); } Will not compile because there is no certainty that fun() won't change the array while the following will work import std.stdio; void fun(immutable(int)[] i) { i.writeln(); } void main() { int[] i = [42]; fun(i.dup); immutable(int)[] j = [42]; fun(j); immutable(int[]) k = [42]; fun(k); }
Re: cannot implicitly convert char[] to string
On 08/15/2015 01:54 PM, Timon Gehr wrote: On 08/15/2015 01:25 PM, vladde wrote: I made a PR to phobos where I modified `std.format.format`. https://github.com/D-Programming-Language/phobos/pull/3528 However the auto builder fails, with the error message: runnable/test23.d(1219): Error: cannot implicitly convert expression (format(s = %s, s)) of type char[] to string The line which fails is `p = std.string.format(s = %s, s);` I don't understand why I can't convert a char[] to string. Get rid of the 'in' in format's signature. Oh, I see, this is by design (which I don't like, but OK.) The reason the conversion does not go through is that format is not marked as pure.
Re: Using replaceInPlace, string and char[]
On 08/15/2015 01:47 AM, TSalm wrote: Must create a ticket for it ? I think so. Unless others object in 10 minutes... :) In the other hand using string is not efficient since this certainly make a copy of the original string. Right ? This is better to use replaceInPlace with char[], but this doesn't actually work :-( There is probably a workaround, which others will hopefully show. (I have to leave now. :) ) However, although not in your example, replaceInPlace would still copy if the result would not fit in the original char[]. Hm... Come to think of it, it cannot replace in place anyway, unless it knows that the slice is the only one looking at those characters. Otherwise, you would disturbing your other slices. (?) Ali
Re: cannot implicitly convert char[] to string
On 08/15/2015 01:25 PM, vladde wrote: I made a PR to phobos where I modified `std.format.format`. https://github.com/D-Programming-Language/phobos/pull/3528 However the auto builder fails, with the error message: runnable/test23.d(1219): Error: cannot implicitly convert expression (format(s = %s, s)) of type char[] to string The line which fails is `p = std.string.format(s = %s, s);` I don't understand why I can't convert a char[] to string. Get rid of the 'in' in format's signature.
cannot implicitly convert char[] to string
I made a PR to phobos where I modified `std.format.format`. https://github.com/D-Programming-Language/phobos/pull/3528 However the auto builder fails, with the error message: runnable/test23.d(1219): Error: cannot implicitly convert expression (format(s = %s, s)) of type char[] to string The line which fails is `p = std.string.format(s = %s, s);` I don't understand why I can't convert a char[] to string.
Use members of a Named Enum without using Enum name?
I have a named enum that I'd like to keep named, that I'd like to use as a type, but every time I use a member I'd rather not write out the enum name. I have a situation like the following: enum PolygonT : byte { TRIANGLE, RECTANGLE, STAR } void someFunc(PolygonT shape) { //some stuff } I'd like to be able to call someFunc(TRIANGLE) rather than someFunc(PolygonT.TRIANGLE). Being clear but not being too long is my aim. Writing the type makes it too verbose and I have lazy fingers... I don't mind if adding another enum with members of the same name like this: enum CelestialBodiesT : byte { MOON, SUN, BLACK_HOLE, STAR } ...would force me to call someFunc(PolygonT.STAR) by the compiler, but for the case where there's no ambiguity, I don't want to write out the type of the enum... I know I can add in an 'alias this' for classes and structs, but I think I only get one and if it's an enum I'm using all over the place I don't want to 'alias this' it everywhere... Is there a way I can do this while retaining type safety? (can I be lazy and protected at the same time?)
Re: Use members of a Named Enum without using Enum name?
On Saturday, 15 August 2015 at 15:37:42 UTC, QuizzicalFella wrote: I'd like to be able to call someFunc(TRIANGLE) rather than someFunc(PolygonT.TRIANGLE). Two options come to mind: alias TRIANGLE = PolygonT.TRIANGLE; // etc Or at the usage site: with(PolygonT) { someFunc(TRIANGLE); } I don't mind if adding another enum with members of the same name like this: enum CelestialBodiesT : byte { MOON, SUN, BLACK_HOLE, STAR } ...would force me to call someFunc(PolygonT.STAR) by the compiler, but for the case where there's no ambiguity, I don't want to write out the type of the enum... That'll work as long as the two enums are defined in separate modules, then only import the one you need to use at the time. Otherwise, they will conflict and it will force you to write it out long form again.
Re: Use members of a Named Enum without using Enum name?
On Saturday, 15 August 2015 at 15:53:23 UTC, Adam D. Ruppe wrote: On Saturday, 15 August 2015 at 15:37:42 UTC, QuizzicalFella wrote: I'd like to be able to call someFunc(TRIANGLE) rather than someFunc(PolygonT.TRIANGLE). Two options come to mind: alias TRIANGLE = PolygonT.TRIANGLE; // etc ...if I wanted to write a mixin that iterated over all the elements in an enum, how would I get a member to print its name without the type? And how do I get the type to print itself? foreach(member; enum) char[] output ~= alias ~member.name~=~enum.name~.~member.name~;
Re: using memset withing a pure function
There's a problem with « dst[0 .. n] = val; ». It should be « dst[0 .. n][] = val; »
Re: using memset withing a pure function
On Saturday, 15 August 2015 at 18:49:15 UTC, anonymous wrote: On Saturday, 15 August 2015 at 18:04:30 UTC, D_Learner wrote: [...] Those two slices have different lengths (when shift != 0). They must have equal lengths, and they must not overlap. [...] Am now sorted. Thanks, your workout simplifies everything