Re: D equivalent of C++ reinterpret cast?
Juanjo Alvarez Wrote: > Unions are not allowed in SafeD, so I guess they are considered > unsafe in D. They're safer in this particular case. Note how original poster forgot about taking and address.
Re: Copying a delegate
Jonathan M Davis Wrote: > delegate by definition has context which is not going to be copied. So, any > functon pointer or delegate that you have must refer to a function which is > logically pure, otherwise any algorithm that relies on save is not going to > work > correctly. If phobos causes subtle bugs, it's a bug worth filing.
Re: Copying a delegate
On Monday 20 September 2010 01:08:25 Kagamin wrote: > Jonathan M Davis Wrote: > > delegate by definition has context which is not going to be copied. So, > > any functon pointer or delegate that you have must refer to a function > > which is logically pure, otherwise any algorithm that relies on save is > > not going to work correctly. > > If phobos causes subtle bugs, it's a bug worth filing. Except that it's not really phobos' fault. The problem is that once part of the state of a struct or class is a delegate, you *can't* copy it. As far as I know, there is no way in the language to do it. A forward range's save property is supposed to give you a copy of the range which copies the state specific to iterating the range such that you can iterate the copy to your heart's content without affecting the original's ability to iterate. But if a delegate is part of the iteration state of a range, and that delegate isn't logically pure, the copy is going to use that delegate and alter the state of the original range, because they share that delegate. I don't think that there's anything Phobos can do about it. It's a limitation of delegates. - Jonathan M Davis
Re: Purity with references and pointers
Simen kjaeraas wrote: Jonathan M Davis wrote: Except that since when is anything implictly convertable to immutable? Implicitly converted to const, yes. That happens often enough, but immutable? Anything that does not contain pointers or references to non-immutable data is implicitly convertible to immutable, if passed by value. And you definitely don't have to use immutable references with pure functions. That sounds like a bug. Unless you mean things like immutable(char)[], which is implicitly convertible to immutable, according to the above rules. I have gotten some const-related errors when using pure on member functions, so I get the impression that using pure on a member function implicitly makes it const, but I'm not sure if that's enough. The 'this' pointer is also a parameter to a function, so also needs to be immutable. But that's impossible, except for trivial, useless classes.
Re: Copying a delegate
Jonathan M Davis Wrote: > I don't think that there's anything Phobos can do > about it. It's a limitation of delegates. If the range doesn't support copying, it shouldn't pretend to support it, and algorithms relying on copy won't compile.
Re: Error: cannot implicitly convert expression (this) of type const(S) to S
On Sat, 18 Sep 2010 17:20:31 -0400, Jonathan M Davis wrote: On Saturday 18 September 2010 09:58:15 Steven Schveighoffer wrote: In reality, you cannot make save const, unless you want to do a deep copy (but I recommend against that, save should be a quick operation). Well, I was trying to make a deep copy (that's what it does if it doesn't have an array in it anyway). I suppose whether it really needs to be const or not depends on what you're trying to do with it. I'm definitely trying to create a range here, and if save() is supposed to make a copy of the range, whether that needs to be a shallow copy or a deep copy depends on what the std.algorithm stuff does with it. When I think copy, I usually think deep copy, but that's not necessarily the case. I will have to enquire as to the intent of save(). For value types, shallow copy and deep copy are the same, so it's not an issue. But for class ranges or struct ranges with references, it does become an issue. You don't want a deep copy of a range. All you want to copy is the iteration state, not the data. save is definitely supposed to be shallow. I.e. you should copy the range itself, not what the range points to. -Steve
Re: D equivalent of C++ reinterpret cast?
On Sun, 19 Sep 2010 13:39:38 -0400, Bradley Mitchell wrote: Hello, I'm trying to implement the Quake 3 fast inverse square root algorithm which requires casting from int to float without modifying the stored bits. A C++ reinterpret cast seems to accomplish this just fine but so far I have had no success in D after trying quite a few different things. Here is the C++ I've written that currently works: #include float fastInvSqrt( float x ) { const int INV_SQRT_N = 1597292357; const float MULT = 1.000363245811462f; float const mx = 0.5f * MULT * x; int xi = *reinterpret_cast( &x ); Note the use of pointers and address above? xi = INV_SQRT_N - (xi >> 1); x = *reinterpret_cast( &xi ); return x * (1.5f * MULT - mx * x * x); } int main() { float a = fastInvSqrt( 9.0f ); std::cout << a << std::endl; } And here is my D code that doesn't work yet: module test; import std.stdio; float fastInvSqrt( float x ) { const int INV_SQRT_N = 1597292357; const float MULT = 1.000363245811462f; float mx = 0.5f * MULT * x; int xi = cast(int)cast(void*)x; You forgot that here... int xi = *cast(int *)(&x); rule of thumb -- if you want to do a reinterpret cast, you usually must take the address first. The compiler never tries anything tricky on pointer casts. -Steve
Re: Purity with references and pointers
Jonathan M Davis Wrote: > If a pure function takes a reference/pointer, does that state that the result > of > the function will be the same on two calls to it if the reference/pointer > points > to the same data in both cases or if the data itself is unchanged? > > If it's a matter of pointing to the same data, then that could be horribly > broken. That would mean that as long as I pased in the same reference, the > compiler could cache the result but that the actual result of the function > could > have and should have been different for each call because the object pointed > to > was altered. You can search for bug report about purity of stdc string functions. Don proposed two flavors of purity. When you pass const data to pure function, the call effectively becomes impure.
Re: Where is module dstats.all for dflplot?
On Sat, 18 Sep 2010 07:15:35 -0400, Sam Hu wrote: > Greetings! > > I want to have a try on dflplot.But I don't find module dstats.all which > is used by dflplot.d,could anybody let me where it is? > > Thank you. Hi! David Simcha (the dflplot author) has changed the name of the library to Plot2Kill, so if you're still using dflplot, it's an old version. Check out the Plot2Kill project for the latest version: http://www.dsource.org/projects/plot2kill As far as I know, dstats is not required to use Plot2Kill, it's only used for the demo/test application. Anyway, if you need it, you can find it here: http://www.dsource.org/projects/dstats -Lars
Re: Error: cannot implicitly convert expression (this) of type const(S) to S
On Monday, September 20, 2010 04:11:05 Steven Schveighoffer wrote: > You don't want a deep copy of a range. All you want to copy is the > iteration state, not the data. > > save is definitely supposed to be shallow. I.e. you should copy the range > itself, not what the range points to. That makes sense, but whenever I see copy, I pretty much always think deep copy, though obviously a copy isn't always a deep copy or you wouldn't need the word deep. - Jonathan M Davis
Re: Copying a delegate
On Monday, September 20, 2010 04:08:11 Kagamin wrote: > Jonathan M Davis Wrote: > > I don't think that there's anything Phobos can do > > about it. It's a limitation of delegates. > > If the range doesn't support copying, it shouldn't pretend to support it, > and algorithms relying on copy won't compile. Except that you don't know what is in a delegate, or it wouldn't be a delegate. Many delegates can be reused just fine and thus "copied" because they are logically pure. Others can't be. If you have a range based on a delegate, unless you know every single function that could be used as the delegate, you have no way of knowing whether the delegate is logically pure. And even then, you'd only know it because you knew what the functions did; the compiler couldn't enforce it. So, you can have a range which properly supports copying as long as its delegate is logically pure, but you can't use the compiler to enforce that the delegate be logically pure. There's no way for Phobos to avoid the problem. The only way to completely avoid the problem is not to have ranges which are generated with delegates, but that would eliminate a lot of useful ranges. - Jonathan M Davis
Re: Applying a tuple to a function (and more)
On Sun, Sep 19, 2010 at 18:33, Juanjo Alvarez wrote: > Philippe Sigaud wrote: > > > What languages are you used to? You seem to do quite well with genericity > > :) > > What I've done profesionally and personally in the last year would be 90% > Python, 5% Java and 5% C++. So yes, since Python is like a D with an > uberauto and everything being runtime templates the real problem I have is > with generic declarations :) > OK, that's why you're using tuples for everything :) Python's tuples are cool. I think I *learnt* what tuples were while dabbling in Python a few years ago. (Haskell's ones are great too). Note that the 'real' D tuples are expression tuples (instantiated typetuples). The "T..." thingies in templates, once instantiated with T t; They know their length, are indexable, slicable, iterable, etc. In a way they are random-access range with a length, only with heterogeneous types. But I don't think they were conceived as tuples in other languages, not at first. I'd guess that, for Walter, they were just a natural extension/cleaning for templates, based on C++. But they are like Python's tuples! Except for one blatant limitation: they cannot be returned from a function :( But you can return a templated struct. So the basic idea is to wrap them in Tuple(T...) to be able to return them. Then std.typecons.tuple does its best to offer a interesting access to the underlying expression tuple. But it's not a first-class citizen in D: you cannot iterate them nor slice them... For now, because the situation has improved. What many people coming from C++/Java do is putting their stuff in structs/classes. They tend not to use tuples that much. This is much better, no doubt. I've changued that part too (I'm really > learning a lot with your posts, you should think about writing a book about > D too). > What I should do is moving my a** and have some code reviewed for Phobos. But it seems I can't find the time. When I've half an hour, I try to help here instead :) > Now I've two new roadblocks: > > Roadblock1: > > If the tuple is defined in the same file as the code expanding it (with the > template function in another file), it works. But if I move the tuple > definition to another file (urls.d) the compiler gives me the error: > > Error: Unions with overlapping fields are not yet supported in CTFE > urls.d(9): Error: cannot evaluate tuple("^/home/$",& index,42,3.14) at > compile time > urls.d(9): Error: cannot evaluate tuple("^/home/$",& index,42,3.14) at > compile time > > That is, this works: > > // file: bindselector.d > import std.typecons; > import views; > > void main() { > // tuple defined here > auto selector_data = tuple( "^/home/$", &(views.index!(int, double)), > 42, 3.14 ); > auto sel_regex_var = selector_data.field[0]; > auto sel_view_var = selector_data.field[1]; > sel_view_var(sel_regex_var, selector_data.expand[2..$]); > } > > > But moving the declaration of "selector_data" to a file urls.d and then > importing that file from bindselector.d gives me that error... bug? > What do you mean, you moved the declaration of selector_data ? You declared it outside main() in another module? I don't know why, I never declare date outside functions/objects. Maybe if you declare it in the 'root scope' of the module (I don't know how to call that: the basic scope of a module, the one where the module name; is), it's initialized at compile time. And at compile time, I'm not sure things like addresses &(...) have a sense. Did you try to make selector_data a function? auto selector_data() { return tuple("^/home/$", &(views.index!(int, double)),42, 3.14 );} > Roadblock2: > The next step is to define multiple tuples in urls.d inside some iterable > data structure, so bindselector.d can import that and do its thing inside a > foreach. > > The problem here is related again with my limitations declaring generics. > Since every tuple will have a different type signature, I tought that the > logical structure to group them would be... yes, another tuple :) Then I > would foreach on that structure and bind the params, etc. > > First try (Fail-1): > > // > auto selector_data_tuples = tuple( > tuple( "^/home/$", &(views.index!(int, > double)), 42, 3.14 ) > ); > > foreach(selector_data; selector_data_tuples) { > auto sel_regex_var = selector_data.field[0]; > auto sel_view_var = selector_data.field[1]; > sel_view_var(sel_regex_var, selector_data.expand[2..$]); > } > // > > Compile error: Error: cannot infer type for selector_data > > Logical, since the type of the iterated element in the foreach is fixed, > and > I'm iterating over tuples of different types. > Oh, but you can iterate on an expression tuple alright, even when all its elements have different types. I don't know why bearophile doesn't like that. It's just, as
Re: pure member functions
bearophile wrote: Jonathan M Davis: I assume that if you declare a member function as pure, then all of its parameters - including the invisible this - are included in that. That is, if all of them - including the invisible this - have the same value, then the result will be the same. This D2 program runs with no errors, and here there isn't a D language/compiler bug: struct Foo { int x; this (int xx) { this.x = xx; } pure int bar() { return x; } } void main() { Foo f = Foo(1); assert(f.bar() == 1); f.x *= 2; assert(f.bar() == 2); } Bye, bearophile You do need to be careful about concluding how 'pure' works based on the current behaviour of the compiler. There's a trap here. What if you use a hypothetical startTimer() function which executes a delegate every few clock ticks? void main() { Foo f = Foo(1); startTimer( () { f.x++; }); scope(exit) killTimer(); assert(f.bar() == 1); // may fail! f.x *= 2; assert(f.bar() == 2); } I actually think that 'pure' on a member function can only mean, it's cacheably pure if and only if 'this' can be cast to immutable. Which includes the important case where the call is made from a pure function (this implies that the 'this' pointer is either a local variable of a pure function, or an immutable object). Since pure functions cannot call impure functions, they can't do any of this nasty asynchronous stuff. In fact I think in general, that's how pure should work: once you're inside 'pure', you should be able to pass even mutable objects into pure functions. This is possible because although it's mutable, the entire code that modifies it is confined to a single function. So the compiler can determine if it is cacheably pure without performing any kind of whole program analysis. But this is just my opinion. I don't know if it will eventually work that way.
Re: pure member functions
On Mon, 20 Sep 2010 15:45:10 -0400, Don wrote: bearophile wrote: Jonathan M Davis: I assume that if you declare a member function as pure, then all of its parameters - including the invisible this - are included in that. That is, if all of them - including the invisible this - have the same value, then the result will be the same. This D2 program runs with no errors, and here there isn't a D language/compiler bug: struct Foo { int x; this (int xx) { this.x = xx; } pure int bar() { return x; } } void main() { Foo f = Foo(1); assert(f.bar() == 1); f.x *= 2; assert(f.bar() == 2); } Bye, bearophile You do need to be careful about concluding how 'pure' works based on the current behaviour of the compiler. There's a trap here. What if you use a hypothetical startTimer() function which executes a delegate every few clock ticks? void main() { Foo f = Foo(1); startTimer( () { f.x++; }); scope(exit) killTimer(); assert(f.bar() == 1); // may fail! f.x *= 2; assert(f.bar() == 2); } Wouldn't f have to be shared for this to be asynchronous? I actually think that 'pure' on a member function can only mean, it's cacheably pure if and only if 'this' can be cast to immutable. Which includes the important case where the call is made from a pure function (this implies that the 'this' pointer is either a local variable of a pure function, or an immutable object). Since pure functions cannot call impure functions, they can't do any of this nasty asynchronous stuff. I think it's ok for a function to be pure if all the arguments are unshared, regardless of immutability. However, in order to cache the return value, the reference itself must not be used as the key, but the entire data of the reference. Even if it's immutable, wouldn't you not want to cache the return values between two identical immutable objects? -Steve
Re: pure member functions
Steven Schveighoffer wrote: On Mon, 20 Sep 2010 15:45:10 -0400, Don wrote: bearophile wrote: Jonathan M Davis: I assume that if you declare a member function as pure, then all of its parameters - including the invisible this - are included in that. That is, if all of them - including the invisible this - have the same value, then the result will be the same. This D2 program runs with no errors, and here there isn't a D language/compiler bug: struct Foo { int x; this (int xx) { this.x = xx; } pure int bar() { return x; } } void main() { Foo f = Foo(1); assert(f.bar() == 1); f.x *= 2; assert(f.bar() == 2); } Bye, bearophile You do need to be careful about concluding how 'pure' works based on the current behaviour of the compiler. There's a trap here. What if you use a hypothetical startTimer() function which executes a delegate every few clock ticks? void main() { Foo f = Foo(1); startTimer( () { f.x++; }); scope(exit) killTimer(); assert(f.bar() == 1); // may fail! f.x *= 2; assert(f.bar() == 2); } Wouldn't f have to be shared for this to be asynchronous? That's an excellent point. 'pure' was put into the language long before 'shared' and '__gshared'. It could now just mean, "doesn't use static, globals, shared, or __gshared". And then cachable pure is just: pure, + all reference parameters are immutable. If this becomes the rule, it seems likely that pure functions would become far more common than impure ones. I actually think that 'pure' on a member function can only mean, it's cacheably pure if and only if 'this' can be cast to immutable. Which includes the important case where the call is made from a pure function (this implies that the 'this' pointer is either a local variable of a pure function, or an immutable object). Since pure functions cannot call impure functions, they can't do any of this nasty asynchronous stuff. I think it's ok for a function to be pure if all the arguments are unshared, regardless of immutability. However, in order to cache the return value, the reference itself must not be used as the key, but the entire data of the reference. Even if it's immutable, wouldn't you not want to cache the return values between two identical immutable objects? Possibly, but my guess is that it would take too long to check.
Re: Applying a tuple to a function (and more)
Philippe Sigaud: > Oh, but you can iterate on an expression tuple alright, even when all its > elements have different types. I don't know why bearophile doesn't like that. I like the iteration on typetuples (the nomenclature here is a mess, see bug 4113), but you have to use such iteration with care because it's a static foreach, your code may become very long (this is why in bug 4085 I have asked to require a "static foreach" to iterate on typetuples, to help the programmer see the difference better). Bye, bearophile
Re: D equivalent of C++ reinterpret cast?
Ali Ãehreli: > I remember being a part of a discussion where D'is unions were told to > be exactly the same as C's. That means, results of using a union is only > specified when it's used through one its members. Writing to one member > and reading from another is unspecified. It is clear that endianness and > padding should complicate matters. I have just written a post about this topic: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=117675 Bye and thank you, bearophile