Re: Primary Ranges of Containers
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 06/18/2012 01:08 PM, Jonathan M Davis wrote: > On Monday, June 18, 2012 10:06:44 Matthias Walter wrote: >> Hi, >> >> last week I realized that a const version of >> std.container.Array.opSlice() is missing. Now I looked at the >> code and I think that it is a general design problem. >> >> The docs state that "c.Range" is "The primary range type >> associated with the container.". I think we really always need >> two Range types (one for const view and one for non-const view) >> by design. >> >> I'd propose to always add a bool template parameter (maybe >> isConst?) to the range since most of the write-functionality can >> be "removed" by a static if statement in order to make the range >> read-only. >> >> Any suggestions? > > Yeah, it'll probably have to be templated. C++ already has to do > something similar with iterators and const_iterators. But since you > don't normally use the type of a range explicitly, it shouldn't be > a big deal. The one downside that might pose a problem though is > that if someone _does_ use the type explicitly, their code will > break if the type gets templated. We could make a second type > (ConstRange?) for the iterating over a const Array, but I'd be > tempted to just templatize the thing and let it break any code that > it breaks. std.container is already likely to break stuff to at > least some extent when the custom allocators get added anyway. I > suppose that we could just rename the type and then create an alias > for the current type > > struct ArrayRange(bool isConst) {...} alias ArrayRange!false > Range; alias ArrayRange!true ConstRange; > > but that might be overkill. I don't know. Regardless, it _is_ > likely that the range type will have to be templatized to fix the > problem. Ranges and range- based functions in general need to be > cleaned up a bit to deal with const, since the way that they're > designed doesn't work with const very well, and we need to make it > work. I think that it _can_ work, but it takes more effort to do > so. I fully agree with all that. In order to migrate older code we may make isConst have a default value of false. Best regards, Matthias -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJP4B8OAAoJEPdcuJbq5/sR7h0H/jeJ+KPUMoiP9SqiamE0qv4V IantID2fzML8b55CWGQ2ZU7YbhQqOPIIEVtRriNAUIA4sHqWXQA03YgFrDk7XZZy jrhx9VCUkiMeIuHhSdXQIwAWH+dkfnQoOS9EwbbiwZjBG+zU5iH/s9tduRzKadTr Bb4QLAx7hEjlsvgRArj0O5z88YeGWbLhUzTz70utoE+1VgROuVF4WzJL9S803ZWX ZZR1HOx0ktE60jvBTMoK2TzSfB5/JjiDQSWjK8ikEQGSw8QR3M3DWD3WkFucOAaL 3K6xH/yoDTBMOT+IVjkfVOsnv0iBB7ARpJKxOD2r+bJOoGWCQ1YQAoyY8rwrez0= =yhaM -END PGP SIGNATURE-
Clang-based service architecture
Google by the voice of Chandler Carruth made this proposal a few days ago https://plus.google.com/u/0/108216155797501293389/posts/WDheftEoxMT It aims at building a clang daemon to parse, compile, and generate informations about source code. Basically + multithreaded, distributed compilation + coherent support of the language (C/C++/ObjC) throughout IDEs or text editors ( formatting, syntax highlight, realtime report of compilation errors/warning, maybe static analysis ) The D community already is moving toward this direction as I can see ( Roman D. Boiko's proposal or Robert Schadek "Distributed Multithreaded Caching D Compiler" ) and that's awesome news ! Also the idea of getting compiler error/warning, formatting, syntax highlight as a service looks very sweet to me. A wonderful way to unite and keep everything in sync from text editor to more powerful IDEs.
Re: DMD + msvc
On 2012-06-19 01:22, Walter Bright wrote: On 6/18/2012 11:10 AM, Adam Wilson wrote: Object generation is an unholy disaster of IFDEF's and my brain has melted every time I try to venture into it; but if we have a clean interface for interacting with them it would make it significantly easier to add things like custom sections, which in turn will open up a plethora of new options, including source embedding. Yeah, me too. But fixing that is not so easy. A start is to have a rigorous set of tests for this part of the compiler. I know the compiler has a test suite but I don't know how much of this particular code is covered. With a rigorous set of tests one will feel more comfortable in refactoring the code. Then it just some hard work that will probably take some time. The first thing would probably be to try to put everything platform specific in one place. Ideally there would only be one set of if-def's. If possible this can happen iteratively in several steps. When a function needs to be changed refactor it as well to make it more clean. Ideally we don't want to the new COFF backend to become a part of this mess. -- /Jacob Carlborg
Re: AST files instead of DI interface files for faster compilation and easier distribution
On 06/19/2012 02:47 AM, Chris Cain wrote: On Monday, 18 June 2012 at 18:05:59 UTC, Daniel wrote: Same here, I wish there were a standardized pre-lexed-token "binary" file-format, would benefit all text editors also, as they need to lex it anyway to perform color syntax highlighting. If I were to make my own language, I'd forego a human-readable format and just have the "language" be defined as a big machine-readable AST. http://de.wikipedia.org/wiki/Lisp ? You'd have to have an IDE, but it could display the code in just about any way the person wants (syntax, style, etc). This could be done even if the language's source code storage format is human-readable. Syntax highlighting would be instantaneous and there would be fewer errors made by programmers (maybe ...). Plus it'd be unbelievably easy to implement things like auto-completion. Parsing is not a huge issue. Depending on how powerful the language is, auto-completion may depend on full code analysis.
Re: AST files instead of DI interface files for faster compilation and easier distribution
On Monday, 18 June 2012 at 18:05:59 UTC, Daniel wrote: Same here, I wish there were a standardized pre-lexed-token "binary" file-format, would benefit all text editors also, as they need to lex it anyway to perform color syntax highlighting. If I were to make my own language, I'd forego a human-readable format and just have the "language" be defined as a big machine-readable AST. You'd have to have an IDE, but it could display the code in just about any way the person wants (syntax, style, etc). Syntax highlighting would be instantaneous and there would be fewer errors made by programmers (maybe ...). Plus it'd be unbelievably easy to implement things like auto-completion.
Re: DMD + msvc
Does this somewhat vague statement meant that we are getting COFF support in the near term? Yes, because that is necessary for MSVC linker compatibility. Hooray!
Re: DMD + msvc
On 6/18/2012 11:10 AM, Adam Wilson wrote: On Mon, 18 Jun 2012 10:50:44 -0700, Walter Bright wrote: On 6/17/2012 3:34 AM, Jacob Carlborg wrote: 1. DMD can only output OMF binaries 2. DMD cannot output 64bit code for Windows 3. DMD is not compatible with the MSVC linker or runtime I intend to fix all of those, at least for 64 bit Windows, in the near term. Does this somewhat vague statement meant that we are getting COFF support in the near term? Yes, because that is necessary for MSVC linker compatibility. Because if so, I have some serious plans for source embedding in custom sections. The only thing blocking it is the fact that OMF doesn't support custom sections. Once the source is embedded in libraries, we can finally jettison DI files once and for all! Also would it be possible at this point to clean up the backend such that we have a clean interface for interacting with object files during their construction, given that with COFF, all object format wills be roughly feature equal? Probably not, though it will be better. Object generation is an unholy disaster of IFDEF's and my brain has melted every time I try to venture into it; but if we have a clean interface for interacting with them it would make it significantly easier to add things like custom sections, which in turn will open up a plethora of new options, including source embedding. Yeah, me too. But fixing that is not so easy.
Re: getcwd behaves inconsistent?
On Monday, 18 June 2012 at 20:53:27 UTC, Nick Sabalausky wrote: "Kapps" wrote in message news:jikemjmapclwcufpw...@forum.dlang.org... On Sunday, 17 June 2012 at 22:39:00 UTC, Stephen Jones wrote: I recently switched from Eclipse to monoD and found that all my code to images etc was invalid because getcwd returns the directory that contains the main entry code in Eclipse, but returns the directory that contains the executable in MonoDevelop. Is there a universally consistent way of accessing files? As mentioned, it is not reliable to use the current working directory for making a relative path absolute. Right. "Current Working Directory" and "Directory of Executable" should never be confused: - The working directory should be assumed to always be different, as it's whatever directory the user just happens to be in when they run your program. - If you want to load files that are relative to the exe's path, then you need the directory of the executble. The working directory won't help at all. Note that args[0] is *not* good for this either, as that gets screwed up by symlinks and all sorts of other stuff. args[0] is unreliable. The approach I use is GetModuleFileNameA on Windows (GetModuleFileNameA(null, Buffer.ptr, MAX_PATH)) and readLinkPosix for /proc/self/exe on Linux (readLinkPosix("/proc/self/exe", Buffer.ptr, Buffer.length)). Yea, that's definitely the way to go. Here are ready-to-go functions that should handle that on Windows, Linux and OSX (untested on OSX as I don't have a working Mac, but theoretically *should* work): https://bitbucket.org/Abscissa/semitwistdtools/src/8123e04b593c/src/semitwist/util/io.d#cl-168 (Ignore the commented out function - that's just a remenant from the D1/Tango days, I should probably just delete that.) Use those functions like this: // Assuming the exe is "C:\Foo\Bar\App.exe" assert(getExec() == `C:\Foo\Bar\App.exe`); assert(getExecName() == `App.exe`); assert(getExecPath() == `C:\Foo\Bar\`); You should be able to rip those functions right out of that file and plop them into any util module you have, just make sure you also include these import lines: version(Win32) import std.c.windows.windows; else version(OSX) private extern(C) int _NSGetExecutablePath(char* buf, uint* bufsize); else import std.c.linux.linux; That was what I was after. Thanks.
Re: How to break const
On 06/18/12 23:08, deadalnix wrote: > Le 18/06/2012 09:14, Mehrdad a écrit : >> Okay, how about this? http://ideone.com/VMlzS >> >> Does this break const? >> >> >> import std.stdio; >> class S >> { >> this(int a) >> { >> this.a = a; >> this.increment = { this.a++; }; >> } >> int a; >> void delegate() increment; >> void oops() const { this.increment(); } >> } >> void main() >> { >> auto c = new const(S)(0); >> writeln(c.a); >> c.oops(); >> writeln(c.a); >> } > > Depending on how it is specified, I think you should either : > - get an error when constructing c, because S isn't « constable ». (delegate > type cannot be consted, but can be unconsted safely). > - get an error when you try to call increment in oops, because the delegate > type can't ensure the constness of the operation. > I'm afraid that: - Banning implicit mutable->const conversions would do far more harm, so this would not be a good solution to the problem. - Requiring that the type of the delegate "ensure the constness" would be far too restrictive. (the question would be: "Is any data reachable via 'this' also reachable through the delegates context pointer?" and every such delegate would of course need to be "pure" [1]. [This isn't *just* about the above example, you get the same problems when a const object isn't created but received from somewhere.] artur [1] which is a misnomer.
Re: How to break const
Le 18/06/2012 09:14, Mehrdad a écrit : Okay, how about this? http://ideone.com/VMlzS Does this break const? import std.stdio; class S { this(int a) { this.a = a; this.increment = { this.a++; }; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { auto c = new const(S)(0); writeln(c.a); c.oops(); writeln(c.a); } Depending on how it is specified, I think you should either : - get an error when constructing c, because S isn't « constable ». (delegate type cannot be consted, but can be unconsted safely). - get an error when you try to call increment in oops, because the delegate type can't ensure the constness of the operation.
Re: How to break const
Le 18/06/2012 17:29, Timon Gehr a écrit : On 06/18/2012 05:14 PM, Christophe Travert wrote: Matthias Walter , dans le message (digitalmars.D:170036), a écrit : On 06/18/2012 07:36 AM, Mehrdad wrote: Is it just me, or did I subvert the type system here? import std.stdio; struct Const { this(void delegate() increment) { this.increment = increment; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { Const c; c = Const({ c.a++; }); writeln(c.a); c.oops(); writeln(c.a); } I don't think so. When calling oops you have two references to the object c: - The this-pointer of the object itself which is not allowed to change the object in the const-call. - The reference from within main which is allowed to change it and can be reached via the frame pointer of the delegate. I see this as perfectly valid code. Of course, opinions may differ here. But here, the frame pointer of the delegate is part of the const structure. By transitivity, the frame pointer should be const, ... 'By transitivity' is not a sufficient reason. What you really mean is 'For the guarantee that a const pure method does not change its mutable parameters'. Transitivity by itself is required to solve a wide range of problem. The most obvious one is controlling what is shared and what isn't using the type system.
Re: How to break const
On Monday, 18 June 2012 at 15:24:31 UTC, Mehrdad wrote: On Monday, 18 June 2012 at 15:21:36 UTC, Timon Gehr wrote: So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... This is mostly about the design of object initialisation. good idea or no? Certainly. My initial instinct would be to require a "const constructor" in order for an object to be const-able, but I'm not sure if that would work correctly or not.. Hmmm... Reminds me of an issue that ended up coming up regarding code I was transforming to use immutable rather than mutable data. I kept coming up with the same issues. Without a const specific constructor, the immutable data I was basing the information off refused to go to a mutable temporary (since I needed it to be mutable), even if the end object was immutable and the data was untouched. I ended up with having to make a separate function that acted as a constructor, copying immutable elements and data as needed as mutable, then passing it back as immutable afterwards. A little ugly but it got the job done. I also came across an interesting problem. struct X { immutable int i_i = 10; const int c_i = 10; //same with immutable immutable int i_i2; const int c_i2; this (int n) { i_i = n; //ct error c_i = n; //ct error i_i2 = n; c_i2 = n; } } void main(){ X x = X(15); } In this case it refuses to modify i_i & c_i during the constructor, the value of i_i & c_i specify is basically a replacement default(init) and should remain mutable until the constructor is finished (Or at least allowed to set once). If I wanted a strictly unchanged value I probably would have used an enum, and not used the space. Is this a bug or intentional?
Re: getcwd behaves inconsistent?
"Kapps" wrote in message news:jikemjmapclwcufpw...@forum.dlang.org... > On Sunday, 17 June 2012 at 22:39:00 UTC, Stephen Jones wrote: >> I recently switched from Eclipse to monoD and found that all my code to >> images etc was invalid because getcwd returns the directory that contains >> the main entry code in Eclipse, but returns the directory that contains >> the executable in MonoDevelop. Is there a universally consistent way of >> accessing files? > > As mentioned, it is not reliable to use the current working directory for > making a relative path absolute. > Right. "Current Working Directory" and "Directory of Executable" should never be confused: - The working directory should be assumed to always be different, as it's whatever directory the user just happens to be in when they run your program. - If you want to load files that are relative to the exe's path, then you need the directory of the executble. The working directory won't help at all. Note that args[0] is *not* good for this either, as that gets screwed up by symlinks and all sorts of other stuff. args[0] is unreliable. > The approach I use is GetModuleFileNameA on Windows > (GetModuleFileNameA(null, Buffer.ptr, MAX_PATH)) and readLinkPosix for > /proc/self/exe on Linux (readLinkPosix("/proc/self/exe", Buffer.ptr, > Buffer.length)). Yea, that's definitely the way to go. Here are ready-to-go functions that should handle that on Windows, Linux and OSX (untested on OSX as I don't have a working Mac, but theoretically *should* work): https://bitbucket.org/Abscissa/semitwistdtools/src/8123e04b593c/src/semitwist/util/io.d#cl-168 (Ignore the commented out function - that's just a remenant from the D1/Tango days, I should probably just delete that.) Use those functions like this: // Assuming the exe is "C:\Foo\Bar\App.exe" assert(getExec() == `C:\Foo\Bar\App.exe`); assert(getExecName() == `App.exe`); assert(getExecPath() == `C:\Foo\Bar\`); You should be able to rip those functions right out of that file and plop them into any util module you have, just make sure you also include these import lines: version(Win32) import std.c.windows.windows; else version(OSX) private extern(C) int _NSGetExecutablePath(char* buf, uint* bufsize); else import std.c.linux.linux;
A currying function
I think std.functional.curry is badly named because I think it's a "partial application" (I suggest to rename it). In Haskell and Scala currying is built-in, this is Haskell, shell (ghci): Prelude> let foo x y z = x * 2 + y * 3 + y * 5 Prelude> let foo1 = foo 5 Prelude> let foo2 = foo1 4 Prelude> foo2 3 42 Through Reddit I've found a curry() in C++11: https://github.com/LeszekSwirski/cpp-curry So I've written a D version of it below, not tested much. I have not translated the C++11 version. This was quite easy to write, and much simpler and shorter than the C++11 version (but maybe this misses something, this is just a first draft). This kind of stuff was quite longer to do in D1, but now with CTFE on strings ops, defining one or more inner static functions that build a string at compile-time, it's quite easy. Now I don't need lot of templates to do this. There are two alternative designs, curry1 seems a bit more elegant, but if you want to use it in-place it forces you to add a () at the beginning, that's not nice and intuitive. So probably curry2 is better. import std.traits: isCallable, ParameterTypeTuple; import std.string: join; import std.conv: xformat; @property curry1(alias F)() if (isCallable!F) { static string genChain() { string[] chain; string[] args; foreach (i, T; ParameterTypeTuple!F) { chain ~= xformat("(%s x%d)", T.stringof, i); args ~= xformat("x%d", i); } return chain.join(" => ") ~ " => F(" ~ args.join(", ") ~ ");"; } mixin("return " ~ genChain()); } auto curry2(F)(F f) if (isCallable!F) { static string genChain() { string[] chain; string[] args; foreach (i, T; ParameterTypeTuple!F) { chain ~= xformat("(%s x%d)", T.stringof, i); args ~= xformat("x%d", i); } return chain.join(" => ") ~ " => f(" ~ args.join(", ") ~ ");"; } mixin("return " ~ genChain()); } // default arguments are ignored double foo(immutable int x, in float y, short z=5) pure nothrow { return x * 2 + y * 3 + y * 5; } void main() { import std.stdio; writeln(foo(5, 4, 3)); auto cf = curry1!foo; auto c2 = cf(5)(4); writeln(c2(3)); writeln(curry1!foo()(5)(4)(3)); writeln(curry2(&foo)(5)(4)(3)); } This is the code string generated by genChain() for the foo() function: (immutable(int) x0) => (const(float) x1) => (short x2) => f(x0, x1, x2); I think this code induces the creation of heap allocated closures, so probably a more efficient version is needed: _D4test24__T5curryTPFNaNbyixfs... L0: push EAX push EAX push EBX push 8 call near ptr __d_allocmemory mov EBX,EAX mov EAX,0Ch[ESP] mov [EBX],EAX fld float ptr 014h[ESP] mov EAX,EBX mov EDX,offset FLAT:_D4test24__T5curryTPFNaNbyixf... fstp float ptr 4[EBX] add ESP,4 pop EBX add ESP,8 ret 4 If the function is: double bar(ref int x, ref double y) pure nothrow { x++; return x * 2 + y * 3; } it generates: (int x0) => (double x1) => f(x0, x1); So this version doesn't handle ref arguments. Bye, bearophile
Re: DMD + msvc
On Monday, June 18, 2012 23:23:02 Manu wrote: > It really is. I suspect we will see a gigantic boots to the D community on > the back of this change! :) Well, we could all use a good pair of shoes. ;) - Jonathan M Davis
Re: DMD + msvc
On 18 June 2012 22:07, "@puremagic.com < "\"Michaël".Larouche"> wrote: > On Monday, 18 June 2012 at 17:51:39 UTC, Walter Bright wrote: > >> On 6/17/2012 3:34 AM, Jacob Carlborg wrote: >> >>> 1. DMD can only output OMF binaries >>> 2. DMD cannot output 64bit code for Windows >>> 3. DMD is not compatible with the MSVC linker or runtime >>> >> >> >> I intend to fix all of those, at least for 64 bit Windows, in the near >> term. >> > > This is great news ! > It really is. I suspect we will see a gigantic boots to the D community on the back of this change! :)
Re: Shared objects?
On Monday, 18 June 2012 at 15:22:19 UTC, Wouter Verhelst wrote: Ah, too bad. Do you have a pointer to some more detailed information on this? Just so I can get a feel for how fast things are moving, and/or whether it's worth for me to wait for that -- I can get started on the other parts; while the plugin architecture would be crucial eventually, it's not something I'll need from the very beginning. Thanks, Martin Nowak is working on this: https://github.com/dawgfoto/druntime/tree/SharedRuntime -- /Jacob Carlborg
Re: DMD + msvc
On Monday, 18 June 2012 at 17:51:39 UTC, Walter Bright wrote: On 6/17/2012 3:34 AM, Jacob Carlborg wrote: 1. DMD can only output OMF binaries 2. DMD cannot output 64bit code for Windows 3. DMD is not compatible with the MSVC linker or runtime I intend to fix all of those, at least for 64 bit Windows, in the near term. This is great news ! For one of my personal projects I wanted to use LLVM with D, after trying to convert the MSVC .lib to OMF format, linking with Win64GDC and MinGW LLVM (but I didn't include all LLVM libs), I gave up and I booted to my Mac partition where the object and the linker are the same for all.
Re: DMD + msvc
On Mon, 18 Jun 2012 10:50:44 -0700, Walter Bright wrote: On 6/17/2012 3:34 AM, Jacob Carlborg wrote: 1. DMD can only output OMF binaries 2. DMD cannot output 64bit code for Windows 3. DMD is not compatible with the MSVC linker or runtime I intend to fix all of those, at least for 64 bit Windows, in the near term. Does this somewhat vague statement meant that we are getting COFF support in the near term? Because if so, I have some serious plans for source embedding in custom sections. The only thing blocking it is the fact that OMF doesn't support custom sections. Once the source is embedded in libraries, we can finally jettison DI files once and for all! Also would it be possible at this point to clean up the backend such that we have a clean interface for interacting with object files during their construction, given that with COFF, all object format wills be roughly feature equal? Object generation is an unholy disaster of IFDEF's and my brain has melted every time I try to venture into it; but if we have a clean interface for interacting with them it would make it significantly easier to add things like custom sections, which in turn will open up a plethora of new options, including source embedding. -- Adam Wilson IRC: LightBender Project Coordinator The Horizon Project http://www.thehorizonproject.org/
Re: AST files instead of DI interface files for faster compilation and easier distribution
On Monday, 18 June 2012 at 17:54:40 UTC, Walter Bright wrote: On 6/18/2012 6:07 AM, Don Clugston wrote: On 17/06/12 00:37, Walter Bright wrote: On 6/14/2012 1:03 AM, Don Clugston wrote: It is for debug builds. Iain's data indicates that it's only a few % of the time taken on semantic1(). Do you have data that shows otherwise? Nothing recent, it's mostly from my C++ compiler testing. But you argued in your blog that C++ parsing is inherently slow, and you've fixed those problems in the design of D. And as far as I can tell, you were extremely successful! Parsing in D is very, very fast. Yeah, but I can't escape that lingering feeling that lexing is slow. I was fairly disappointed that asynchronously reading the source files didn't have a measurable effect most of the time. Same here, I wish there were a standardized pre-lexed-token "binary" file-format, would benefit all text editors also, as they need to lex it anyway to perform color syntax highlighting.
Re: AST files instead of DI interface files for faster compilation and easier distribution
On 6/18/2012 6:07 AM, Don Clugston wrote: On 17/06/12 00:37, Walter Bright wrote: On 6/14/2012 1:03 AM, Don Clugston wrote: It is for debug builds. Iain's data indicates that it's only a few % of the time taken on semantic1(). Do you have data that shows otherwise? Nothing recent, it's mostly from my C++ compiler testing. But you argued in your blog that C++ parsing is inherently slow, and you've fixed those problems in the design of D. And as far as I can tell, you were extremely successful! Parsing in D is very, very fast. Yeah, but I can't escape that lingering feeling that lexing is slow. I was fairly disappointed that asynchronously reading the source files didn't have a measurable effect most of the time.
Re: DMD + msvc
On 6/17/2012 3:34 AM, Jacob Carlborg wrote: 1. DMD can only output OMF binaries 2. DMD cannot output 64bit code for Windows 3. DMD is not compatible with the MSVC linker or runtime I intend to fix all of those, at least for 64 bit Windows, in the near term.
Just because it's not dmd, don't mean you have to shy away from contribution.
Just thought I might say that it's ok to send pull requests for any important/critical changes in upstream dmd, phobos and druntime down to gdc if you feel it is the correct thing to do. It has been done in the past for any showstopping bugs in the library (various multithread related issues), and also for cool new features (__vector support) - and afterall that is one of the reasons why I felt moving to github was important - if there is an issue that you can resolve yourself, then get it done! Rather than wait for the ever persistant development bottleneck that is myself to find time to get round to it. We don't bite, and only ask that anything gdc-specific is wrapped in version(GNU) so that it won't be forgotten upon the next big merge. PS: Sorry Alexrp, but I thought I might contribute my view to the community. :~) Regards Iain
Re: How to break const
On 06/18/2012 06:30 PM, Mehrdad wrote: On Monday, 18 June 2012 at 16:23:39 UTC, Timon Gehr wrote: I agree. Some of the keywords are poorly chosen, but this does not have any actual _practical_ implications for coding. Changing them, however, does. Not sure if this was intended to be referring to my post or not, but just to clarify: It was not. ;) The real problem is _not_ the fact that there is a technical issue with const/pure/immutable/whatever. Like you said, that might not have any practical consequences. The problem is that when the compiler _uses_ const/pure/immutable to make decisions regarding optimizations. It is important that the type system is sound. When that's the case, then IMHO they **MUST** be foolproof, no matter how rare/common they are (assuming no casts and such, to subvert the system). This must be the case even if the compiler does not optimize. Otherwise the compiler generates wrong binaries for correct code. Then the compiler is wrong.
Re: How to break const
On 6/18/12 10:24 AM, Mehrdad wrote: On Monday, 18 June 2012 at 15:21:36 UTC, Timon Gehr wrote: So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... This is mostly about the design of object initialisation. good idea or no? Certainly. My initial instinct would be to require a "const constructor" in order for an object to be const-able, but I'm not sure if that would work correctly or not.. The constructor of a const or immutable object progressively evolves the object from a raw state to a fixed, constructed state. During the process the object has not discernable type. This is what needs to be fixed. Andrei
Re: How to break const
On 6/18/12 10:15 AM, Mehrdad wrote: So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... good idea or no? It's the implementation (not design) of constructors typechecking that's the problem. Andrei
Re: How to break const
On Monday, 18 June 2012 at 16:23:39 UTC, Timon Gehr wrote: I agree. Some of the keywords are poorly chosen, but this does not have any actual _practical_ implications for coding. Changing them, however, does. Not sure if this was intended to be referring to my post or not, but just to clarify: The real problem is _not_ the fact that there is a technical issue with const/pure/immutable/whatever. Like you said, that might not have any practical consequences. The problem is that when the compiler _uses_ const/pure/immutable to make decisions regarding optimizations. When that's the case, then IMHO they **MUST** be foolproof, no matter how rare/common they are (assuming no casts and such, to subvert the system). Otherwise the compiler generates wrong binaries for correct code.
Re: How to break const
On 06/18/2012 06:12 PM, deadalnix wrote: Le 18/06/2012 18:04, Timon Gehr a écrit : It would be better to have 'nostatic' as the keyword for the current 'pure' and 'pure' as a shortcut for 'immutable nostatic'. This would also silence the 'pure is a misnomer' crowd. I don't really have an opinion on that subject. I understand the keywork choice can be confusing, but the overall design is really nice. I agree. Some of the keywords are poorly chosen, but this does not have any actual _practical_ implications for coding. Changing them, however, does. It is just frustrating to always be stopped mid-sentence when explaining the design to someone unfamiliar with it, or even have them lose interest because they think to have found a 'problem' with it. There is also a group of one or two guys who cannot mention 'pure' without also mentioning that they disagree with the keyword choice. Interestingly, few oppose to 'const'. This is probably because C++ has paved the way for it. TL;DR: poorly chosen keywords create needless communication overhead
Re: How to break const
Le 18/06/2012 18:04, Timon Gehr a écrit : To explain my proposal, I have to make several thing clear first. You have here 2 things to qualify : the delegate itself, and the hidden parameter. As type qualifier are transitive in D, qualify the delegate also transitively qualify the hidden parameter. The proposal was to use postfix qualifier notation to qualify the hidden parameter, and qualifier between return type and delegate keyword to qualify the delegate itself. Why would the second part of the proposal be necessary? What do you qualify as the second part ? My original proposal stated that the type qualifier before the return type qualify the return type, but this is another topic. To make is clearer, some examples : void delegate() const; // A mutable delegate that use const frame pointer (all variable accessed throw the frame pointer are made const). void const delegate(); // A const delegate that use a const frame pointer (transitivity). void const delegate() immutable; // A const delegate that use an immutable frame pointer (delegate can only access immutable data from the frame pointer). void immutable delegate() const; // Error, immutable data cannot refers to const data. Note that the implicit cast goes the other way around than usual. void delegate() const can be safely casted to void delegate(), but not the other way around, as you are allowed to not mutate mutable data, but not the other way around. Comments: 1. struct S{ int x; void foo()pure{x++;} // ok } void main(){ int x; void foo()pure{x++;} // currently an error } The second part should be allowed. It is qualifying foo as 'immutable' which should fail. Yes. 2. int y; struct S{ int x; void foo()immutable{y++;} // ok } void main(){ void foo()immutable{y++;} // should be allowed } The problem is the unfortunate annotation overhead. And yes. This is another topic, but I think the way to go is inference. It would be better to have 'nostatic' as the keyword for the current 'pure' and 'pure' as a shortcut for 'immutable nostatic'. This would also silence the 'pure is a misnomer' crowd. I don't really have an opinion on that subject. I understand the keywork choice can be confusing, but the overall design is really nice.
Re: How to break const
On 06/18/2012 05:12 PM, deadalnix wrote: Le 18/06/2012 16:51, Andrei Alexandrescu a écrit : Mehrdad posted a code sample and you replied to it with what I could only assume was an explanation of the code's behavior. I hope you'd agree it was a reasonable assumption, whether or not it was correct. The problem at work here is that "this" is typed incorrectly during the construction of a qualified object. It should go progressively from a "raw" to a "cooked" state, and cannot be passed to any function while raw. I've however made other posts to explain why transitivity is broken when it comes to delegate. I looked at your posts through June and couldn't find such, so a couple of links would be great. Of course, bug reports would be even better! I'm not sure you are talking about the proposal or the transitivity issue here. I'll explain the proposal below, for the explaination of why the transitivity is broken, see : http://forum.dlang.org/thread/ywispsasaylqscyua...@forum.dlang.org?page=2#post-jrn7sv:24jjj:241:40digitalmars.com To explain my proposal, I have to make several thing clear first. You have here 2 things to qualify : the delegate itself, and the hidden parameter. As type qualifier are transitive in D, qualify the delegate also transitively qualify the hidden parameter. The proposal was to use postfix qualifier notation to qualify the hidden parameter, and qualifier between return type and delegate keyword to qualify the delegate itself. Why would the second part of the proposal be necessary? My original proposal stated that the type qualifier before the return type qualify the return type, but this is another topic. To make is clearer, some examples : void delegate() const; // A mutable delegate that use const frame pointer (all variable accessed throw the frame pointer are made const). void const delegate(); // A const delegate that use a const frame pointer (transitivity). void const delegate() immutable; // A const delegate that use an immutable frame pointer (delegate can only access immutable data from the frame pointer). void immutable delegate() const; // Error, immutable data cannot refers to const data. Note that the implicit cast goes the other way around than usual. void delegate() const can be safely casted to void delegate(), but not the other way around, as you are allowed to not mutate mutable data, but not the other way around. Comments: 1. struct S{ int x; void foo()pure{x++;} // ok } void main(){ int x; void foo()pure{x++;} // currently an error } The second part should be allowed. It is qualifying foo as 'immutable' which should fail. 2. int y; struct S{ int x; void foo()immutable{y++;} // ok } void main(){ void foo()immutable{y++;} // should be allowed } The problem is the unfortunate annotation overhead. It would be better to have 'nostatic' as the keyword for the current 'pure' and 'pure' as a shortcut for 'immutable nostatic'. This would also silence the 'pure is a misnomer' crowd.
Re: How to break const
Le 18/06/2012 17:50, Timon Gehr a écrit : On 06/18/2012 05:28 PM, Mehrdad wrote: On Monday, 18 June 2012 at 15:24:31 UTC, Mehrdad wrote: On Monday, 18 June 2012 at 15:21:36 UTC, Timon Gehr wrote: So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... This is mostly about the design of object initialisation. good idea or no? Certainly. My initial instinct would be to require a "const constructor" in order for an object to be const-able, but I'm not sure if that would work correctly or not.. Come to think of it, that would play REALLY nicely with 'scope' -- a reference to a non-const object can be escaped from a 'const constructor' if and only if the reference is scope! Bingo! Does that work?? Yes, but it requires proper enforcement of 'scope'. - which is undecidable/must be done conservatively - code would have to become 'scope correct' Come on, what can't we infers qualifiers ?
Re: How to break const
On 06/18/2012 05:28 PM, Mehrdad wrote: On Monday, 18 June 2012 at 15:24:31 UTC, Mehrdad wrote: On Monday, 18 June 2012 at 15:21:36 UTC, Timon Gehr wrote: So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... This is mostly about the design of object initialisation. good idea or no? Certainly. My initial instinct would be to require a "const constructor" in order for an object to be const-able, but I'm not sure if that would work correctly or not.. Come to think of it, that would play REALLY nicely with 'scope' -- a reference to a non-const object can be escaped from a 'const constructor' if and only if the reference is scope! Bingo! Does that work?? Yes, but it requires proper enforcement of 'scope'. - which is undecidable/must be done conservatively - code would have to become 'scope correct'
Re: How to break const
On Monday, 18 June 2012 at 15:36:23 UTC, deadalnix wrote: Le 18/06/2012 17:28, Mehrdad a écrit : On Monday, 18 June 2012 at 15:24:31 UTC, Mehrdad wrote: On Monday, 18 June 2012 at 15:21:36 UTC, Timon Gehr wrote: So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... This is mostly about the design of object initialisation. good idea or no? Certainly. My initial instinct would be to require a "const constructor" in order for an object to be const-able, but I'm not sure if that would work correctly or not.. Come to think of it, that would play REALLY nicely with 'scope' -- a reference to a non-const object can be escaped from a 'const constructor' if and only if the reference is scope! Bingo! Does that work?? Indeed, this should be scope for ctor (avoid partially initialized object in 3rd party code) /dtor (avoid resurrection, which is a real pain for any GC, and a very good way to ends up with alive object in invalid state). note: "for a CONST ctor", not just any ctor
Re: How to break const
Le 18/06/2012 17:28, Mehrdad a écrit : On Monday, 18 June 2012 at 15:24:31 UTC, Mehrdad wrote: On Monday, 18 June 2012 at 15:21:36 UTC, Timon Gehr wrote: So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... This is mostly about the design of object initialisation. good idea or no? Certainly. My initial instinct would be to require a "const constructor" in order for an object to be const-able, but I'm not sure if that would work correctly or not.. Come to think of it, that would play REALLY nicely with 'scope' -- a reference to a non-const object can be escaped from a 'const constructor' if and only if the reference is scope! Bingo! Does that work?? Indeed, this should be scope for ctor (avoid partially initialized object in 3rd party code) /dtor (avoid resurrection, which is a real pain for any GC, and a very good way to ends up with alive object in invalid state).
Re: How to break const
Le 18/06/2012 17:23, Timon Gehr a écrit : On 06/18/2012 05:13 PM, deadalnix wrote: Le 18/06/2012 16:55, Mehrdad a écrit : On Monday, 18 June 2012 at 14:48:37 UTC, deadalnix wrote: Le 18/06/2012 16:44, Mehrdad a écrit : Interesting, making the delegate `pure' doesn't change anything either. So 'pure' doesn't let you "infer something just by looking at the code either", right? It does ! It tell you that the function have no side effect, and that the function called with identical arguments will return identical results. pure will not ensure constness or immutability. const and immutable are made for that. The fact that D decouple purity and immutability is a very nice design decision and is explained nicely here : http://klickverbot.at/blog/2012/05/purity-in-d/ Identical calls giving identical results? What? import std.stdio; struct S { this(int a) { this.a = a; this.increment = { return this.a++; }; } int a; int delegate() pure increment; auto oops() const { return this.increment(); } } void main() { auto c = immutable(S)(0); writeln(c.oops()); // 0 writeln(c.oops()); // 1 writeln(c.oops()); // 2 writeln(c.oops()); // 3 writeln(c.oops()); // 4 writeln(c.oops()); // 5 } They are not call with the same parameters. The hidden parameter have changed (I know this is tricky). The whole problem is that the hidden parameter has changed. It is immutable! As said, this is effectively a const/immutable issue. Not a purity issue. I'm not claiming that this code is fine, just explaining that the code is fine in regard to purity.
Re: How to break const
On 06/18/2012 05:14 PM, Christophe Travert wrote: Matthias Walter , dans le message (digitalmars.D:170036), a écrit : On 06/18/2012 07:36 AM, Mehrdad wrote: Is it just me, or did I subvert the type system here? import std.stdio; struct Const { this(void delegate() increment) { this.increment = increment; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { Const c; c = Const({ c.a++; }); writeln(c.a); c.oops(); writeln(c.a); } I don't think so. When calling oops you have two references to the object c: - The this-pointer of the object itself which is not allowed to change the object in the const-call. - The reference from within main which is allowed to change it and can be reached via the frame pointer of the delegate. I see this as perfectly valid code. Of course, opinions may differ here. But here, the frame pointer of the delegate is part of the const structure. By transitivity, the frame pointer should be const, ... 'By transitivity' is not a sufficient reason. What you really mean is 'For the guarantee that a const pure method does not change its mutable parameters'.
Re: How to break const
On Monday, 18 June 2012 at 15:24:31 UTC, Mehrdad wrote: On Monday, 18 June 2012 at 15:21:36 UTC, Timon Gehr wrote: So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... This is mostly about the design of object initialisation. good idea or no? Certainly. My initial instinct would be to require a "const constructor" in order for an object to be const-able, but I'm not sure if that would work correctly or not.. Come to think of it, that would play REALLY nicely with 'scope' -- a reference to a non-const object can be escaped from a 'const constructor' if and only if the reference is scope! Bingo! Does that work??
Re: How to break const
On 06/18/2012 05:13 PM, deadalnix wrote: Le 18/06/2012 16:55, Mehrdad a écrit : On Monday, 18 June 2012 at 14:48:37 UTC, deadalnix wrote: Le 18/06/2012 16:44, Mehrdad a écrit : Interesting, making the delegate `pure' doesn't change anything either. So 'pure' doesn't let you "infer something just by looking at the code either", right? It does ! It tell you that the function have no side effect, and that the function called with identical arguments will return identical results. pure will not ensure constness or immutability. const and immutable are made for that. The fact that D decouple purity and immutability is a very nice design decision and is explained nicely here : http://klickverbot.at/blog/2012/05/purity-in-d/ Identical calls giving identical results? What? import std.stdio; struct S { this(int a) { this.a = a; this.increment = { return this.a++; }; } int a; int delegate() pure increment; auto oops() const { return this.increment(); } } void main() { auto c = immutable(S)(0); writeln(c.oops()); // 0 writeln(c.oops()); // 1 writeln(c.oops()); // 2 writeln(c.oops()); // 3 writeln(c.oops()); // 4 writeln(c.oops()); // 5 } They are not call with the same parameters. The hidden parameter have changed (I know this is tricky). The whole problem is that the hidden parameter has changed. It is immutable!
Re: How to break const
On Monday, 18 June 2012 at 15:21:36 UTC, Timon Gehr wrote: So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... This is mostly about the design of object initialisation. good idea or no? Certainly. My initial instinct would be to require a "const constructor" in order for an object to be const-able, but I'm not sure if that would work correctly or not..
Re: How to break const
Le 18/06/2012 17:20, Mehrdad a écrit : On Monday, 18 June 2012 at 15:19:26 UTC, deadalnix wrote: Yes, but this isn't a problem with pure here, this is a problem with const. Hence the title... The sample code should not compile. What should the error be? Is it correct in the language spec? The specification lack on that point, because we are here facing a specification bug. Depending on how we choose to fix that, the error can be different. Fix the initializer to dissalow the way you initialize c is probably the way to go on that specific case. Andrei says that work have been done in that direction, but I'm not aware of where it is now. It also require a way to qualify the frame pointer; which isn't possible ATM.
Re: How to break const
On 06/18/2012 05:15 PM, Mehrdad wrote: On Monday, 18 June 2012 at 15:11:00 UTC, Timon Gehr wrote: On 06/18/2012 04:55 PM, Mehrdad wrote: Identical calls giving identical results? What? import std.stdio; struct S { this(int a) { this.a = a; this.increment = { return this.a++; }; } int a; int delegate() pure increment; auto oops() const { return this.increment(); } } void main() { auto c = immutable(S)(0); writeln(c.oops()); // 0 writeln(c.oops()); // 1 writeln(c.oops()); // 2 writeln(c.oops()); // 3 writeln(c.oops()); // 4 writeln(c.oops()); // 5 } Now you have managed to break the type system. The underlying issue is unrelated to delegates though. Yeah, I didn't mean to say it's a delegate issue either. That's why the title was saying "how to break _const_". Delegates were just a means to an end. :) So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... This is mostly about the design of object initialisation. good idea or no? Certainly.
Re: How to break const
On Monday, 18 June 2012 at 15:19:26 UTC, deadalnix wrote: Yes, but this isn't a problem with pure here, this is a problem with const. Hence the title... The sample code should not compile. What should the error be? Is it correct in the language spec?
Re: How to break const
On Monday, 18 June 2012 at 15:16:58 UTC, Mehrdad wrote: Explain it however you want. The bottom line I'm getting at is, you can't re-order the calls, EVEN IF by "looking at them" you can tell they're pure @safe nothrow const... (Sorry wasn't intending to make a mean comment -- my bad if it came across that way.) And not just re-ordering for that matter. I can't see /any/ optimizations happening even though these are const/pure/@safe/nothrow/whatever...
Re: D in your browser? possible?
On Monday, 18 June 2012 at 14:59:53 UTC, Timon Gehr wrote: On 06/18/2012 03:47 PM, nazriel wrote: On Sunday, 17 June 2012 at 16:38:25 UTC, Damian wrote: I've noticed a few languages are adopting this, for example Haskell: http://tryhaskell.org Go: http://play.golang.org Will D get something like this? I find it to be of great use with Go specifically and I'm sure it would benefit D just as much. Hey. We are working on something like that. http://dpaste.dzfl.pl/ At the end we want also to share an API to allow users to use service on their own like in the GO Lang website etc, where you can click Try it now (actually its already done via "Compile" button, where request is sent via AJAX). (Warning: Compiler section is actually dummy-filled, at the moment only dmd2.059 is avaible). Very nice. Why do you use radio buttons in the 'Libraries' section though? Those are not mutually exclusive. The thing is, we want also provide support for D1, where Tango excludes Phobos and vice-versa. I am not sure yet how we should handle it, maybe some JS-magic, which would replace checkbox for radiobox when using D1, or just ignoring 2nd choice when using D1. This is cosmetic change though, can be done anytime (backend supports both libraries in same time)
Re: Shared objects?
Jacob Carlborg writes: > On 2012-06-18 16:56, Wouter Verhelst wrote: >> However, what >> I don't find is the answer to the two following questions: >> >> - Does D support dlopen(), or some similar mechanism, to allow me to >>load plugins at runtime? > > Yes. You can compile D code to a standard dynamic library, just as you > would using C. Cool. >> - If it does, does Object.factory() still work for new classes loaded in >>through dlopen() (or its functional equivalence)? > > No. > > Dynamic libraries are currently not working properly in D. The runtime > needs to be updated to handle it. There are some problem with module > info, exception handling tables and TLS. There might be some problem > left with PIC as well. > > This is worked on and hopefully we will have a solution not too far in > the future. Ah, too bad. Do you have a pointer to some more detailed information on this? Just so I can get a feel for how fast things are moving, and/or whether it's worth for me to wait for that -- I can get started on the other parts; while the plugin architecture would be crucial eventually, it's not something I'll need from the very beginning. Thanks, -- The volume of a pizza of thickness a and radius z can be described by the following formula: pi zz a
Re: How to break const
Le 18/06/2012 17:16, Mehrdad a écrit : On Monday, 18 June 2012 at 15:13:33 UTC, deadalnix wrote: Identical calls giving identical results? What? import std.stdio; struct S { this(int a) { this.a = a; this.increment = { return this.a++; }; } int a; int delegate() pure increment; auto oops() const { return this.increment(); } } void main() { auto c = immutable(S)(0); writeln(c.oops()); // 0 writeln(c.oops()); // 1 writeln(c.oops()); // 2 writeln(c.oops()); // 3 writeln(c.oops()); // 4 writeln(c.oops()); // 5 } They are not call with the same parameters. The hidden parameter have changed (I know this is tricky). Explain it however you want. The bottom line I'm getting at is, you can't re-order the calls, EVEN IF by "looking at them" you can tell they're pure @safe nothrow const... Yes, but this isn't a problem with pure here, this is a problem with const. The sample code should not compile.
Re: How to break const
On Monday, 18 June 2012 at 15:13:33 UTC, deadalnix wrote: Identical calls giving identical results? What? import std.stdio; struct S { this(int a) { this.a = a; this.increment = { return this.a++; }; } int a; int delegate() pure increment; auto oops() const { return this.increment(); } } void main() { auto c = immutable(S)(0); writeln(c.oops()); // 0 writeln(c.oops()); // 1 writeln(c.oops()); // 2 writeln(c.oops()); // 3 writeln(c.oops()); // 4 writeln(c.oops()); // 5 } They are not call with the same parameters. The hidden parameter have changed (I know this is tricky). Explain it however you want. The bottom line I'm getting at is, you can't re-order the calls, EVEN IF by "looking at them" you can tell they're pure @safe nothrow const...
Re: How to break const
Le 18/06/2012 16:55, Mehrdad a écrit : On Monday, 18 June 2012 at 14:48:37 UTC, deadalnix wrote: Le 18/06/2012 16:44, Mehrdad a écrit : Interesting, making the delegate `pure' doesn't change anything either. So 'pure' doesn't let you "infer something just by looking at the code either", right? It does ! It tell you that the function have no side effect, and that the function called with identical arguments will return identical results. pure will not ensure constness or immutability. const and immutable are made for that. The fact that D decouple purity and immutability is a very nice design decision and is explained nicely here : http://klickverbot.at/blog/2012/05/purity-in-d/ Identical calls giving identical results? What? import std.stdio; struct S { this(int a) { this.a = a; this.increment = { return this.a++; }; } int a; int delegate() pure increment; auto oops() const { return this.increment(); } } void main() { auto c = immutable(S)(0); writeln(c.oops()); // 0 writeln(c.oops()); // 1 writeln(c.oops()); // 2 writeln(c.oops()); // 3 writeln(c.oops()); // 4 writeln(c.oops()); // 5 } They are not call with the same parameters. The hidden parameter have changed (I know this is tricky).
Re: How to break const
On Monday, 18 June 2012 at 15:11:00 UTC, Timon Gehr wrote: On 06/18/2012 04:55 PM, Mehrdad wrote: Identical calls giving identical results? What? import std.stdio; struct S { this(int a) { this.a = a; this.increment = { return this.a++; }; } int a; int delegate() pure increment; auto oops() const { return this.increment(); } } void main() { auto c = immutable(S)(0); writeln(c.oops()); // 0 writeln(c.oops()); // 1 writeln(c.oops()); // 2 writeln(c.oops()); // 3 writeln(c.oops()); // 4 writeln(c.oops()); // 5 } Now you have managed to break the type system. The underlying issue is unrelated to delegates though. Yeah, I didn't mean to say it's a delegate issue either. That's why the title was saying "how to break _const_". Delegates were just a means to an end. :) So (**IMHO**) if that's really the case, we should really spend some time fixing the /design/ of const before the implementation... good idea or no?
Re: How to break const
Matthias Walter , dans le message (digitalmars.D:170036), a écrit : > On 06/18/2012 07:36 AM, Mehrdad wrote: >> Is it just me, or did I subvert the type system here? >> >> >> import std.stdio; >> >> struct Const >> { >> this(void delegate() increment) >> { this.increment = increment; } >> int a; >> void delegate() increment; >> void oops() const { this.increment(); } >> } >> >> void main() >> { >> Const c; >> c = Const({ c.a++; }); >> writeln(c.a); >> c.oops(); >> writeln(c.a); >> } >> > > I don't think so. When calling oops you have two references to the object c: > > - The this-pointer of the object itself which is not allowed to change > the object in the const-call. > - The reference from within main which is allowed to change it and can > be reached via the frame pointer of the delegate. > > I see this as perfectly valid code. Of course, opinions may differ here. But here, the frame pointer of the delegate is part of the const structure. By transitivity, the frame pointer should be const, and therefore, calling the delegate (which modifies the frame pointer) should not be legal. To be callable from a const method (oops), the member delegate (increment) should be of type "void delegate() const". This type exists, but is not easy to get[1]. Because constness of frame pointers is not implemented as it should be[2], there is a hole in the const system. [1] AFAIK, it can only be got by making an explicit delegate like &struct.const_method [2] Just like pure and no_throw attributes are complicated to work with delegates, the const attribute would be a mess to use at the moment. -- Christophe
Re: How to break const
On 06/18/2012 04:33 PM, deadalnix wrote: Le 18/06/2012 15:03, Timon Gehr a écrit : On 06/18/2012 02:45 PM, deadalnix wrote: Le 18/06/2012 07:59, Matthias Walter a écrit : On 06/18/2012 07:36 AM, Mehrdad wrote: Is it just me, or did I subvert the type system here? import std.stdio; struct Const { this(void delegate() increment) { this.increment = increment; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { Const c; c = Const({ c.a++; }); writeln(c.a); c.oops(); writeln(c.a); } I don't think so. When calling oops you have two references to the object c: - The this-pointer of the object itself which is not allowed to change the object in the const-call. - The reference from within main which is allowed to change it and can be reached via the frame pointer of the delegate. I see this as perfectly valid code. Of course, opinions may differ here. Matthias The hidden parameter of the delegate is stored in c. This hidden parameter must be qualified with const when c is made const, for transitivity. However, it isn't. In short : - c is made const - the frame pointer is stored in c - the frame pointer must be made const for transitivity. => The type system is broken. You'll find many examples of this behavior with delegates. The type system is not broken. You cannot modify an immutable object using this behaviour. Delegates are type checked once and for all when they are declared. Transitive const does not necessarily need to apply to their context pointers. I think it is useful to reason about delegates at a higher abstraction level than function pointer and context pointer. You cannot use this to modify immutable data, granted. But you can use that to break transitivity (ie, make immutable data refers mutable datas). It have many hidden traps. For instance, data that isn't shared or immutable can be shared anyway between thread throw delegates. Not being able to ensure transitivity with delegate break all benefit of transitivity. However, delegate is a special beast, because it cannot be safely « constified », but can be safely « unconstified ». The issue is that immutable objects can contain impure delegates as fields. This should probably be banned.
Re: DMD + msvc
On 18 June 2012 16:08, Manu wrote: > On 18 June 2012 11:38, Kagamin wrote: >> >> On Sunday, 17 June 2012 at 10:49:30 UTC, Gor Gyolchanyan wrote: >>> >>> Thanks for the reply. >>> This is so ridiculous and frustrating. >> >> >> Use GDC? > > > I use GDC now. It produces COFF objects, and is technically capable of > linking against MSVC code, except the 2 compilers expect different runtimes. > You have to be REALLY careful with your GDC code to make sure it doesn't > produce implicit calls into the GNU runtime, otherwise you'll get link > conflicts. > You can afford some really standard runtime calls that are also present in > the mscrt, and it'll just link to those instead of the gnu ones. > > I have successfully build small scale projects with GDC linking against MSVC > code, but there's a long list of problems and gotchas... > My current approach is to build D code into DLL's and dynamically link > against my MSVC code, or vice-versa. > > Hopefully the new 64bit dmd comes soon :) DMD would be linking against it's own runtime on windows too, rather than msvc runtime, iirc. So you may have similar problems there too. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
Re: How to break const
Le 18/06/2012 16:51, Andrei Alexandrescu a écrit : Mehrdad posted a code sample and you replied to it with what I could only assume was an explanation of the code's behavior. I hope you'd agree it was a reasonable assumption, whether or not it was correct. The problem at work here is that "this" is typed incorrectly during the construction of a qualified object. It should go progressively from a "raw" to a "cooked" state, and cannot be passed to any function while raw. I've however made other posts to explain why transitivity is broken when it comes to delegate. I looked at your posts through June and couldn't find such, so a couple of links would be great. Of course, bug reports would be even better! I'm not sure you are talking about the proposal or the transitivity issue here. I'll explain the proposal below, for the explaination of why the transitivity is broken, see : http://forum.dlang.org/thread/ywispsasaylqscyua...@forum.dlang.org?page=2#post-jrn7sv:24jjj:241:40digitalmars.com To explain my proposal, I have to make several thing clear first. You have here 2 things to qualify : the delegate itself, and the hidden parameter. As type qualifier are transitive in D, qualify the delegate also transitively qualify the hidden parameter. The proposal was to use postfix qualifier notation to qualify the hidden parameter, and qualifier between return type and delegate keyword to qualify the delegate itself. My original proposal stated that the type qualifier before the return type qualify the return type, but this is another topic. To make is clearer, some examples : void delegate() const; // A mutable delegate that use const frame pointer (all variable accessed throw the frame pointer are made const). void const delegate(); // A const delegate that use a const frame pointer (transitivity). void const delegate() immutable; // A const delegate that use an immutable frame pointer (delegate can only access immutable data from the frame pointer). void immutable delegate() const; // Error, immutable data cannot refers to const data. Note that the implicit cast goes the other way around than usual. void delegate() const can be safely casted to void delegate(), but not the other way around, as you are allowed to not mutate mutable data, but not the other way around.
Re: How to break const
On 06/18/2012 04:55 PM, Mehrdad wrote: Identical calls giving identical results? What? import std.stdio; struct S { this(int a) { this.a = a; this.increment = { return this.a++; }; } int a; int delegate() pure increment; auto oops() const { return this.increment(); } } void main() { auto c = immutable(S)(0); writeln(c.oops()); // 0 writeln(c.oops()); // 1 writeln(c.oops()); // 2 writeln(c.oops()); // 3 writeln(c.oops()); // 4 writeln(c.oops()); // 5 } Now you have managed to break the type system. The underlying issue is unrelated to delegates though.
Re: D in your browser? possible?
On 17 June 2012 19:38, Damian wrote: > I've noticed a few languages are adopting this, for example > Haskell: http://tryhaskell.org > Go: http://play.golang.org > > Will D get something like this? I find it to be of great use > with Go specifically and I'm sure it would benefit D just as much. > A friend of mine started this: https://bitbucket.org/fearog/gdc-nacl Chrome NaCl (http://en.wikipedia.org/wiki/Google_Native_Client) target for GDC, to run realtime client-side D code in your browser! Yeah! I'm sure he could use some help ;)
Re: DMD + msvc
On 18 June 2012 11:38, Kagamin wrote: > On Sunday, 17 June 2012 at 10:49:30 UTC, Gor Gyolchanyan wrote: > >> Thanks for the reply. >> This is so ridiculous and frustrating. >> > > Use GDC? > I use GDC now. It produces COFF objects, and is technically capable of linking against MSVC code, except the 2 compilers expect different runtimes. You have to be REALLY careful with your GDC code to make sure it doesn't produce implicit calls into the GNU runtime, otherwise you'll get link conflicts. You can afford some really standard runtime calls that are also present in the mscrt, and it'll just link to those instead of the gnu ones. I have successfully build small scale projects with GDC linking against MSVC code, but there's a long list of problems and gotchas... My current approach is to build D code into DLL's and dynamically link against my MSVC code, or vice-versa. Hopefully the new 64bit dmd comes soon :)
Re: Shared objects?
On 2012-06-18 16:56, Wouter Verhelst wrote: Hi group, I've been reading up on D for the past few days--something I'd been planning to do for quite a while--and find much to like and little to dislike; as such, I am considering using it for my next project, which would run on Linux (and possibly some other POSIX systems) and would need to load plugins. Now I've done such things in C in the past, and it's not too difficult: you create a .so file, have it call some initial function right after the dlopen(), and then have that initial function register the new functionality available. After looking at the documentation for a few days, I've come to the conclusion that with Object.factory and interfaces, I believe I can abstract things enough so that all a plugin would need to do is register a new class, which could then be instantiated if needs be. Yes, in theory. However, what I don't find is the answer to the two following questions: - Does D support dlopen(), or some similar mechanism, to allow me to load plugins at runtime? Yes. You can compile D code to a standard dynamic library, just as you would using C. - If it does, does Object.factory() still work for new classes loaded in through dlopen() (or its functional equivalence)? No. Dynamic libraries are currently not working properly in D. The runtime needs to be updated to handle it. There are some problem with module info, exception handling tables and TLS. There might be some problem left with PIC as well. This is worked on and hopefully we will have a solution not too far in the future. -- /Jacob Carlborg
Re: D in your browser? possible?
On 06/18/2012 03:47 PM, nazriel wrote: On Sunday, 17 June 2012 at 16:38:25 UTC, Damian wrote: I've noticed a few languages are adopting this, for example Haskell: http://tryhaskell.org Go: http://play.golang.org Will D get something like this? I find it to be of great use with Go specifically and I'm sure it would benefit D just as much. Hey. We are working on something like that. http://dpaste.dzfl.pl/ At the end we want also to share an API to allow users to use service on their own like in the GO Lang website etc, where you can click Try it now (actually its already done via "Compile" button, where request is sent via AJAX). (Warning: Compiler section is actually dummy-filled, at the moment only dmd2.059 is avaible). Very nice. Why do you use radio buttons in the 'Libraries' section though? Those are not mutually exclusive.
Re: DMD + msvc
On 17 June 2012 13:49, Gor Gyolchanyan wrote: > On Sun, Jun 17, 2012 at 2:34 PM, Jacob Carlborg wrote: > > On 2012-06-17 07:15, Gor Gyolchanyan wrote: > >> > >> Is it possible to use the VC2010 linker with DMD? That would allow > >> easily linking with COFF libraries and building 64 bit binaries. > > > > > > No. > > > > 1. DMD can only output OMF binaries > > 2. DMD cannot output 64bit code for Windows > > 3. DMD is not compatible with the MSVC linker or runtime > > > > -- > > /Jacob Carlborg > > Thanks for the reply. > This is so ridiculous and frustrating. > I've been bugging Walter for this for months, and the word on the street is that he's working on it now :) Intention is to support the MS linker and runtimes (which is what I need too).
Re: How to break const
On Monday, 18 June 2012 at 14:55:42 UTC, Mehrdad wrote: Identical calls giving identical results? What? import std.stdio; struct S { this(int a) { this.a = a; this.increment = { return this.a++; }; } int a; int delegate() pure increment; auto oops() const { return this.increment(); } } void main() { auto c = immutable(S)(0); writeln(c.oops()); // 0 writeln(c.oops()); // 1 writeln(c.oops()); // 2 writeln(c.oops()); // 3 writeln(c.oops()); // 4 writeln(c.oops()); // 5 } Heck, make that all @safe pure nothrow: int delegate() pure @safe nothrow increment; auto oops() pure const @safe nothrow { return this.increment(); }
Shared objects?
Hi group, I've been reading up on D for the past few days--something I'd been planning to do for quite a while--and find much to like and little to dislike; as such, I am considering using it for my next project, which would run on Linux (and possibly some other POSIX systems) and would need to load plugins. Now I've done such things in C in the past, and it's not too difficult: you create a .so file, have it call some initial function right after the dlopen(), and then have that initial function register the new functionality available. After looking at the documentation for a few days, I've come to the conclusion that with Object.factory and interfaces, I believe I can abstract things enough so that all a plugin would need to do is register a new class, which could then be instantiated if needs be. However, what I don't find is the answer to the two following questions: - Does D support dlopen(), or some similar mechanism, to allow me to load plugins at runtime? - If it does, does Object.factory() still work for new classes loaded in through dlopen() (or its functional equivalence)? Thanks, -- The volume of a pizza of thickness a and radius z can be described by the following formula: pi zz a
Re: How to break const
On 06/18/12 16:41, deadalnix wrote: > Le 18/06/2012 16:28, Artur Skawina a écrit : >> It's fine, if you view a delegate as opaque. >> > > No it isn't. You cannot ensure transitivity anywhere. This have obvious, and > severe drawback for concurrent programing (implicit sharing is back) and GC > performances (GC can eb crazy fast when it come to transitive immutable data, > see OCaml's GC performances for instance). > >> 'this' being const does not preclude accessing the object that 'this' >> points to via another, mutable, reference. >> >> Consider the alternative - you'd have to forbid storing any delegate >> with a non-const non-value argument inside any object. So how would you like to handle this? And, no, allowing only the cases that /can/ be statically checked is not ok - it would result in black magic - delegates would be accepted or not depending on the contents of the object (think templates and composition). >> And "breaking" const would then _still_ be possible and trivial. >> > > No, and your example don't demonstrate that in any way. Transitivity is > maintained in the example below, because g isn't a member of s, and if it > were, then the example would break at compile time. The word "breaking" is in quotes for a reason. Const is not an immutability guarantee. If you treat delegates as opaque then there's no practical difference between using them or accessing the data via another external reference. > purity is another beast altogether. D's "weak pure" can help; I just don't like the redefinition of the term "purity"; another name for "weak purity" would be better. artur
Re: How to break const
On Monday, 18 June 2012 at 14:48:37 UTC, deadalnix wrote: Le 18/06/2012 16:44, Mehrdad a écrit : Interesting, making the delegate `pure' doesn't change anything either. So 'pure' doesn't let you "infer something just by looking at the code either", right? It does ! It tell you that the function have no side effect, and that the function called with identical arguments will return identical results. pure will not ensure constness or immutability. const and immutable are made for that. The fact that D decouple purity and immutability is a very nice design decision and is explained nicely here : http://klickverbot.at/blog/2012/05/purity-in-d/ Identical calls giving identical results? What? import std.stdio; struct S { this(int a) { this.a = a; this.increment = { return this.a++; }; } int a; int delegate() pure increment; auto oops() const { return this.increment(); } } void main() { auto c = immutable(S)(0); writeln(c.oops()); // 0 writeln(c.oops()); // 1 writeln(c.oops()); // 2 writeln(c.oops()); // 3 writeln(c.oops()); // 4 writeln(c.oops()); // 5 }
Re: How to break const
On 6/18/12 9:45 AM, deadalnix wrote: Le 18/06/2012 16:43, Andrei Alexandrescu a écrit : On 6/18/12 7:43 AM, deadalnix wrote: Le 18/06/2012 07:36, Mehrdad a écrit : Is it just me, or did I subvert the type system here? delegate fail to ensure transitivity of type qualifier. This is no news. This is however a big error. I proposed a fix to that by changing the semantic of the type qualifier depending on its position in the declaration, but didn't received much feedback at the time. I don't think that's the correct explanation. Andrei I fail to understand what you mean here. This post ins't supposed to explain anything. Mehrdad posted a code sample and you replied to it with what I could only assume was an explanation of the code's behavior. I hope you'd agree it was a reasonable assumption, whether or not it was correct. The problem at work here is that "this" is typed incorrectly during the construction of a qualified object. It should go progressively from a "raw" to a "cooked" state, and cannot be passed to any function while raw. I've however made other posts to explain why transitivity is broken when it comes to delegate. I looked at your posts through June and couldn't find such, so a couple of links would be great. Of course, bug reports would be even better! Andrei
Re: How to break const
Le 18/06/2012 16:44, Mehrdad a écrit : Interesting, making the delegate `pure' doesn't change anything either. So 'pure' doesn't let you "infer something just by looking at the code either", right? It does ! It tell you that the function have no side effect, and that the function called with identical arguments will return identical results. pure will not ensure constness or immutability. const and immutable are made for that. The fact that D decouple purity and immutability is a very nice design decision and is explained nicely here : http://klickverbot.at/blog/2012/05/purity-in-d/
Re: How to break const
On Monday, 18 June 2012 at 14:41:02 UTC, deadalnix wrote: Le 18/06/2012 16:28, Artur Skawina a écrit : It's fine, if you view a delegate as opaque. No it isn't. You cannot ensure transitivity anywhere. This have obvious, and severe drawback for concurrent programing (implicit sharing is back) and GC performances (GC can eb crazy fast when it come to transitive immutable data, see OCaml's GC performances for instance). 'this' being const does not preclude accessing the object that 'this' points to via another, mutable, reference. Consider the alternative - you'd have to forbid storing any delegate with a non-const non-value argument inside any object. And "breaking" const would then _still_ be possible and trivial. No, and your example don't demonstrate that in any way. Transitivity is maintained in the example below, because g isn't a member of s, and if it were, then the example would break at compile time. import std.stdio; S*[const(S)*] g; struct S { int i; this(int i) { this.i = i; g[&this] =&this; } void f() const { g[&this].i=666; } } void main() { const s = S(42); writeln(s); s.f(); writeln(s); } Yes, D's "pure" could help here, only it's misnamed (even if in this particular case that term would be fitting). purity is another beast altogether. Interesting, making the delegate `pure' doesn't change anything either. So 'pure' doesn't let you "infer something just by looking at the code either", right?
Re: How to break const
On 6/18/12 7:43 AM, deadalnix wrote: Le 18/06/2012 07:36, Mehrdad a écrit : Is it just me, or did I subvert the type system here? delegate fail to ensure transitivity of type qualifier. This is no news. This is however a big error. I proposed a fix to that by changing the semantic of the type qualifier depending on its position in the declaration, but didn't received much feedback at the time. I don't think that's the correct explanation. Andrei
Re: How to break const
Le 18/06/2012 16:43, Andrei Alexandrescu a écrit : On 6/18/12 7:43 AM, deadalnix wrote: Le 18/06/2012 07:36, Mehrdad a écrit : Is it just me, or did I subvert the type system here? delegate fail to ensure transitivity of type qualifier. This is no news. This is however a big error. I proposed a fix to that by changing the semantic of the type qualifier depending on its position in the declaration, but didn't received much feedback at the time. I don't think that's the correct explanation. Andrei I fail to understand what you mean here. This post ins't supposed to explain anything. I've however made other posts to explain why transitivity is broken when it comes to delegate.
Re: How to break const
On Monday, 18 June 2012 at 12:43:04 UTC, deadalnix wrote: Le 18/06/2012 07:36, Mehrdad a écrit : Is it just me, or did I subvert the type system here? delegate fail to ensure transitivity of type qualifier. This is no news. This is however a big error. Oh lol :( thought I'd discovered something. Well in that case, shouldn't the system protect itself then? Otherwise it seems like 'const' in D becomes just like C++ const (doesn't let you "prove" anything)... I proposed a fix to that by changing the semantic of the type qualifier depending on its position in the declaration, but didn't received much feedback at the time. Interesting!
Re: How to break const
Le 18/06/2012 16:28, Artur Skawina a écrit : It's fine, if you view a delegate as opaque. No it isn't. You cannot ensure transitivity anywhere. This have obvious, and severe drawback for concurrent programing (implicit sharing is back) and GC performances (GC can eb crazy fast when it come to transitive immutable data, see OCaml's GC performances for instance). 'this' being const does not preclude accessing the object that 'this' points to via another, mutable, reference. Consider the alternative - you'd have to forbid storing any delegate with a non-const non-value argument inside any object. And "breaking" const would then _still_ be possible and trivial. No, and your example don't demonstrate that in any way. Transitivity is maintained in the example below, because g isn't a member of s, and if it were, then the example would break at compile time. import std.stdio; S*[const(S)*] g; struct S { int i; this(int i) { this.i = i; g[&this] =&this; } void f() const { g[&this].i=666; } } void main() { const s = S(42); writeln(s); s.f(); writeln(s); } Yes, D's "pure" could help here, only it's misnamed (even if in this particular case that term would be fitting). purity is another beast altogether.
Re: How to break const
On Monday, 18 June 2012 at 14:37:26 UTC, Andrei Alexandrescu wrote: On 6/18/12 1:35 AM, Matthias Walter wrote: On 06/18/2012 08:19 AM, Mehrdad wrote: On Monday, 18 June 2012 at 06:14:22 UTC, Matthias Walter wrote: Its not, that a const method cannot modify an object, it just ensures that the const method cannot modify the object *by using the this-pointer*. I see... So that means you /can't/ tell something just by looking at a part of the code, right? (Just mentioning this since this idea seemed to be emphasized a lot by D.) Yes, you are right with that. Actually things are a fair amount subtler. On the face of it, immutable does fulfill the OP's expectation. But even for const code, there's still a lot of guarantees that can be inferred depending on the types involved. Andrei Changing "new const(S)(0);" to "new immutable(S)(0);" still doesn't work tho.
Re: How to break const
On 6/18/12 2:14 AM, Mehrdad wrote: Okay, how about this? http://ideone.com/VMlzS Does this break const? import std.stdio; class S { this(int a) { this.a = a; this.increment = { this.a++; }; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { auto c = new const(S)(0); writeln(c.a); c.oops(); writeln(c.a); } Yes. Currently the constructor is not typechecked properly. Kenji has done some work on that and is still blocked by me and Walter with some questions. Andrei
Re: How to break const
On 6/18/12 1:35 AM, Matthias Walter wrote: On 06/18/2012 08:19 AM, Mehrdad wrote: On Monday, 18 June 2012 at 06:14:22 UTC, Matthias Walter wrote: Its not, that a const method cannot modify an object, it just ensures that the const method cannot modify the object *by using the this-pointer*. I see... So that means you /can't/ tell something just by looking at a part of the code, right? (Just mentioning this since this idea seemed to be emphasized a lot by D.) Yes, you are right with that. Actually things are a fair amount subtler. On the face of it, immutable does fulfill the OP's expectation. But even for const code, there's still a lot of guarantees that can be inferred depending on the types involved. Andrei
Re: How to break const
Le 18/06/2012 15:03, Timon Gehr a écrit : On 06/18/2012 02:45 PM, deadalnix wrote: Le 18/06/2012 07:59, Matthias Walter a écrit : On 06/18/2012 07:36 AM, Mehrdad wrote: Is it just me, or did I subvert the type system here? import std.stdio; struct Const { this(void delegate() increment) { this.increment = increment; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { Const c; c = Const({ c.a++; }); writeln(c.a); c.oops(); writeln(c.a); } I don't think so. When calling oops you have two references to the object c: - The this-pointer of the object itself which is not allowed to change the object in the const-call. - The reference from within main which is allowed to change it and can be reached via the frame pointer of the delegate. I see this as perfectly valid code. Of course, opinions may differ here. Matthias The hidden parameter of the delegate is stored in c. This hidden parameter must be qualified with const when c is made const, for transitivity. However, it isn't. In short : - c is made const - the frame pointer is stored in c - the frame pointer must be made const for transitivity. => The type system is broken. You'll find many examples of this behavior with delegates. The type system is not broken. You cannot modify an immutable object using this behaviour. Delegates are type checked once and for all when they are declared. Transitive const does not necessarily need to apply to their context pointers. I think it is useful to reason about delegates at a higher abstraction level than function pointer and context pointer. You cannot use this to modify immutable data, granted. But you can use that to break transitivity (ie, make immutable data refers mutable datas). It have many hidden traps. For instance, data that isn't shared or immutable can be shared anyway between thread throw delegates. Not being able to ensure transitivity with delegate break all benefit of transitivity. However, delegate is a special beast, because it cannot be safely « constified », but can be safely « unconstified ».
Re: How to break const
On 06/18/12 14:45, deadalnix wrote: > Le 18/06/2012 07:59, Matthias Walter a écrit : >> On 06/18/2012 07:36 AM, Mehrdad wrote: >>> Is it just me, or did I subvert the type system here? >>> >>> >>> import std.stdio; >>> >>> struct Const >>> { >>> this(void delegate() increment) >>> { this.increment = increment; } >>> int a; >>> void delegate() increment; >>> void oops() const { this.increment(); } >>> } >>> >>> void main() >>> { >>> Const c; >>> c = Const({ c.a++; }); >>> writeln(c.a); >>> c.oops(); >>> writeln(c.a); >>> } >>> >> >> I don't think so. When calling oops you have two references to the object c: >> >> - The this-pointer of the object itself which is not allowed to change >> the object in the const-call. >> - The reference from within main which is allowed to change it and can >> be reached via the frame pointer of the delegate. >> >> I see this as perfectly valid code. Of course, opinions may differ here. >> >> Matthias > > The hidden parameter of the delegate is stored in c. This hidden parameter > must be qualified with const when c is made const, for transitivity. However, > it isn't. > > In short : > - c is made const > - the frame pointer is stored in c > - the frame pointer must be made const for transitivity. > > => The type system is broken. You'll find many examples of this behavior with > delegates. It's fine, if you view a delegate as opaque. 'this' being const does not preclude accessing the object that 'this' points to via another, mutable, reference. Consider the alternative - you'd have to forbid storing any delegate with a non-const non-value argument inside any object. And "breaking" const would then _still_ be possible and trivial. import std.stdio; S*[const(S)*] g; struct S { int i; this(int i) { this.i = i; g[&this] = &this; } void f() const { g[&this].i=666; } } void main() { const s = S(42); writeln(s); s.f(); writeln(s); } Yes, D's "pure" could help here, only it's misnamed (even if in this particular case that term would be fitting). artur
Re: D in your browser? possible?
On Sunday, 17 June 2012 at 16:38:25 UTC, Damian wrote: I've noticed a few languages are adopting this, for example Haskell: http://tryhaskell.org Go: http://play.golang.org Will D get something like this? I find it to be of great use with Go specifically and I'm sure it would benefit D just as much. Hey. We are working on something like that. http://dpaste.dzfl.pl/ At the end we want also to share an API to allow users to use service on their own like in the GO Lang website etc, where you can click Try it now (actually its already done via "Compile" button, where request is sent via AJAX). (Warning: Compiler section is actually dummy-filled, at the moment only dmd2.059 is avaible).
Re: AST files instead of DI interface files for faster compilation and easier distribution
On 17/06/12 00:37, Walter Bright wrote: On 6/14/2012 1:03 AM, Don Clugston wrote: It is for debug builds. Iain's data indicates that it's only a few % of the time taken on semantic1(). Do you have data that shows otherwise? Nothing recent, it's mostly from my C++ compiler testing. But you argued in your blog that C++ parsing is inherently slow, and you've fixed those problems in the design of D. And as far as I can tell, you were extremely successful! Parsing in D is very, very fast. Yes, it is designed so you could just import a symbol table. It is done as source code, however, because it's trivial to implement. It has those nasty side-effects listed under (3) though. I don't think they're nasty or are side effects. They are new problems which people ask for solutions for. And they are far more difficult to solve than the original problem.
Re: How to break const
On 06/18/2012 02:45 PM, deadalnix wrote: Le 18/06/2012 07:59, Matthias Walter a écrit : On 06/18/2012 07:36 AM, Mehrdad wrote: Is it just me, or did I subvert the type system here? import std.stdio; struct Const { this(void delegate() increment) { this.increment = increment; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { Const c; c = Const({ c.a++; }); writeln(c.a); c.oops(); writeln(c.a); } I don't think so. When calling oops you have two references to the object c: - The this-pointer of the object itself which is not allowed to change the object in the const-call. - The reference from within main which is allowed to change it and can be reached via the frame pointer of the delegate. I see this as perfectly valid code. Of course, opinions may differ here. Matthias The hidden parameter of the delegate is stored in c. This hidden parameter must be qualified with const when c is made const, for transitivity. However, it isn't. In short : - c is made const - the frame pointer is stored in c - the frame pointer must be made const for transitivity. => The type system is broken. You'll find many examples of this behavior with delegates. The type system is not broken. You cannot modify an immutable object using this behaviour. Delegates are type checked once and for all when they are declared. Transitive const does not necessarily need to apply to their context pointers. I think it is useful to reason about delegates at a higher abstraction level than function pointer and context pointer.
Re: valid uses of shared
"Steven Schveighoffer" , dans le message (digitalmars.D:169568), a écrit : > On Thu, 07 Jun 2012 22:16:21 -0400, Robert DaSilva > wrote: > > >> You're forgetting about Global data. > > I wasn't so much forgetting it as I was ignoring it :) > > My thought on that is that the shared keyword in that case is truly a > storage class. It's the one place where having a value-type based shared > value makes sense. If we had some kind of synchronized/shared pairing, > the compiler would have to allocate mutex space for that too. > >> I think rather the head shared should be striped as this fits better >> with how D treats meaningless specifiers. > > I don't think we can do that with type constructors, but I'm not sure. > I'm certainly against it, as I am against the current abuses of that > methodology. > >> And trying to put structs that contain shared data on the stack should >> be illegal. The compiler can already heap-allocate function variables that should be on the stack. So why disallowing shared for function variables? void foo() { shared int test; // allocates test on shared memory block. } Just like: int delegate(int) adder(int a) { return b => (a+b); // allocates a on the heap to make a closure. } -- Christophe
Re: How to break const
Le 18/06/2012 09:58, Jonathan M Davis a écrit : On Monday, June 18, 2012 08:19:55 Mehrdad wrote: On Monday, 18 June 2012 at 06:14:22 UTC, Matthias Walter wrote: Its not, that a const method cannot modify an object, it just ensures that the const method cannot modify the object *by using the this-pointer*. I see... So that means you /can't/ tell something just by looking at a part of the code, right? (Just mentioning this since this idea seemed to be emphasized a lot by D.) You can if the function is pure as well, because then that delegate would not be legal. For instance, this code import std.stdio; struct Const { this(void delegate() pure increment) { this.increment = increment; } int a; void delegate() pure increment; void oops() const pure { this.increment(); } } void main() { Const c; c = Const({ c.a++; }); writeln(c.a); c.oops(); writeln(c.a); } fails to compile, giving this error: q.d(15): Error: constructor q.Const.this (void delegate() pure increment) is not callable using argument types (void delegate() nothrow @safe) All const guarantees is that the object isn't altered through the const reference/pointer (which in the case of a const function is this). That's powerful, but it needs pure as well to really be able to just glance at it and know that it's not altering your object. If you want an extreme exampl. you could create an object whose entire state was held in a global variable, then the fact that the this pointer was const wouldn't mean much. But if the member functions were pure, then you couldn't access that global variable, and so that externalization of the state wouldn't work, and you'd be guaranteed that the const function didn't alter your object (as long as none of the arguments to that const function held a reference or pointer to that object anyway (though that's a fairly abnormal thing to do) - only strong purity absolutely guarantees that your object isn't being altered). - Jonathan M Davis It would be true if the delegate wasn't stored in c. For instance, it is true if the delegate is passed as oops argument. But in our case, the type system is broken. See explanations in other posts I've made in this thread.
Re: How to break const
Le 18/06/2012 07:36, Mehrdad a écrit : Is it just me, or did I subvert the type system here? delegate fail to ensure transitivity of type qualifier. This is no news. This is however a big error. I proposed a fix to that by changing the semantic of the type qualifier depending on its position in the declaration, but didn't received much feedback at the time. import std.stdio; struct Const { this(void delegate() increment) { this.increment = increment; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { Const c; c = Const({ c.a++; }); writeln(c.a); c.oops(); writeln(c.a); }
Re: How to break const
Le 18/06/2012 07:59, Matthias Walter a écrit : On 06/18/2012 07:36 AM, Mehrdad wrote: Is it just me, or did I subvert the type system here? import std.stdio; struct Const { this(void delegate() increment) { this.increment = increment; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { Const c; c = Const({ c.a++; }); writeln(c.a); c.oops(); writeln(c.a); } I don't think so. When calling oops you have two references to the object c: - The this-pointer of the object itself which is not allowed to change the object in the const-call. - The reference from within main which is allowed to change it and can be reached via the frame pointer of the delegate. I see this as perfectly valid code. Of course, opinions may differ here. Matthias The hidden parameter of the delegate is stored in c. This hidden parameter must be qualified with const when c is made const, for transitivity. However, it isn't. In short : - c is made const - the frame pointer is stored in c - the frame pointer must be made const for transitivity. => The type system is broken. You'll find many examples of this behavior with delegates.
Re: RandomSample with specified random number generator
On 06/18/12 10:40, Joseph Rushton Wakeling wrote: > On 17/06/12 19:50, Artur Skawina wrote: >> I took your random.d and ran with that: >> >> [6612, 6650, 6704, 0, 6629, 6834, 6634, 6756, 6590, 6591] >> [6589, 6587, 6636, 0, 6673, 6704, 6647, 6704, 6643, 6817] >> [6744, 6552, 6602, 0, 6641, 6722, 6598, 6676, 6749, 6716] >> [6641, 6583, 6710, 0, 6618, 6684, 6789, 6673, 6683, 6619] >> [6667, 6692, 6600, 0, 6717, 6588, 6660, 6678, 6673, 6725] >> >> so the problem is still there, just a little different. >> >> I'm using an old GDC build, in case that makes any difference: >> >> gcc version 4.6.3 20120106 (prerelease gdc 0.31 - r748:ab99d67f04c2, using >> dmd 2.057) > > Just built my random.d with gdc 4.6.3 together with your test code. Here's > what comes out: > > [5954, 5896, 6018, 6004, 5978, 5963, 5959, 5970, 6151, 6107] > [6020, 6044, 5914, 5994, 6110, 6064, 5969, 5985, 6002, 5898] > [5877, 6021, 6022, 6054, 6075, 5967, 5998, 6010, 6023, 5953] > [6059, 5968, 5972, 5908, 5982, 6034, 6189, 5909, 5982, 5997] > [6006, 6077, 6011, 6037, 5823, 6062, 6022, 5925, 6065, 5972] > [5877, 6006, 6005, 6049, 6013, 5971, 6053, 6023, 5902, 6101] > [5946, 5984, 6006, 6018, 6049, 6097, 5993, 6030, 5922, 5955] > [5992, 6071, 5974, 5993, 6066, 5974, 5897, 6017, 5951, 6065] > [5975, 6127, 6103, 5889, 6000, 5949, 6003, 5849, 5974, 6131] > [6005, 5937, 5920, 5978, 6032, 6003, 6023, 6064, 6086, 5952] > > ... are you sure there's not something wrong in the way you added my random.d > to your test code? I've sent a copy of my code to you privately so you can > test. Your standalone version works fine. For some reason the test fails as shown above when I replace the std.random module with your version (same as the working test program minus the runtime test), compile it and link my test with the resulting random.o object. artur
Re: Primary Ranges of Containers
On Monday, June 18, 2012 10:06:44 Matthias Walter wrote: > Hi, > > last week I realized that a const version of > std.container.Array.opSlice() is missing. Now I looked at the code and I > think that it is a general design problem. > > The docs state that "c.Range" is "The primary range type associated with > the container.". I think we really always need two Range types (one for > const view and one for non-const view) by design. > > I'd propose to always add a bool template parameter (maybe isConst?) to > the range since most of the write-functionality can be "removed" by a > static if statement in order to make the range read-only. > > Any suggestions? Yeah, it'll probably have to be templated. C++ already has to do something similar with iterators and const_iterators. But since you don't normally use the type of a range explicitly, it shouldn't be a big deal. The one downside that might pose a problem though is that if someone _does_ use the type explicitly, their code will break if the type gets templated. We could make a second type (ConstRange?) for the iterating over a const Array, but I'd be tempted to just templatize the thing and let it break any code that it breaks. std.container is already likely to break stuff to at least some extent when the custom allocators get added anyway. I suppose that we could just rename the type and then create an alias for the current type struct ArrayRange(bool isConst) {...} alias ArrayRange!false Range; alias ArrayRange!true ConstRange; but that might be overkill. I don't know. Regardless, it _is_ likely that the range type will have to be templatized to fix the problem. Ranges and range- based functions in general need to be cleaned up a bit to deal with const, since the way that they're designed doesn't work with const very well, and we need to make it work. I think that it _can_ work, but it takes more effort to do so. - Jonathan M Davis
Re: Segmented Ranges?
"bearophile" , dans le message (digitalmars.D:169611), a écrit : > struct BilevelScan(Range) { This is basically std.algorithm.joiner > So an idea is to introduce in D the multi-level Ranges: > SegmentedInputRange > SegmentedOutputRange > SegmentedForwardRange > SegmentedBidirectionalRange > SegmentedRandomAccessRange > > I think a Segmented Input Range is more complex than an Input > Range. Inventing such ranges is like finding the miminal set of > axioms that allow to write down a theorem, that is to efficiently > implement the normal algorithms. This is not an easy for me, I > don't know much about this topic. I would only use this axiom: - a SegmentedRange defines a bySegment property, returning a Range of Range bearing the same element type as SegmentedRange. and define BySegment!Range as the type returned by range.bySegment, and SegmentType!Range as the type returned by range.bySegment.front. Then it is up to the implementer of the algorithm to test the type of a SegmentedRange (InputRange, OutputRange, etc.), the type of BySegment!Range, and the type of SegmentType!Range when needed. There are too many combinaisons to make specific range types for all of them. Moreover SegmentedRandomAccessRange would be ambiguous: is it a RandomAccessRange, a Range whose BySegment method returns a RandomAccessRange, a Range whose SegmentType is a RandomAccessRange, or all of them ? -- Christophe
Re: Proposal to add 'Elements of Programming' Concepts to std.traits
16.06.2012 20:11, Walter Bright пишет: On 6/16/2012 8:26 AM, Guillaume Chatelet wrote: And then we wonder why software is notorious for being delivered late and full of bugs, while other engineers routinely deliver finished bridges, automobiles, electrical appliances, etc., on time and with only minor defects. I have a nit to pick with that statement, as a former mechanical engineer who has done professional mechanical designs and has taken apart a lot of others. Bridges, automobiles, electrical appliances, etc., are full of design errors. You all probably know a canonical example, Tacoma Narrows Bridge: http://www.youtube.com/watch?v=j-zczJXSxnw Let's forgive its designers because it was the first such accident with bridge. But in Russia we still (2010) have this: http://www.youtube.com/watch?v=rVzYDIlBQ0w And this bridge still works without rebuilding, but with attenuator now. -- Денис В. Шеломовский Denis V. Shelomovskij
Re: DMD + msvc
On Sunday, 17 June 2012 at 10:49:30 UTC, Gor Gyolchanyan wrote: Thanks for the reply. This is so ridiculous and frustrating. Use GDC?
Re: RandomSample with specified random number generator
On 17/06/12 19:50, Artur Skawina wrote: I took your random.d and ran with that: [6612, 6650, 6704, 0, 6629, 6834, 6634, 6756, 6590, 6591] [6589, 6587, 6636, 0, 6673, 6704, 6647, 6704, 6643, 6817] [6744, 6552, 6602, 0, 6641, 6722, 6598, 6676, 6749, 6716] [6641, 6583, 6710, 0, 6618, 6684, 6789, 6673, 6683, 6619] [6667, 6692, 6600, 0, 6717, 6588, 6660, 6678, 6673, 6725] so the problem is still there, just a little different. I'm using an old GDC build, in case that makes any difference: gcc version 4.6.3 20120106 (prerelease gdc 0.31 - r748:ab99d67f04c2, using dmd 2.057) Just built my random.d with gdc 4.6.3 together with your test code. Here's what comes out: [5954, 5896, 6018, 6004, 5978, 5963, 5959, 5970, 6151, 6107] [6020, 6044, 5914, 5994, 6110, 6064, 5969, 5985, 6002, 5898] [5877, 6021, 6022, 6054, 6075, 5967, 5998, 6010, 6023, 5953] [6059, 5968, 5972, 5908, 5982, 6034, 6189, 5909, 5982, 5997] [6006, 6077, 6011, 6037, 5823, 6062, 6022, 5925, 6065, 5972] [5877, 6006, 6005, 6049, 6013, 5971, 6053, 6023, 5902, 6101] [5946, 5984, 6006, 6018, 6049, 6097, 5993, 6030, 5922, 5955] [5992, 6071, 5974, 5993, 6066, 5974, 5897, 6017, 5951, 6065] [5975, 6127, 6103, 5889, 6000, 5949, 6003, 5849, 5974, 6131] [6005, 5937, 5920, 5978, 6032, 6003, 6023, 6064, 6086, 5952] ... are you sure there's not something wrong in the way you added my random.d to your test code? I've sent a copy of my code to you privately so you can test.
Re: How to break const
On Monday, June 18, 2012 09:14:59 Mehrdad wrote: > Okay, how about this? http://ideone.com/VMlzS > > Does this break const? > > > import std.stdio; > class S > { > this(int a) > { > this.a = a; > this.increment = { this.a++; }; > } > int a; > void delegate() increment; > void oops() const { this.increment(); } > } > void main() > { > auto c = new const(S)(0); > writeln(c.a); > c.oops(); > writeln(c.a); > } I'm not sure. I believe that it gets away with it, because none of the member variable are actually const until the constructor has completed, in which case, you've managed to hide away a non-const reference to what is supposed to be a const object. Technically, I don't think that it breaks const, but it does seem rather off. However, if the object isn't actually const until the constructor is complete, then it _is_ perfectly legimate. Now, what worries me is that this seems to compile: import std.stdio; class S { this(int a) immutable { this.a = a; this.increment = { this.a++; }; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { auto c = new const(S)(0); writeln(c.a); c.oops(); writeln(c.a); } As I understand it, that should _not_ compile. An immutable constructor should disallow all mutation of member variables after their initial assignment within the constructor, but clearly that's not happening. It even allows adding ++a; on its own inside of the constructor, so it's not just an issue with the delegate either. - Jonathan M Davis
Primary Ranges of Containers
Hi, last week I realized that a const version of std.container.Array.opSlice() is missing. Now I looked at the code and I think that it is a general design problem. The docs state that "c.Range" is "The primary range type associated with the container.". I think we really always need two Range types (one for const view and one for non-const view) by design. I'd propose to always add a bool template parameter (maybe isConst?) to the range since most of the write-functionality can be "removed" by a static if statement in order to make the range read-only. Any suggestions? Best regards, Matthias
Re: How to break const
On Monday, 18 June 2012 at 07:58:50 UTC, Jonathan M Davis wrote: That's powerful, but it needs pure as well to really be able to just glance at it and know that it's not altering your object. I see, so I need pure for the first example; thanks. How about the second one though?
Re: How to break const
On Monday, 18 June 2012 at 07:58:50 UTC, Jonathan M Davis wrote: That's powerful, but it needs pure as well to really be able to just glance at it and know that it's not altering your object. I see, so I need pure for the first example; thanks. How about the second one though?
Re: How to break const
On Monday, June 18, 2012 08:19:55 Mehrdad wrote: > On Monday, 18 June 2012 at 06:14:22 UTC, Matthias Walter wrote: > > Its not, that a const method cannot modify an object, it just > > ensures that the const method cannot modify the object *by > > using the this-pointer*. > > I see... > > > So that means you /can't/ tell something just by looking at a > part of the code, right? > > (Just mentioning this since this idea seemed to be emphasized a > lot by D.) You can if the function is pure as well, because then that delegate would not be legal. For instance, this code import std.stdio; struct Const { this(void delegate() pure increment) { this.increment = increment; } int a; void delegate() pure increment; void oops() const pure { this.increment(); } } void main() { Const c; c = Const({ c.a++; }); writeln(c.a); c.oops(); writeln(c.a); } fails to compile, giving this error: q.d(15): Error: constructor q.Const.this (void delegate() pure increment) is not callable using argument types (void delegate() nothrow @safe) All const guarantees is that the object isn't altered through the const reference/pointer (which in the case of a const function is this). That's powerful, but it needs pure as well to really be able to just glance at it and know that it's not altering your object. If you want an extreme exampl. you could create an object whose entire state was held in a global variable, then the fact that the this pointer was const wouldn't mean much. But if the member functions were pure, then you couldn't access that global variable, and so that externalization of the state wouldn't work, and you'd be guaranteed that the const function didn't alter your object (as long as none of the arguments to that const function held a reference or pointer to that object anyway (though that's a fairly abnormal thing to do) - only strong purity absolutely guarantees that your object isn't being altered). - Jonathan M Davis
Re: DMD + msvc
On Sunday, 17 June 2012 at 10:49:30 UTC, Gor Gyolchanyan wrote: On Sun, Jun 17, 2012 at 2:34 PM, Jacob Carlborg wrote: On 2012-06-17 07:15, Gor Gyolchanyan wrote: Is it possible to use the VC2010 linker with DMD? That would allow easily linking with COFF libraries and building 64 bit binaries. No. 1. DMD can only output OMF binaries 2. DMD cannot output 64bit code for Windows 3. DMD is not compatible with the MSVC linker or runtime -- /Jacob Carlborg Thanks for the reply. This is so ridiculous and frustrating. Yeah, but do note that even if DMD _was_ compatible with the VC2010 linker, then that still wouldn't get you 64-bit code...
Re: How to break const
Okay, how about this? http://ideone.com/VMlzS Does this break const? import std.stdio; class S { this(int a) { this.a = a; this.increment = { this.a++; }; } int a; void delegate() increment; void oops() const { this.increment(); } } void main() { auto c = new const(S)(0); writeln(c.a); c.oops(); writeln(c.a); }