Re: opAssign and const?
On Friday, May 04, 2012 08:52:49 Era Scarecrow wrote: > On Friday, 4 May 2012 at 06:48:40 UTC, Jonathan M Davis wrote: > > If you make the one which isn't a ref const as well, it'll > > probably work. > > Yeah I think so too. It will just be either a direct copy or I > cast the object as const and pass it through. Seems like extra > work to me and should be handled by the compiler. Anyways, thanks > for looking at the problem with me. With the last beta, there was a discussion in changing how ref and const ref works to allow rvalues while disallowing whatever use cases it is that causes problems with that in C++. If that gets sorted out and fully implemented, then you'd only need one overload. As it stands, the closest that you could get would be to use auto ref, but that only works with templated functions. - Jonathan M Davis
Re: opAssign and const?
On Friday, 4 May 2012 at 06:48:40 UTC, Jonathan M Davis wrote: If you make the one which isn't a ref const as well, it'll probably work. Yeah I think so too. It will just be either a direct copy or I cast the object as const and pass it through. Seems like extra work to me and should be handled by the compiler. Anyways, thanks for looking at the problem with me.
Re: Transforming a range back to the original type?
On 2012-05-03 00:34, bearophile wrote: The newly redesigned containers in Scala language are often able to do this, but this has required the use of a very advanced static type system, that is currently not in D (maybe there are ways to implement it with D templates, but it will require work to implement). I've heard of that. I've started to read a paper about how the collection API is implemented. -- /Jacob Carlborg
Re: opAssign and const?
On Friday, May 04, 2012 08:32:40 Era Scarecrow wrote: > On Friday, 4 May 2012 at 06:15:21 UTC, Jonathan M Davis wrote: > > I believe that the issue is that x2 isn't const, so when the > > compiler decides which of the two overloads to use, it picks > > the one which doesn't use const. If the const ref version were > > the only one, then it would work with x2, but since it isn't, > > the other one gets picked because it's deemed a better match. > > I figured that was the case too. But I get the feeling that's > wrong in this case. I was hoping to have only two declared > opAssing's, one for temporaries (without ref) and one for > copying. Kinda like the difference between saying a=b and a[]=b[] > for an array. Be annoying if I had to force the cast to be const > to do what I wanted; Right? If you make the one which isn't a ref const as well, it'll probably work. - Jonathan M Davis
Re: opAssign and const?
On Friday, 4 May 2012 at 06:32:41 UTC, Era Scarecrow wrote: opAssing's Hmmm suppose to be OpAssign. Nothing quite like a bug in your automatic text converter right?
Re: opAssign and const?
On Friday, 4 May 2012 at 06:15:21 UTC, Jonathan M Davis wrote: I believe that the issue is that x2 isn't const, so when the compiler decides which of the two overloads to use, it picks the one which doesn't use const. If the const ref version were the only one, then it would work with x2, but since it isn't, the other one gets picked because it's deemed a better match. I figured that was the case too. But I get the feeling that's wrong in this case. I was hoping to have only two declared opAssing's, one for temporaries (without ref) and one for copying. Kinda like the difference between saying a=b and a[]=b[] for an array. Be annoying if I had to force the cast to be const to do what I wanted; Right?
Re: Transforming a range back to the original type?
On 2012-05-04 01:11, Stewart Gordon wrote: To sum it up, it can't be done in the general case. The range API doesn't know or care about the underlying data structure. That's half the point of it. The underlying data structure might not even exist. An example is a range used as a file stream, a random number generator or to lazily generate a mathematical sequence. Yeah, I know, I know. It's all good in theory but I never found a use for it in practice and in most cases it's just annoying. Moreover, what would you want such a function to return if the range is: - a file stream with a cache - an array wrapper to loop infinitely through it? - a concatenation of ranges that may be of different types? I was mostly thinking when the range originated from a collection. Where it's actually possible to transfer the range back to the original collection type. Moreover, even if there were some "range with an underlying container" classification, it would be an extra burden on the writer of the range wrapper to implement this. No, I was thinking that the developer of the collection would provide that. I mean, it's already possible to transform a range to an array, I'm sure it's possible to transform it to a list of some kind as well. Then we could have this for example: collA.range.toArray(); collB.range.toList(); What I was asking for was if there is, or could be, a generic interface for this. Something like: collA.range.toCollection(); collA.range.toCollection(); If "collA" is an array "toCollection" would transform the range to an array, just as std.array.array does. If "collB" is a list the range would be transformed back in to a list. If you want to generate a range that views a container in a certain way, and then construct a container of the original type (or indeed any type) from that range, then create the container and then use a foreach loop on the range (or a .save of it, if you want to keep the range afterwards) to put the data into the container. Stewart. -- /Jacob Carlborg
Re: ref semantics with hashes
On 5/3/12, Artur Skawina wrote: >alias p1.p2.p3.p4.p5.p6.hash hash3; >alias p1.p2?p1.p2.hash:p3.p4.hash hash4; >alias getfoo().hash hash5; I was under the impression that alias would only be used as a compile-time alias to a nested symbol. So this: alias p1.p2.p3.hash foo; test(foo); would be somewhat equivalent to: alias p1.p2.p3.hash foo; mixin("test(p1.p2.p3.hash);"); I never thought of using alias as some sort of pointer in disguise.
Re: opAssign and const?
On Friday, May 04, 2012 07:49:29 Era Scarecrow wrote: > I have the following dilemma. Hopefully I have this right. > > struct X { >ref X opAssign(X x2); >ref X opAssign(ref X x2); > } > > X fn(); > > void func(){ >X x, x2; > >x = x2; //uses ref >x = fn(); //without ref > } > > According to the book, this is how it is suppose to be. const is > a added promise not to modify anything. So... if i changed the > ref to ref const... it won't call unless the item input was const > as well. > > //same as above except.. > struct X { >ref X opAssign(X x2); >ref X opAssign(ref const X x2); //const added > } > > void func(){ >X x, x2; >const X x3; > >x = x2; //without ref??? >x = x3; //ref > } > > Since the input is intended to be read only anyways, why won't > it work as expected with x = x2? This seems like a bug. If it's > not, then I need to make two ref versions so it will behave > properly. (If you need I can past actual working example) I believe that the issue is that x2 isn't const, so when the compiler decides which of the two overloads to use, it picks the one which doesn't use const. If the const ref version were the only one, then it would work with x2, but since it isn't, the other one gets picked because it's deemed a better match. - Jonathan M Davis
opAssign and const?
I have the following dilemma. Hopefully I have this right. struct X { ref X opAssign(X x2); ref X opAssign(ref X x2); } X fn(); void func(){ X x, x2; x = x2; //uses ref x = fn(); //without ref } According to the book, this is how it is suppose to be. const is a added promise not to modify anything. So... if i changed the ref to ref const... it won't call unless the item input was const as well. //same as above except.. struct X { ref X opAssign(X x2); ref X opAssign(ref const X x2); //const added } void func(){ X x, x2; const X x3; x = x2; //without ref??? x = x3; //ref } Since the input is intended to be read only anyways, why won't it work as expected with x = x2? This seems like a bug. If it's not, then I need to make two ref versions so it will behave properly. (If you need I can past actual working example)
Re: How to prevent direct public creation of a struct?
"Brad Anderson" wrote in message news:jhsccvjskiqqzzqbd...@forum.dlang.org... > On Thursday, 3 May 2012 at 21:36:53 UTC, Nick Sabalausky wrote: >> I want to do something like this: >> >> -- >> module moduleFoo; >> >> // Only allow certain values of "str" >> template foo(string str) >> { >> static assert(str == "a" || str == "b" || str == "c"); >> immutable foo = Foo(str); >> } >> >> struct Foo >> { >> // Only "a", "b", and "c" should be allowed, >> // checked at compile-time via "template foo". >> // Also, not modifyable. >> private string _str; >> @property string str() >> { >> return _str; >> } >> } >> -- >> >> I want struct Foo itself to be public, but I want to *force* all code >> outside moduleFoo to *create* Foo via the "foo" template. Copying should >> be >> allowed though. Ie: >> >> -- >> auto a = foo!"a"; // ok >> a.str = "b"; // Error: str is a read-only property >> auto z = foo!"z"; // Error: fails static assert >> auto a2 = a; // Copy it: ok >> >> auto b = Foo("b"); // Error: I want to *force* the usage of "template >> foo" >> >> Foo x; // Kinda ambivalent about this: I'd prefer if it were disallowed, >> but >> I don't think that's possible. If it's indeed impossible, I know I can >> just >> declare Foo.str as (string str = "a";) so that's not a big problem. >> -- >> >> The *key* thing here that I'm not sure how to do is: How do I disallow >> this?: >> >> auto b = Foo("b"); // Error: I want to *force* the usage of "template >> foo" > > I would have thought adding a private this(string str) constructor would > work but then foo can't be called from a separate module ("privcons.d(5): > Error: struct privcons.Foo member this is not accessible" which is the > same but desirable error it gives if you do "auto b = Foo("b");"). I > thought all module members had access to private members of the same > module but I guess that's not the case with template functions. Hmm, interestingly, it works if the template calls through an intermediary private function: http://d.puremagic.com/issues/show_bug.cgi?id=8028 I don't know if I'm relying on a bug or working around a bug, but this seems to work, *and* disallows "Foo b;" which is nice: --- template foo(string str) { static assert(["a", "b", "c"].find(str), "Invalid str: '"~str~"'"); immutable foo = _foo(name); } private Foo _foo(string str) { return Foo(str); } struct Foo { immutable string str; private this(string str) { this.str = str; } @disable this(); } --- // In a serparate module: Foo a = foo!"a"; // Ok auto a2 = a; // Ok a.str = "b"; // Error: can only initialize const member name inside constructor auto z = foo!"z"; // Error: static assert "Invalid str: 'z'" instantiated from here: foo!("z") auto b = Foo("b"); // Error: struct test2.Foo member this is not accessible Foo x; // Error: variable test1.main.x initializer required for type Foo --- So that's awesome, everything as I wanted :)
Re: Transforming a range back to the original type?
On 02/05/2012 22:01, Jacob Carlborg wrote: Is there a general function for transforming a range back to the original type? If not, would it be possible to create one? To sum it up, it can't be done in the general case. The range API doesn't know or care about the underlying data structure. That's half the point of it. The underlying data structure might not even exist. An example is a range used as a file stream, a random number generator or to lazily generate a mathematical sequence. Moreover, what would you want such a function to return if the range is: - a file stream with a cache - an array wrapper to loop infinitely through it? - a concatenation of ranges that may be of different types? Moreover, even if there were some "range with an underlying container" classification, it would be an extra burden on the writer of the range wrapper to implement this. If you want to generate a range that views a container in a certain way, and then construct a container of the original type (or indeed any type) from that range, then create the container and then use a foreach loop on the range (or a .save of it, if you want to keep the range afterwards) to put the data into the container. Stewart.
Re: Mixins are not inherited?
Very sad, i thougth that was possible. As regards to "instanceof" Try this code: unittest { class A { mixin TRef!(typeof(this)); } class B : A { } class C : B { } A a1 = new B(); A a2 = new C(); assert(instanceof!(A)(a1) == false); assert(instanceof!(B)(a1)); assert(instanceof!(C)(a1) == false); } with my instanceof and then with your version.
Re: How to prevent direct public creation of a struct?
On Thursday, May 03, 2012 17:37:47 Nick Sabalausky wrote: > I want to do something like this: > > -- > module moduleFoo; > > // Only allow certain values of "str" > template foo(string str) > { > static assert(str == "a" || str == "b" || str == "c"); > immutable foo = Foo(str); > } > > struct Foo > { > // Only "a", "b", and "c" should be allowed, > // checked at compile-time via "template foo". > // Also, not modifyable. > private string _str; > @property string str() > { > return _str; > } > } > -- > > I want struct Foo itself to be public, but I want to *force* all code > outside moduleFoo to *create* Foo via the "foo" template. Copying should be > allowed though. Ie: > > -- > auto a = foo!"a"; // ok > a.str = "b"; // Error: str is a read-only property > auto z = foo!"z"; // Error: fails static assert > auto a2 = a; // Copy it: ok > > auto b = Foo("b"); // Error: I want to *force* the usage of "template foo" > > Foo x; // Kinda ambivalent about this: I'd prefer if it were disallowed, but > I don't think that's possible. If it's indeed impossible, I know I can just > declare Foo.str as (string str = "a";) so that's not a big problem. > -- > > The *key* thing here that I'm not sure how to do is: How do I disallow > this?: > > auto b = Foo("b"); // Error: I want to *force* the usage of "template foo" Make all constructors private. Then the only way to construct the struct would be through it's init value. If you use @disable this(); you can also prevent the use of init, but that disables init completely, not just outside of the module that the struct is in. It looks like you're relying on the default-generated constructor for POD structs, and that isn't going to cut it, since it's public. You'll have to declare the appropriate constructor and make it private. - Jonathan M Davis
Re: Mixins are not inherited?
On Thursday, May 03, 2012 23:32:50 Namespace wrote: > By the following code i get these error messages: > > > Error: template RefTest.Ref.__unittest1.instanceof(T : Object,U : > Object) cannot deduce template function from argument types > !(A)(B) > > Error: template RefTest.Ref.__unittest1.instanceof does not match > any function template declaration > > Error: template instance instanceof!(A) errors instantiating > template > > > How is this possible? I thougth that the mixin would be inherited > and so every subclass would be implicit cast to his super type. > Isn't that so? > If i write "mixin TRef!(B);" in class B, it works fine. Can > anyone explain me why do i have to write it in class B? > > [code] > unittest { > bool instanceof(T : Object, U : Object)(const Ref!U obj) { > const U o = obj.access; > > return const_cast(o).toString() == typeid(T).toString(); > } > > class A { > mixin TRef!(A); > } > > class B : A { > //mixin TRef!(B); > } > > class C : B { > //mixin TRef!(C); > } > > A a1 = new B(); > A a2 = new C(); > > assert(instanceof!(A)(a1) == false); > assert(instanceof!(B)(a1)); > assert(instanceof!(C)(a1) == false); > > writeln(a1); > > B b1 = cast(B) a1; > > assert(instanceof!(A)(b1) == false); // <-- fails > > writeln(b1); > > writeln(); > } > [/code] > > "TRef" is the same mixin template and "Ref" the same template > struct as in my last threads. Nothing you put in a base class is automatically in a derived class. If you put a member variable or member function in a base class, it's not in the derived class. It's just that the derived class has access to it as long as it's protected or public. In the case of a mixin, you're essentially copying and pasting code. So, it's in the base class similarly to if you typed it there yourself. However, templated functions aren't virtual, so unlike if you typed them yourself, they won't be virtual if you use a template mixin. So, if you want to mixin something into every class in a hierarchy, you must mix it in to every class in the hierarchy, not just the base class. And if you want to test whether an object is an instance of a specific class, then cast it and check whether the result is null. You don't need to create a function to figure it out for you. e.g. auto c = cast(MyClass)object; if(c is null) writeln("c is NOT an instance of MyClass"); else writeln("c IS an instance of MyClass"); - Jonathan M Davis
Re: How to prevent direct public creation of a struct?
On Thu, 03 May 2012 17:37:47 -0400, Nick Sabalausky wrote: > The *key* thing here that I'm not sure how to do is: How do I disallow > this?: > > auto b = Foo("b"); // Error: I want to *force* the usage of "template > foo" The @disable annotation can do this, I believe: struct Foo { @disable this(); // Cannot use default constructor } But this disables it for code within the module as well as outside, so you may wish to also add a private constructor.
Re: How to prevent direct public creation of a struct?
On Thursday, 3 May 2012 at 21:36:53 UTC, Nick Sabalausky wrote: I want to do something like this: -- module moduleFoo; // Only allow certain values of "str" template foo(string str) { static assert(str == "a" || str == "b" || str == "c"); immutable foo = Foo(str); } struct Foo { // Only "a", "b", and "c" should be allowed, // checked at compile-time via "template foo". // Also, not modifyable. private string _str; @property string str() { return _str; } } -- I want struct Foo itself to be public, but I want to *force* all code outside moduleFoo to *create* Foo via the "foo" template. Copying should be allowed though. Ie: -- auto a = foo!"a"; // ok a.str = "b"; // Error: str is a read-only property auto z = foo!"z"; // Error: fails static assert auto a2 = a; // Copy it: ok auto b = Foo("b"); // Error: I want to *force* the usage of "template foo" Foo x; // Kinda ambivalent about this: I'd prefer if it were disallowed, but I don't think that's possible. If it's indeed impossible, I know I can just declare Foo.str as (string str = "a";) so that's not a big problem. -- The *key* thing here that I'm not sure how to do is: How do I disallow this?: auto b = Foo("b"); // Error: I want to *force* the usage of "template foo" I would have thought adding a private this(string str) constructor would work but then foo can't be called from a separate module ("privcons.d(5): Error: struct privcons.Foo member this is not accessible" which is the same but desirable error it gives if you do "auto b = Foo("b");"). I thought all module members had access to private members of the same module but I guess that's not the case with template functions.
How to prevent direct public creation of a struct?
I want to do something like this: -- module moduleFoo; // Only allow certain values of "str" template foo(string str) { static assert(str == "a" || str == "b" || str == "c"); immutable foo = Foo(str); } struct Foo { // Only "a", "b", and "c" should be allowed, // checked at compile-time via "template foo". // Also, not modifyable. private string _str; @property string str() { return _str; } } -- I want struct Foo itself to be public, but I want to *force* all code outside moduleFoo to *create* Foo via the "foo" template. Copying should be allowed though. Ie: -- auto a = foo!"a"; // ok a.str = "b"; // Error: str is a read-only property auto z = foo!"z"; // Error: fails static assert auto a2 = a; // Copy it: ok auto b = Foo("b"); // Error: I want to *force* the usage of "template foo" Foo x; // Kinda ambivalent about this: I'd prefer if it were disallowed, but I don't think that's possible. If it's indeed impossible, I know I can just declare Foo.str as (string str = "a";) so that's not a big problem. -- The *key* thing here that I'm not sure how to do is: How do I disallow this?: auto b = Foo("b"); // Error: I want to *force* the usage of "template foo"
Mixins are not inherited?
By the following code i get these error messages: Error: template RefTest.Ref.__unittest1.instanceof(T : Object,U : Object) cannot deduce template function from argument types !(A)(B) Error: template RefTest.Ref.__unittest1.instanceof does not match any function template declaration Error: template instance instanceof!(A) errors instantiating template How is this possible? I thougth that the mixin would be inherited and so every subclass would be implicit cast to his super type. Isn't that so? If i write "mixin TRef!(B);" in class B, it works fine. Can anyone explain me why do i have to write it in class B? [code] unittest { bool instanceof(T : Object, U : Object)(const Ref!U obj) { const U o = obj.access; return const_cast(o).toString() == typeid(T).toString(); } class A { mixin TRef!(A); } class B : A { //mixin TRef!(B); } class C : B { //mixin TRef!(C); } A a1 = new B(); A a2 = new C(); assert(instanceof!(A)(a1) == false); assert(instanceof!(B)(a1)); assert(instanceof!(C)(a1) == false); writeln(a1); B b1 = cast(B) a1; assert(instanceof!(A)(b1) == false); // <-- fails writeln(b1); writeln(); } [/code] "TRef" is the same mixin template and "Ref" the same template struct as in my last threads.
Re: Fixed-size arrays and randomShuffle()
Vidar Wahlberg: I'm not sure whether this counts as something that should be reported as a bug/improvement, It's a badly written function (with insufficient unit tests): http://d.puremagic.com/issues/show_bug.cgi?id=8026 Bye, bearophile
Re: Fixed-size arrays and randomShuffle()
OK, I took a look at your example, and I saw the kind of performance you were seeing. I performed an investigation on what could cause such a disparity and came up with a conclusion. The answer is two things: First of all, as noted above, D's default generator is a mersenne twister RNG. You can emulate Java's RNG like so: auto rng = LinearCongruentialEngine!(ulong, 25214903917uL, 11uL, 2uL^^48uL)(); Once I equalized that, I looked into the various methods that are called and settled in on uniform. https://github.com/D-Programming-Language/phobos/blob/master/std/random.d#L1154 As you can see, there's a division at line 1154 and another at line 1158. This means there's a minimum of two division operations every time uniform is called. Now, normally this isn't a big deal, but if we really want maximum performance, we need to eliminate at least one. If you replace lines 1154-1161 (auto bucketSize ... to return...) with: CountType rnum, result; do { rnum = cast(CountType) uniform!CountType(urng); result = rnum % count; } while (rnum > count && (rnum - result + (count - 1)) < (rnum - result - 1)); return cast(typeof(return)) (min + result); Then the time taken shrinks down to roughly the same (within a tenth of a second) as Java. I'll probably clean this up (and write some comments on how this works) and see about submitting it as a patch unless anyone sees anything wrong with this approach.
Re: ptrace (process trace system call) on Linux from D
Thank you for the reply, your recommendation works. I could however not find ptrace anywhere in druntime. There is only one mention of it in std.process, in a comment. But I do have some other questions: (1) Can I declare a ptrace function which calls the original ptrace? (I would like to check the return value and errno for exception throwing and such). I essentially want to shadow the original. (2) Is it more D-ish to use something like "enum PTRequest { traceMe = 0, ... }" instead of the fully capitalised originals? It doesn't seem to affect the working of things. (3) wait() is declared as returning a pid_t in the manpage, and is declared as such in core.sys.posix.sys.wait. In std.c.process however, it returns an int. I can't even find a process.h in my Linux install. What am I supposed to use? I know it essentially doesn't matter, as pid_t is aliased as int. Are there D alternatives to wait() and fork() that I could use with ptrace() instead of the C posix system functions? (4) Some things are declared only in core.*, not in std.*. Will they be added at some point or is this how it's supposed to be?
Re: cannot cast
On Thursday, May 03, 2012 10:54:47 Namespace wrote: > On Thursday, 3 May 2012 at 08:46:26 UTC, Chris Cain wrote: > > On Thursday, 3 May 2012 at 08:00:43 UTC, Namespace wrote: > >> So, you mean that if i declared any parameter as const, it > >> have to stay const all the time? > > > > Yes. const = you can't change. Changing it is invalid behavior. > > Imagine const/immutable as bits in readonly memory and you'll > > have to right mindset. > > > >> What would you do, if you need in a special case a mutable > >> version or must change the object itself? > >> Because there is no "mutable" keyword in D you have to cast > >> away the constness. > > > > In what way do you mean? If it's something you honestly _need_ > > to change and it's const, then maybe throwing an exception > > would be appropriate. > > I thought that const = "cannot change directly" and immutable > stands for "cannot change all the time". If not, why exist both > storage classes beside? An immutable variable can never be changed by any reference to that data. It's also implicitly shared across threads (since it can never change). If a const variable is a value type, then there really isn't any difference between const and immutable. If it's a reference type, then it just indicates that that particular reference cannot alter the data. Another reference may or may not be able to (and const is _not_ implicitly shared across threads, because the data _can_ change if there are mutable references to it). But if a reference is const, it's breaking the type system to cast away const and alter the data precisely because the compiler can't know whether that data is actually mutable or not. For instance, what if if you did something like const var = new immutable(A); var may be const, but it refers to a value which is actually immutable. Depending on what the compiler does, mutating var could result in nasty stuff like segfaults. In the general case, the compiler has no way of knowing whether a const variable is really mutable or immutable underneath. So, casting away const and mutating a variable is undefined behavior. As far as the compiler is concerned, a variable is _never_ mutated through a const reference, and it will optimize code based on that. So, casting away const can not only result in segfaults if the data is actually immutable, but it can result in incorrect behavior due to optimizations that the compiler makes based on the assumption that the variable wouldn't change but which you violated by casting away const and mutating the variable. Unlike immutable, _other_ references to the data may mutate it (and the compiler must take that into account when optimizing), but you should never try and mutate a const variable. Once something is const, _leave_ it that way. If you need a mutable reference to it, then you need to get one which was mutable in the first place rather than coming from the const reference through casting. Casting away const is legal, because D is a systems language, but actually mutating the variable after casting away const is undefined behavior, so you should never do it unless you really know what you're doing. http://stackoverflow.com/questions/4219600/logical-const-in-d - Jonathan M Davis
Re: string find and replace
On 5/3/12 11:01 PM, Ary Manzana wrote: On 5/3/12 9:30 PM, Iain wrote: On Thursday, 3 May 2012 at 14:22:57 UTC, Iain wrote: Forgive me if I am missing something obvious, but is there a simple option for finding all instances of a particular character in a string or char[] and replacing them with another character? I can do this with std.regex, but it seems overkill, when all I want is the equivalent of PHP's str_replace() function. Many thanks! Apologies, after half an hour searching, I post, then five minutes later figure it out. myString = replace(myString, to, from); // from std.array Note that you can also do: myString = myString.replace(to, from) I'd point you to the reference on the official page (UFCS: unified function call syntax), but I can't find it... and it should be replace(from, to)
Re: string find and replace
On 5/3/12 9:30 PM, Iain wrote: On Thursday, 3 May 2012 at 14:22:57 UTC, Iain wrote: Forgive me if I am missing something obvious, but is there a simple option for finding all instances of a particular character in a string or char[] and replacing them with another character? I can do this with std.regex, but it seems overkill, when all I want is the equivalent of PHP's str_replace() function. Many thanks! Apologies, after half an hour searching, I post, then five minutes later figure it out. myString = replace(myString, to, from); // from std.array Note that you can also do: myString = myString.replace(to, from) I'd point you to the reference on the official page (UFCS: unified function call syntax), but I can't find it...
Re: Fixed-size arrays and randomShuffle()
On a related note, how did you get the other random generators working? I tried to compile this and it gives me an error: -=-=-=- import std.random, std.stdio, std.datetime; void main() { int[] arr = new int[5_000_000]; foreach(i, ref e; arr) e = i; auto rng = MinstdRand0(1); rng.seed(unpredictableSeed); StopWatch sw = AutoStart.yes; randomShuffle(arr, rng); sw.stop(); writeln("Took ", sw.peek().to!("msecs", double)(), "ms"); } -=-=-=- The error: -=-=-=- C:\D\dmd2\windows\bin\..\..\src\phobos\std\random.d(1263): Error: cannot implicitly convert expression (rndGen()) of type MersenneTwisterEngine!(uint,32,624,397,31,-1727483681u,11,7,-1658038656u,15,-272236544u,18) to LinearCongruentialEngine!(uint,16807,0,2147483647) -=-=-=- Is this a bug in 2.059? Or am I doing something wrong?
Re: Fixed-size arrays and randomShuffle()
On 2012-05-03 17:31, Chris Cain wrote: You might want to post your code... Sure! D: --- import std.random; import std.stdio; void main() { auto iterations = 1000; int[] a; for (int i = 0; i < 42; ++i) a ~= i; for (int i = 0; i < iterations; ++i) randomShuffle(a); } naushika:~/projects> dmd random.d && time ./random ./random 38,35s user 0,05s system 99% cpu 38,420 total --- Java (7): --- import java.util.ArrayList; import java.util.Collections; public class Rnd { public static void main(String... args) { int iterations = 1000; ArrayList a = new ArrayList(); for (int i = 0; i < 42; ++i) a.add(i); for (int i = 0; i < iterations; ++i) Collections.shuffle(a); } } naushika:~/projects> javac Rnd.java && time java Rnd java Rnd 9,92s user 0,03s system 100% cpu 9,922 total ---
Re: Compute in one pass 3 tokens position
Le lundi 30 avril 2012 à 14:52 +0200, bioinfornatics a écrit : > Hi, > I would like to know how compute in on pass 3 tokens position in a > sequence. > curently i do: > File f = File( "reader.d", "r" ); > scope(exit) f.close(); > char[1024] buffer; > char[] content = f.rawRead(buffer); > char[sizediff_t] token = ['(', '{', ';']; > auto position = map!( a => content.countUntil( a ) )( [ ['('], ['{'], > [';'] ] ); > > > if i use reduce instead map the build fail > update code for add attribute poure notrhow nd safe :) -- import std.string; import std.stdio; import std.conv; import std.c.process; /** * searchIndex * search at wich index is located each token in given sequence. * It compute it in one pass. * Returns: * An ssociative array: * key = token and value first index where is found * value take -1 if not found in given sequence. */ @safe nothrow pure sizediff_t[char[]] searchIndex( in char[] sequence, in char[][] token...) in{ assert(sequence !is null, "Error given sequence is null"); } body{ bool isComputing = true; size_t index = 0; size_t flag= 0; sizediff_t[char[]] result; foreach( tok; token) result[tok] = -1; while(isComputing){ if( index >= sequence.length ) isComputing = false; else if( flag == token.length ) isComputing = false; else{ foreach( tok; token){ if( sequence.length - index >= tok.length ){ const(char)[] currentToken = (tok.length > 1) ? sequence[index .. index + tok.length] : [sequence[index]]; if( currentToken in result && result[currentToken] == -1 ){ result[currentToken] = index; flag++; } } } index++; } } return result; } void main( string[] args ){ if( args.length == 1 ){ writefln( "Usage %s...", args[0] ); exit(0); } writeln( searchIndex( "This a cool statement such as D is fun. Use it and got the D power. Oh yeah! Are you ready? Try it!! Have fun.", args[1..$]) ); }
Re: Fixed-size arrays and randomShuffle()
On Thursday, 3 May 2012 at 14:41:20 UTC, Vidar Wahlberg wrote: I tried those two as well. Still significantly slower than what I can achieve in Java. You might want to post your code... I wrote this code in D: -=-=-=- import std.random, std.stdio, std.datetime; void main() { int[] arr = new int[5_000_000]; foreach(i, ref e; arr) e = i; StopWatch sw = AutoStart.yes; arr.randomShuffle(); sw.stop(); writeln("Took ", sw.peek().to!("msecs", double)(), "ms"); } -=-=-=- And it performed _identically_ to this in Java: -=-=-=- import java.util.ArrayList; import java.util.Collections; public class Main { public static void main(String[] args) { ArrayList ints = new ArrayList<>(5000); for(int i = 0; i < 5_000_000; ++i) ints.add(i); long startTime = System.currentTimeMillis(); Collections.shuffle(ints); long endTime = System.currentTimeMillis(); System.out.println("Took " + (endTime - startTime) + "ms"); } } -=-=-=-
Re: Compute in one pass 3 tokens position
Le lundi 30 avril 2012 à 14:52 +0200, bioinfornatics a écrit : > Hi, > I would like to know how compute in on pass 3 tokens position in a > sequence. > curently i do: > File f = File( "reader.d", "r" ); > scope(exit) f.close(); > char[1024] buffer; > char[] content = f.rawRead(buffer); > char[sizediff_t] token = ['(', '{', ';']; > auto position = map!( a => content.countUntil( a ) )( [ ['('], ['{'], > [';'] ] ); > > > if i use reduce instead map the build fail > - CODE --- import std.stdio; import std.conv; import std.c.process; sizediff_t[string] counter( in char[] sequence, string[] token...) in{ assert(sequence !is null, "Error given sequence is null"); } body{ bool isComputing = true; size_t index = 0; size_t flag= 0; sizediff_t[string] result; foreach( tok; token) result[tok] = -1; while(isComputing){ if( index >= sequence.length ) isComputing = false; else if( flag == token.length ) isComputing = false; else{ foreach( tok; token){ if( sequence.length - index >= tok.length ){ string currentToken = to!string(sequence[index .. index + tok.length]); if( currentToken in result && result[currentToken] == -1 ){ result[currentToken] = index; flag++; } } } index++; } } return result; } void main( string[] args ){ if( args.length == 1 ){ writefln( "Usage %s...", args[0] ); exit(0); } writeln( counter( "This a cool statement such as D is fun. Use it and ot the D power. Oh yeah! Are you ready? Try it!! Have fun.", args[1..$]) ); } -- END CODE --- $ ./test This D ! ["D":30, "!":74, "This":0] import std.string; if all token is found befoore reach end sequence it stop and save us from some loop it works too if token do not has same length as shown in example
Re: Passing array as const slows down code?
On 05/03/12 16:07, Steven Schveighoffer wrote: > On Wed, 02 May 2012 16:05:13 -0400, Joseph Rushton Wakeling > wrote: > >> On 30/04/12 16:03, Steven Schveighoffer wrote: >>> Try removing the ref and see if it goes back. That usage of ref should not >>> affect anything (if anything it should be slower, since it's an extra level >>> of >>> indirection). >> >> Removing the ref ups the time as described before, but only with GDC (DMD >> the runtime is the same). It's a real effect. > > I'm not familiar with GDC, but as bearophile says, it sounds like a compiler > bug. Maybe GDC is making an optimization in one case and not in the other, > but both should be equivalently able to get the optimization. > >> >>> There is no implicit local copy for const. I have a suspicion that you >>> changed >>> two things and forgot about one of them when running your tests. >> >> Really don't think so. You can even check the version history of changes if >> you like! > > IIRC, your original post concerned not-checked in code. Anyway, if you've > re-run the tests, this is a confirmation. I'd go ahead and file a bug > against GDC. Rest assured, const should not *slow down* anything. There *was* a GDC bug some time ago, where a 'const' or 'in' function argument prevented inlining. Iain fixed it, so unless an old GDC version is used, it's probably not related. http://forum.dlang.org/thread/jdhb57$10vf$1...@digitalmars.com?page=16#post-mailman.33.1325763631.16222.d.gnu:40puremagic.com artur
Re: Fixed-size arrays and randomShuffle()
On 2012-05-03 16:26, Dmitry Olshansky wrote: It's all about RNG used behind the scenes. Default one is Mersane Twister which (AFAIK) is not particularly fast. But has a period of 2^19937 elements. You should probably use XorShift or MinstdRand generator and a version of shuffle with 2nd parameter. I tried those two as well. Still significantly slower than what I can achieve in Java.
Re: string find and replace
On Thursday, 3 May 2012 at 14:22:57 UTC, Iain wrote: Forgive me if I am missing something obvious, but is there a simple option for finding all instances of a particular character in a string or char[] and replacing them with another character? I can do this with std.regex, but it seems overkill, when all I want is the equivalent of PHP's str_replace() function. Many thanks! Apologies, after half an hour searching, I post, then five minutes later figure it out. myString = replace(myString, to, from); // from std.array
Re: Fixed-size arrays and randomShuffle()
On 03.05.2012 18:02, Ali Çehreli wrote: > A quick follow-up: > I've tried some various random number engines, but neither come even > close to the performance of whatever is used for Java's > "Collection.shuffle()" method. Perhaps someone can shed some light on this? I have no idea with that one. It's all about RNG used behind the scenes. Default one is Mersane Twister which (AFAIK) is not particularly fast. But has a period of 2^19937 elements. You should probably use XorShift or MinstdRand generator and a version of shuffle with 2nd parameter. -- Dmitry Olshansky
string find and replace
Forgive me if I am missing something obvious, but is there a simple option for finding all instances of a particular character in a string or char[] and replacing them with another character? I can do this with std.regex, but it seems overkill, when all I want is the equivalent of PHP's str_replace() function. Many thanks!
Re: ref semantics with hashes
On Wed, 02 May 2012 16:32:04 -0400, H. S. Teoh wrote: On Wed, May 02, 2012 at 09:38:35PM +0200, Andrej Mitrovic wrote: [...] So if the hash wasn't already initialized then the reference in the Foo struct is a reference to null, and if you duplicate that reference and add a key the old reference still points to null. The only way to ensure a proper link with a hash is to initialize it with a key and then immediately remove that key, which makes the hash not-null but empty: [...] Why do we have such error-prone semantics? I was told that this was expected behaviour. Should the new AA implementation change this, so that it always allocates an empty AA upon instantiation? This can't be done. You can always create a struct without calling any code. What I'd like to see is an initializer function/property, e.g.: auto a = int[int].create(); // static property that allocates a new empty AA. -Steve
Re: Access Violation in callback from sort
On Wed, 02 May 2012 11:27:57 -0400, Jabb wrote: Just got the TDPL book and it's a great read! I learn best when typing out the code myself, so I decided to make a single VisualD project and put the different exercises in separate modules. I am having problems with sort in std.algorithms - well, actually it appears to be a closure problem when sort calls my delegate. There shouldn't be any closure here, sort is not storing the delegate pointer. Here's a sample of the problem - in main.d I have //-- module main; import std.algorithm; void main() { uint[string] counts = [ "a":4, "b":5, "c":3, "d":1 ]; string[] keys = counts.keys; sort!((a, b) { return counts[a] > counts[b]; })(keys); } //-- Alone this works just fine. But if I add another file called myalgs.d, and put the following in it: //-- module myalgs; import std.algorithm; //-- Then I get the following exception: object.Error: Access Violation C:\D\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d(7112): mainmain__T8sortImplS14main9__lambda3VE3std9algorithm12SwapStrategy0TAAyaZsortImpl Steping through the code it appears that the Access Violation occurs when accessing counts[a]. I am using DMD32 v2.059; my compilation command line looks like: dmd -g -debug -X -Xf"$(IntDir)\$(TargetName).json" -deps="$(OutDir)\$(ProjectName).dep" -of"$(OutDir)\$(ProjectName).exe_cv" -map "$(INTDIR)\$(SAFEPROJECTNAME).map" -L/NOMAP I can't see any errors, I think this is worthy of a bug report, it's nice and small and self-contained. http://d.puremagic.com/issues -Steve
Re: Passing array as const slows down code?
On Wed, 02 May 2012 16:05:13 -0400, Joseph Rushton Wakeling wrote: On 30/04/12 16:03, Steven Schveighoffer wrote: Try removing the ref and see if it goes back. That usage of ref should not affect anything (if anything it should be slower, since it's an extra level of indirection). Removing the ref ups the time as described before, but only with GDC (DMD the runtime is the same). It's a real effect. I'm not familiar with GDC, but as bearophile says, it sounds like a compiler bug. Maybe GDC is making an optimization in one case and not in the other, but both should be equivalently able to get the optimization. There is no implicit local copy for const. I have a suspicion that you changed two things and forgot about one of them when running your tests. Really don't think so. You can even check the version history of changes if you like! IIRC, your original post concerned not-checked in code. Anyway, if you've re-run the tests, this is a confirmation. I'd go ahead and file a bug against GDC. Rest assured, const should not *slow down* anything. -Steve
Re: Fixed-size arrays and randomShuffle()
On 05/03/2012 06:55 AM, Vidar Wahlberg wrote: > On 2012-05-03 15:34, Ali Çehreli wrote: >> Fixed-length arrays are value types. 'a' is copied to randomShuffle() so >> its copy is shuffled. Passing a slice of the whole array works: >> >> randomShuffle(a[]); > > True, it is however still not exceptionally newbie (or perhaps even > user?) friendly (my question was more of "does it have to be this way?" > rather than "how do you do this?", even though I appreciate the answer > on how to do it). > Is it not possible for the compilator to let you know that what you're > doing doesn't make any sense? Random shuffle can work on a fixed-length array and there is a way for the implementation to know: import std.traits; // ... __traits(isStaticArray, a) That can be used in a template constraint. > A quick follow-up: > I've tried some various random number engines, but neither come even > close to the performance of whatever is used for Java's > "Collection.shuffle()" method. Perhaps someone can shed some light on this? I have no idea with that one. Ali
Re: Fixed-size arrays and randomShuffle()
Why would you not want it to shuffle a fixed array? That's a very frustrating silent failure.
Re: Transforming a range back to the original type?
On Thu, 03 May 2012 13:17:40 +0200, Jacob Carlborg wrote: On 2012-05-03 09:43, Simen Kjaeraas wrote: In addition to std.array.array, as others have pointed out, there is also std.range.InputRangeObject. I'm not sure if I understand what InputRangeObject does. But I don't think it does what I want. It basically wraps a range in a class interface. This allows you to use InputRangeObject!T instead of T[]. I've never used it, so I'm not sure what it does or how it does it.
Re: Fixed-size arrays and randomShuffle()
On 2012-05-03 15:34, Ali Çehreli wrote: Fixed-length arrays are value types. 'a' is copied to randomShuffle() so its copy is shuffled. Passing a slice of the whole array works: randomShuffle(a[]); True, it is however still not exceptionally newbie (or perhaps even user?) friendly (my question was more of "does it have to be this way?" rather than "how do you do this?", even though I appreciate the answer on how to do it). Is it not possible for the compilator to let you know that what you're doing doesn't make any sense? A quick follow-up: I've tried some various random number engines, but neither come even close to the performance of whatever is used for Java's "Collection.shuffle()" method. Perhaps someone can shed some light on this?
Re: Fixed-size arrays and randomShuffle()
On 05/03/2012 06:30 AM, Vidar Wahlberg wrote: May be that this works as intended, but it fooled me: --- import std.random; import std.stdio; void main() { int[5] a = 0; a[0] = 1; int[] b = [1, 0, 0, 0, 0]; randomShuffle(a); Fixed-length arrays are value types. 'a' is copied to randomShuffle() so its copy is shuffled. Passing a slice of the whole array works: randomShuffle(a[]); writeln(a); randomShuffle(b); writeln(b); } --- In DMD 2.0.59 the fixed-size array "a" won't be shuffled (the dynamic array "b" will), and you won't get any warning about it. I'm not sure whether this counts as something that should be reported as a bug/improvement, nor if only randomShuffle() displays this behaviour, perhaps you could enlighten me. Ali
Fixed-size arrays and randomShuffle()
May be that this works as intended, but it fooled me: --- import std.random; import std.stdio; void main() { int[5] a = 0; a[0] = 1; int[] b = [1, 0, 0, 0, 0]; randomShuffle(a); writeln(a); randomShuffle(b); writeln(b); } --- In DMD 2.0.59 the fixed-size array "a" won't be shuffled (the dynamic array "b" will), and you won't get any warning about it. I'm not sure whether this counts as something that should be reported as a bug/improvement, nor if only randomShuffle() displays this behaviour, perhaps you could enlighten me.
Re: Transforming a range back to the original type?
On 2012-05-03 09:43, Simen Kjaeraas wrote: In addition to std.array.array, as others have pointed out, there is also std.range.InputRangeObject. I'm not sure if I understand what InputRangeObject does. But I don't think it does what I want. -- /Jacob Carlborg
Re: ref semantics with hashes
On 05/03/12 00:38, Andrej Mitrovic wrote: > In fact what would *actually* solve this problem (for me) is if/when > we have aliases implemented for this scenario: > > import std.stdio; > > struct Foo > { >int[] hash; > } > > void main() > { > Foo foo; > alias foo.hash hash2; > > hash2[0] = 1; > writeln(foo.hash); // [1:1] > writeln(hash2); // [1:1] > } > > Hopefully we get that one day. Until then, you can use @property ref hash2() { return foo.hash; } which is a bit more verbose, but functionally equivalent. Your new alias syntax would be just sugar, and would (a) hide the complexity of the operation and (b) have to be artificially restricted. alias p1.p2.p3.p4.p5.p6.hash hash3; alias p1.p2?p1.p2.hash:p3.p4.hash hash4; alias getfoo().hash hash5; etc would also be possible otherwise and that isn't necessarily a good idea. artur
Re: extern and opaque structs
On 2012-05-03 07:00, James Miller wrote: I'm doing C bindings and I have an opaque struct and an extern'd variable of the type of that struct. The problem is that dmd is complaining that the struct has no definition (which is true). Making it a pointer works (expected) but i can't do that because the interface is expecting an full struct. Adding __gshared doesn't help. I assume this is bug, since usage of extern means that I don't need to know the size, since it will be allocated in the C code, not the D code. -- James Miller This doesn't work: struct Foo; extern (C) extern Foo foo; -- /Jacob Carlborg
Re: cannot cast
On Thursday, 3 May 2012 at 09:00:08 UTC, Chris Cain wrote: const = you (as in, your view of the data as you're working with it) can't change Actually, let me be even clearer with this... I mean _you_ cannot change it, but it might be changed by someone else's view, in which case it would appear to change in your view ... but not by any interaction you make with it. This means concretely that anything you do with the object will have no effect on its bit representation in memory, although the bit representation in memory might be changed by other threads/processes/views.
Re: cannot cast
On Thursday, 3 May 2012 at 08:54:48 UTC, Namespace wrote: I thought that const = "cannot change directly" and immutable stands for "cannot change all the time". If not, why exist both storage classes beside? const = you (as in, your view of the data as you're working with it) can't change immutable = no one can change it ... as in, there exists no view of the data that can mutate it. It's a subtle distinction. In fact, you can be handed a "const" and it's actually immutable underneath. And since immutable data can actually be stored in read only memory...
Re: cannot cast
On Thursday, 3 May 2012 at 08:46:26 UTC, Chris Cain wrote: On Thursday, 3 May 2012 at 08:00:43 UTC, Namespace wrote: So, you mean that if i declared any parameter as const, it have to stay const all the time? Yes. const = you can't change. Changing it is invalid behavior. Imagine const/immutable as bits in readonly memory and you'll have to right mindset. What would you do, if you need in a special case a mutable version or must change the object itself? Because there is no "mutable" keyword in D you have to cast away the constness. In what way do you mean? If it's something you honestly _need_ to change and it's const, then maybe throwing an exception would be appropriate. I thought that const = "cannot change directly" and immutable stands for "cannot change all the time". If not, why exist both storage classes beside?
Re: cannot cast
On Thursday, 3 May 2012 at 08:00:43 UTC, Namespace wrote: So, you mean that if i declared any parameter as const, it have to stay const all the time? Yes. const = you can't change. Changing it is invalid behavior. Imagine const/immutable as bits in readonly memory and you'll have to right mindset. What would you do, if you need in a special case a mutable version or must change the object itself? Because there is no "mutable" keyword in D you have to cast away the constness. In what way do you mean? If it's something you honestly _need_ to change and it's const, then maybe throwing an exception would be appropriate.
Re: Transforming a range back to the original type?
On 2012-05-02 23:40, Jonathan M Davis wrote: On Wednesday, May 02, 2012 23:01:21 Jacob Carlborg wrote: Is there a general function for transforming a range back to the original type? If not, would it be possible to create one? You mean that if you have something like auto range = getRangeFromSomewhere(); auto newRange = find(filter!func(range), value); you want to transform newRange back to the same type as range? No, I want to transform newRange back to a collection, the same type as the original collection. I was thinking something like this: Collection c = new Collection(); c = c.filter!(x => x < 3).toCollection(); -- /Jacob Carlborg
Re: cannot cast
On 05/03/2012 09:33 AM, Namespace wrote: On Wednesday, 2 May 2012 at 22:38:36 UTC, Namespace wrote: Other, shorter example: [code] import std.stdio, std.traits; class A { int val; alias val this; T opCast(T : Object)() { writeln("FOO"); return to!(T)(this); } } class B : A { } T to(T : Object, U : Object)(const U obj) { return *(cast(T*) &obj); } T const_cast(T)(const T obj) { return cast(T) obj; } void main () { A a = new B(); a.val = 42; writefln("a.val: %d", a.val); B* b = cast(B*) &a; writefln("*b.val: %d", b.val); B b1 = to!(B)(a); writefln("b1.val: %d", b1.val); B b2 = cast(B) a; writefln("b2.val: %d", b2.val); const B b3 = cast(B) a; B b4 = const_cast(b3); } [/code] print: alias_this_impl.d(24): Error: function alias_this_impl.A.opCast!(B).opCast () is not callable using argument types () alias_this_impl.d(44): Error: template instance alias_this_impl.const_cast!(B) e rror instantiating I'm not very skillful in such "template" stories. Maybe someone can help me? Solved with T const_cast(T)(const T obj) { return to!(T)(obj); } But i think that there must exist a more nicer way to cast away const, isn't there? To cast away "const" with a simple cast to "T" fails (see my post above), because i have no idea, how i can restrict my opCast. So i have to convert it again with "to". Do some of you have any ideas how i can restrict my opCast, so my const_cast doesn't match it, e.g. with some template magic? Unqual können Sie finden in std.traits. template Unqual(T) { version (none) // Error: recursive alias declaration @@@BUG1308@@@ { static if (is(T U == const U)) alias Unqual!U Unqual; else static if (is(T U == immutable U)) alias Unqual!U Unqual; else static if (is(T U == inout U)) alias Unqual!U Unqual; else static if (is(T U == shared U)) alias Unqual!U Unqual; else alias T Unqual; } else // workaround { static if (is(T U == shared(const U))) alias U Unqual; else static if (is(T U == const U )) alias U Unqual; else static if (is(T U == immutable U )) alias U Unqual; else static if (is(T U == inout U )) alias U Unqual; else static if (is(T U == shared U )) alias U Unqual; else alias T Unqual; } } unittest { static assert(is(Unqual!(int) == int)); static assert(is(Unqual!(const int) == int)); static assert(is(Unqual!(immutable int) == int)); static assert(is(Unqual!(inout int) == int)); static assert(is(Unqual!(shared int) == int)); static assert(is(Unqual!(shared(const int)) == int)); alias immutable(int[]) ImmIntArr; static assert(is(Unqual!(ImmIntArr) == immutable(int)[])); }
Re: cannot cast
On Thursday, 3 May 2012 at 07:41:32 UTC, Simen Kjaeraas wrote: On Thu, 03 May 2012 00:38:35 +0200, Namespace wrote: I'm not very skillful in such "template" stories. Maybe someone can help me? The main problem here is your opCast is non-const. (it's always an indication of const problems when DMD says " is not callable using argument types ()") Solution: class A { int val; alias val this; T opCast(T : Object)() { writeln("FOO"); return to!(T)(this); } // Add this T opCast(T : Object)() const { writeln("FOO"); return to!(T)(this); } } My tests are failed, but isn't it possible, to reduce both methods to one with the inout keyword?
Re: cannot cast
If you want to restrict opCast, then use a template constraint, constraining it to what you want to work with it. Also, casting away const is generally a bad idea in D. Casting away const and mutating a variable is an _extremely_ bad idea. You _really_ shouldn't be doing it. So, the fact that you _have_ a function which is specifically trying to cast away const is almost certainly _not_ a good idea. http://stackoverflow.com/questions/4219600/logical-const-in-d - Jonathan M Davis So, you mean that if i declared any parameter as const, it have to stay const all the time? What would you do, if you need in a special case a mutable version or must change the object itself? Because there is no "mutable" keyword in D you have to cast away the constness.
Re: Transforming a range back to the original type?
On 2012-05-02 23:07, Matt Soucy wrote: On 05/02/2012 05:01 PM, Jacob Carlborg wrote: Is there a general function for transforming a range back to the original type? If not, would it be possible to create one? I believe std.array's array function does what you want. -Matt I was thinking of a generic function that works for all types of collections and not arrays. -- /Jacob Carlborg
Re: cannot cast
On Thursday, 3 May 2012 at 07:41:32 UTC, Simen Kjaeraas wrote: On Thu, 03 May 2012 00:38:35 +0200, Namespace wrote: I'm not very skillful in such "template" stories. Maybe someone can help me? The main problem here is your opCast is non-const. (it's always an indication of const problems when DMD says " is not callable using argument types ()") Solution: class A { int val; alias val this; T opCast(T : Object)() { writeln("FOO"); return to!(T)(this); } // Add this T opCast(T : Object)() const { writeln("FOO"); return to!(T)(this); } } Hm, simple. Thank you, as long as the bug isn't fixed, this has to be enough. :)
Re: cannot cast
On Thursday, May 03, 2012 09:33:01 Namespace wrote: > On Wednesday, 2 May 2012 at 22:38:36 UTC, Namespace wrote: > > Other, shorter example: > > > > [code] > > import std.stdio, std.traits; > > > > class A { > > > > int val; > > > > alias val this; > > > > T opCast(T : Object)() { > > > > writeln("FOO"); > > > > return to!(T)(this); > > > > } > > > > } > > > > class B : A { > > > > } > > > > T to(T : Object, U : Object)(const U obj) { > > > > return *(cast(T*) &obj); > > > > } > > > > T const_cast(T)(const T obj) { > > > > return cast(T) obj; > > > > } > > > > void main () { > > > > A a = new B(); > > a.val = 42; > > > > writefln("a.val: %d", a.val); > > > > B* b = cast(B*) &a; > > writefln("*b.val: %d", b.val); > > > > B b1 = to!(B)(a); > > writefln("b1.val: %d", b1.val); > > > > B b2 = cast(B) a; > > writefln("b2.val: %d", b2.val); > > > > const B b3 = cast(B) a; > > > > B b4 = const_cast(b3); > > > > } > > [/code] > > > > print: > > > > alias_this_impl.d(24): Error: function > > alias_this_impl.A.opCast!(B).opCast () is > > > > not callable using argument types () > > > > alias_this_impl.d(44): Error: template instance > > alias_this_impl.const_cast!(B) e > > rror instantiating > > > > I'm not very skillful in such "template" stories. Maybe someone > > can help me? > > Solved with > > T const_cast(T)(const T obj) { > return to!(T)(obj); > } > > But i think that there must exist a more nicer way to cast away > const, isn't there? > > To cast away "const" with a simple cast to "T" fails (see my post > above), because i have no idea, how i can restrict my opCast. So > i have to convert it again with "to". Do some of you have any > ideas how i can restrict my opCast, so my const_cast doesn't > match it, e.g. with some template magic? If you want to restrict opCast, then use a template constraint, constraining it to what you want to work with it. Also, casting away const is generally a bad idea in D. Casting away const and mutating a variable is an _extremely_ bad idea. You _really_ shouldn't be doing it. So, the fact that you _have_ a function which is specifically trying to cast away const is almost certainly _not_ a good idea. http://stackoverflow.com/questions/4219600/logical-const-in-d - Jonathan M Davis
Re: Transforming a range back to the original type?
On Wed, 02 May 2012 23:01:21 +0200, Jacob Carlborg wrote: Is there a general function for transforming a range back to the original type? If not, would it be possible to create one? In addition to std.array.array, as others have pointed out, there is also std.range.InputRangeObject.
Re: cannot cast
On Thu, 03 May 2012 00:38:35 +0200, Namespace wrote: I'm not very skillful in such "template" stories. Maybe someone can help me? The main problem here is your opCast is non-const. (it's always an indication of const problems when DMD says " is not callable using argument types ()") Solution: class A { int val; alias val this; T opCast(T : Object)() { writeln("FOO"); return to!(T)(this); } // Add this T opCast(T : Object)() const { writeln("FOO"); return to!(T)(this); } }
Re: cannot cast
On Wednesday, 2 May 2012 at 22:38:36 UTC, Namespace wrote: Other, shorter example: [code] import std.stdio, std.traits; class A { int val; alias val this; T opCast(T : Object)() { writeln("FOO"); return to!(T)(this); } } class B : A { } T to(T : Object, U : Object)(const U obj) { return *(cast(T*) &obj); } T const_cast(T)(const T obj) { return cast(T) obj; } void main () { A a = new B(); a.val = 42; writefln("a.val: %d", a.val); B* b = cast(B*) &a; writefln("*b.val: %d", b.val); B b1 = to!(B)(a); writefln("b1.val: %d", b1.val); B b2 = cast(B) a; writefln("b2.val: %d", b2.val); const B b3 = cast(B) a; B b4 = const_cast(b3); } [/code] print: alias_this_impl.d(24): Error: function alias_this_impl.A.opCast!(B).opCast () is not callable using argument types () alias_this_impl.d(44): Error: template instance alias_this_impl.const_cast!(B) e rror instantiating I'm not very skillful in such "template" stories. Maybe someone can help me? Solved with T const_cast(T)(const T obj) { return to!(T)(obj); } But i think that there must exist a more nicer way to cast away const, isn't there? To cast away "const" with a simple cast to "T" fails (see my post above), because i have no idea, how i can restrict my opCast. So i have to convert it again with "to". Do some of you have any ideas how i can restrict my opCast, so my const_cast doesn't match it, e.g. with some template magic?