Re: DIP22 : Private symbol visibility
Case 1 (binary level, C + D): - sample.d - module sample; private int func() { return 42; } -- - oops.c - #include stdio.h extern int _D6sample4funcFZi(); void* _Dmodule_ref = 0; void* _D15TypeInfo_Struct6__vtblZ = 0; void _Dmain() { } int main() { long value = _D6sample4funcFZi(); printf(%ld\n, value); return 0; } -- - shell - $ dmd - c sample.d $ gcc -c oops.c $ gcc oops.o sample.o ./a.out 42 -- This is valid code now and will break. Internal linkage is a binary-level encapsulation tool, contrary to language-level private. Not that when compiling sample.d dmd can't know if oops.c will actually link to func and make decision about internal linkage. Saying this is invalid code may severely limit language interconnection possibilities and something like injecting druntime. Case 2 (pure D, language level): - sample.d - module sample; private struct Hest { int a, b; } public alias Hidden UseMe; -- - oops.d - import sample; import std.stdio; void main() { UseMe tmp; tmp.a = 42; } -- Now suddenly changing Test definition may break code in oops.d and we need first to make sure Test is not referenced in public aliases or as function parameter or as public type member field etc. Again, this code itself is not only valid but quite idiomatic. Internal linkage provides strong guarantees that any change to symbol will affect only its module, with no special cases. Case 3 (consistency): I do insist on keeping class and module protection attribute consistent. Saying class privates are always accessible from other modules via tupleof friends and module privates may be not is causing confusion for no real gain. Also it may break code if we have any means to enumerate module symbols via traits (do we? I don't know).
Re: DIP22 : Private symbol visibility
On Wednesday, 30 January 2013 at 05:29:14 UTC, Jesse Phillips wrote: And this results in people writing code that ...? Is there an example where you can break code in another module by changing something marked as private? Examples separated: http://forum.dlang.org/post/irrbdrxordjawkryv...@forum.dlang.org There is currently no way in D to mark symbols for internal linkage What would that give us? Strong 100% guarantees changes to the symbol won't break anything but its module. Strong 100% guarantees to compiler that he can optimize away/change all internal code when doing separate compilation. Compiler errors upon access to private symbol are changed from %s is not accessible to undefined identifier %s That will just be confusing. You put the name of that symbol because you saw it, being told it is undefined is going to make you think the compiler is broken. That was the most uneasy part of proposal. I have been thinking for few hours about it, considering different options. In the end, I have decided that it is only confusing to one coming from C++ lax approach and for clean mind it should make perfect sense that private symbol is indistinguishable from non-existing one in regular user code - that is the point of encapsulation how I get it. Also in case of denied access most likely you have put that symbol because of typo, not because you know it (why would you intentionally try to use symbol you already know is private?). And it exposes internal module details by an accident. I am very open for more arguments though, it is a somewhat tricky change.
Re: DIP22 : Private symbol visibility
On Wednesday, 30 January 2013 at 09:42:01 UTC, Dicebot wrote: On Wednesday, 30 January 2013 at 05:29:14 UTC, Jesse Phillips wrote: And this results in people writing code that ...? Is there an example where you can break code in another module by changing something marked as private? Examples separated: http://forum.dlang.org/post/irrbdrxordjawkryv...@forum.dlang.org I understand the risk of breakage. But . . . Is this code supposed to work in the first place ? I mean, the private function is not marked export, the language make no guarantee it will be accessible from C. Additionally, does it make sense to prevent D from calling some piece of code, but still allow some external C code to do it ? I think it is invalid code in the first place, and just happen to work right now. case 2 is more tricky, but export isn't involved here.
Re: Mono-D v0.4.9.5 - Infinite analysis fix + Mixin analysis improvement
On 2013-01-30 00:28, alex wrote: Okay, I've uploaded a new version that features a basically working version. There is now a separated mixin insight and expression evaluation available. There are still many things left to do though. I'll give it a try. -- /Jacob Carlborg
Re: DIP22 : Private symbol visibility
On 2013-01-30 10:57, deadalnix wrote: I understand the risk of breakage. But . . . Not worth the breakage. Is this code supposed to work in the first place ? I mean, the private function is not marked export, the language make no guarantee it will be accessible from C. Additionally, does it make sense to prevent D from calling some piece of code, but still allow some external C code to do it ? I think it is invalid code in the first place, and just happen to work right now. case 2 is more tricky, but export isn't involved here. It's not just accessing from C code. Due to D supporting separate compilation you can have the implementation of a private method in a separate object file. -- /Jacob Carlborg
Re: DIP22 : Private symbol visibility
On Wednesday, 30 January 2013 at 12:02:46 UTC, Jacob Carlborg wrote: It's not just accessing from C code. Due to D supporting separate compilation you can have the implementation of a private method in a separate object file. The code is in C in the example. But if you replace the C code by another D module, the exact same reasoning holds. What point are you trying to make by raising that ? It seems completely irrelevant to me. Or I didn't inferred the part of the reasoning that was implied in your post. Please make it explicit.
Re: Dgame
On Tuesday, 29 January 2013 at 16:34:15 UTC, Namespace wrote: On Tuesday, 29 January 2013 at 15:19:37 UTC, David wrote: Am 29.01.2013 16:10, schrieb Namespace: Ahh. That could be a problem: I hate makefiles and never wrote one. Hehe, to quote ibuclaw: `make no-sense` It doesn't need to be a makefile, some kind of build-script, which automates the process of building the library. E.g. a d file which compiles the stuff for you: rdmd build.d Seems I have to edit my tutorials and my installations guide. You have now a build script. Thanks to aladacron, I adapted his build script from derelict. Compile build.d and let it run. Your lib files are generated in the directory lib/MODE where MODE is the current mode. Compile normal and MODE is Release, compile with -debug and MODE is Debug. The only problem is currently, that I have no experiences with GDC and LDC, so I have no idea which flags they use for debug mode. Because of that, Debug build works currently only for dmd. But I will fix this later. LDC has ldmd2 wrapper script which is used similar to dmd and GDC has gdmd (gdmd is written in perl so you need to have perl installed to run it). Those wrapper scripts support most of DMD's flags. They also have -vdmd flag, which tells the wrapper script to print out the commands that it runs. You can use that to find out which ldc2 and gdc commands correspond to a given dmd command, if you want to use ldc2 or gdc directly.
Re: DIP22 : Private symbol visibility
On 2013-01-30 17:26, deadalnix wrote: The code is in C in the example. But if you replace the C code by another D module, the exact same reasoning holds. What point are you trying to make by raising that ? It seems completely irrelevant to me. Or I didn't inferred the part of the reasoning that was implied in your post. Please make it explicit. If you have a public and a private function in the same module, it's possible to implement the two functions in two separate object files. The private function must then be available in the object file to link the program properly. -- /Jacob Carlborg
Re: Possible @property compromise
On Wednesday, 30 January 2013 at 03:02:38 UTC, deadalnix wrote: On Wednesday, 30 January 2013 at 00:26:11 UTC, q66 wrote: It deeply disturbs me that people even take the original post seriously. Well, you may give some arguments instead of no, just no, to convince people. It just gives another meaning to foo.bar, and ENFORCING camelCase by the language while lowercasing shit is just horrible. Anyone with a slightest trace of language design sense realizes that.
Re: Implementing Half Floats in D
On Tuesday, 29 January 2013 at 22:49:02 UTC, Joseph Rushton Wakeling wrote: On 01/29/2013 11:27 PM, Iain Buclaw wrote: I'm sure this was mentioned before, but what does halffloat have over std.numeric.CustomFloat? These formats are for storage only; all operations on them are performed by first implicitly extracting them to real first. ... whereas HalfFloat extracts to float, and so should be faster, which is probably one of the main goals here. But since std.numeric was mentioned, why not add HalfFloat there rather than its own separate module? The discussion we had on github agreed that std.halffloat isn't a good place. But OTOH std.numeric needs a complete overhaul, it's a mess. It would be a mistake to throw it in there.
Re: Throwable class design
On Wednesday, January 30, 2013 08:32:47 rumbu wrote: On Wednesday, 30 January 2013 at 07:01:56 UTC, H. S. Teoh wrote: Not true. I use this idiom a lot: a lower level function throws an error message (e.g., integer format error), and a catch-block halfway up the call-chain modifies .msg to include contextual information (e.g., filename, line number) and rethrows the exception, so that at the top level the error message contains both context information and the low-level error message. T I thought exceptions are meant to be catched, not rethrown. If you are the developper of an end user solution, you'll catch the exception and you will display a message some way with the details that you need, or, better, you will silently drop the exception taking the necessary actions to resolve the cause. Throwing exceptions in the user's face is not so friendly. If you are a library developper, you'll catch the exception and you will rethrow *another* exception wrapping the original exception in the next field through the constructor. Target developpers of your library have no interest in your detailed message, but in the *type* of the exception thrown. Their program flow cannot interpret messages. Exceptions get rethrown all the time. Heck, that's what happens with finally, scope(failure), and scope(exit). It's what you do when you need to react to the fact that the exception was thrown (maybe even to the specific exception) but aren't going to handle it in that section of code. Now, mutating the exception before rethrowing is another thing. I'd tend to think that that was bad practice, but I suppose that it could be useful upon occasion. In general though, if I wanted to add information, I'd wrap the caught exception in a new exception and throw that. - Jonathan M Davis
Re: Deque impl.
On 01/30/2013 07:55 AM, monarch_dodra wrote: On Tuesday, 29 January 2013 at 22:44:35 UTC, Robert Schadek wrote: On 01/29/2013 09:20 PM, monarch_dodra wrote: 3. Nitpick: Don't use parenthesis for single arg templates: No: Deque!(int) yes: Deque!int May I ask why? Both are correct after all. Or is it just the preferred style? It's just style, and a nitpick. Feel free to ignore it. 5. Users expect opSlice() to produce an actual range. You are using it to deep copy the deck. This goes against your comment in regards to slicing an iterator. Just have your opSlice() do the same as what range() does, and get rid of range(). This is the usage I'd expect: // Deque!intde = ... ; Iterator!int it = de[]; writeln(it); // I submitted a bug report for sort recently (9091 became 8368). monarchdodra said (and pointed to source) that opSlice should return the same type in respect to the called object. Yes, 9071. I remember it quite well, and it was the first thing that came to mind the instant I saw your your code. What I said is that for a *range* to offer correct *hasSlicing* primitive, then the opSlice(size_t, size_t) primitive must return the same type. Deque is not a range though, Iterator is, and we're talking about the primitive opSlice() Again: this is a Container vs Range issue. For example, built-in arrays also have this scheme. // //statarr is a static array. A container. statarr is NOT a range. int[5] statarr = [0, 1, 2, 3, 4]; //dynarrX are ranges extracted from their container int[] dynarr1 = statarr[]; int[] dynarr2 = statarr[1 .. 3]; // As you can see, int[] != int[5] I see your point.
Re: IOC is inside Clang-head
On Tuesday, 29 January 2013 at 21:26:11 UTC, Walter Bright wrote: On 1/29/2013 1:15 PM, David Nadlinger wrote: On Tuesday, 29 January 2013 at 19:21:34 UTC, Walter Bright wrote: One real issue is order of evaluation bugs, but I didn't see a note about that in the Clang list. Why would you need runtime checking for that? I didn't say you did! Besides the AddressSanatizer and MemorySanatizer features which are obviously real-world oriented (cf. Valgrind), I also find quite a few of the ubsan features to be actually useful in practice - integer overflow detection is only a small part of it. valgrind is immensely useful for C, but a lot less so for D as D guarantees initialization and a GC takes care of much of the rest. Many have jokes about Java being a language that requires an IDE to be usable. Usually I joke that C is a language for tool vendors. How many vendors can take their business to C undefined behaviors and pointer abuse. No one on their senses does use C today without an endless list of tools that validate their code is not going to explode. -- Paulo
Re: IOC is inside Clang-head
On Wednesday, 30 January 2013 at 09:01:53 UTC, Paulo Pinto wrote: On Tuesday, 29 January 2013 at 21:26:11 UTC, Walter Bright wrote: On 1/29/2013 1:15 PM, David Nadlinger wrote: On Tuesday, 29 January 2013 at 19:21:34 UTC, Walter Bright wrote: One real issue is order of evaluation bugs, but I didn't see a note about that in the Clang list. Why would you need runtime checking for that? I didn't say you did! Besides the AddressSanatizer and MemorySanatizer features which are obviously real-world oriented (cf. Valgrind), I also find quite a few of the ubsan features to be actually useful in practice - integer overflow detection is only a small part of it. valgrind is immensely useful for C, but a lot less so for D as D guarantees initialization and a GC takes care of much of the rest. Many have jokes about Java being a language that requires an IDE to be usable. Usually I joke that C is a language for tool vendors. How many vendors can take their business to C undefined behaviors and pointer abuse. No one on their senses does use C today without an endless list of tools that validate their code is not going to explode. -- Paulo s/take/thank
Re: Throwable class design
On Wednesday, 30 January 2013 at 08:44:52 UTC, Jonathan M Davis wrote: Exceptions get rethrown all the time. Heck, that's what happens with finally, scope(failure), and scope(exit). It's what you do when you need to react to the fact that the exception was thrown (maybe even to the specific exception) but aren't going to handle it in that section of code. Now, mutating the exception before rethrowing is another thing. I'd tend to think that that was bad practice, but I suppose that it could be useful upon occasion. In general though, if I wanted to add information, I'd wrap the caught exception in a new exception and throw that. - Jonathan M Davis Exceptions are not rethrown, finally block is executed *after* throwing/catching the exception. I don't know the details of the scope(*) implementations, but I doubt that they are rethrowing any exceptions. Exceptions are propagated, not rethrown with a mutated message or field.
Re: Throwable class design
On Wednesday, 30 January 2013 at 09:05:22 UTC, rumbu wrote: On Wednesday, 30 January 2013 at 08:44:52 UTC, Jonathan M Davis wrote: Exceptions get rethrown all the time. Heck, that's what happens with finally, scope(failure), and scope(exit). It's what you do when you need to react to the fact that the exception was thrown (maybe even to the specific exception) but aren't going to handle it in that section of code. Now, mutating the exception before rethrowing is another thing. I'd tend to think that that was bad practice, but I suppose that it could be useful upon occasion. In general though, if I wanted to add information, I'd wrap the caught exception in a new exception and throw that. - Jonathan M Davis Exceptions are not rethrown, finally block is executed *after* throwing/catching the exception. I don't know the details of the scope(*) implementations, but I doubt that they are rethrowing any exceptions. Exceptions are propagated, not rethrown with a mutated message or field. Finally needs to rethrow the exception at the end of the scope. If an exception is thrown in the finally clause, it is chained at the end of the exception currently in flight. I'm pretty sure scope(*) just lowers to try/catch/finally: try { // something // scope(success) } catch (Exception) { // scope(failure) } finally { // scope(exit) }
Re: Request for comments: std.d.lexer
On Monday, 28 January 2013 at 21:03:21 UTC, Timon Gehr wrote: Better, but still slow. I implemented the various suggestions from a past thread and made the lexer only work ubyte[] (to aviod phobos converting everything to dchar all the time) and gave the tokenizer instance a character buffer that it re-uses. Results: $ avgtime -q -r 200 ./dscanner --tokenCount ../phobos/std/datetime.d Total time (ms): 13861.8 Repetitions: 200 Sample mode: 69 (90 ocurrences) Median time: 69.0745 Avg time : 69.3088 Std dev. : 0.670203 Minimum: 68.613 Maximum: 72.635 95% conf.int. : [67.9952, 70.6223] e = 1.31357 99% conf.int. : [67.5824, 71.0351] e = 1.72633 EstimatedAvg95%: [69.2159, 69.4016] e = 0.0928836 EstimatedAvg99%: [69.1867, 69.4308] e = 0.12207 If my math is right, that means it's getting 4.9 million tokens/second now. According to Valgrind the only way to really improve things now is to require that the input to the lexer support slicing. (Remember the secret of Tango's XML parser...) The bottleneck is now on the calls to .idup to construct the token strings from slices of the buffer. I guess that at some point pure nothrow TokenType lookupTokenType(const string input) might become a bottleneck. (DMD does not generate near-optimal string switches, I think.) Right now that's a fairly small box on KCachegrind.
Re: Request for comments: std.d.lexer
Am 30.01.2013 10:49, schrieb Brian Schott: On Monday, 28 January 2013 at 21:03:21 UTC, Timon Gehr wrote: Better, but still slow. I implemented the various suggestions from a past thread and made the lexer only work ubyte[] (to aviod phobos converting everything to dchar all the time) and gave the tokenizer instance a character buffer that it re-uses. Results: $ avgtime -q -r 200 ./dscanner --tokenCount ../phobos/std/datetime.d . If my math is right, that means it's getting 4.9 million tokens/second now. According to Valgrind the only way to really improve things now is to require that the input to the lexer support slicing. (Remember the secret of Tango's XML parser...) The bottleneck is now on the calls to .idup to construct the token strings from slices of the buffer. but you still need to compare that to the current dmd lexer - nothing else can be a benchmark reference
Re: Request for comments: std.d.lexer
On 2013-01-30 10:49, Brian Schott wrote: If my math is right, that means it's getting 4.9 million tokens/second now. According to Valgrind the only way to really improve things now is to require that the input to the lexer support slicing. (Remember the secret of Tango's XML parser...) The bottleneck is now on the calls to .idup to construct the token strings from slices of the buffer. Yep. I'm eager to see what timings you get with the whole file kept in memory and sliced, without copying token strings.
Regarding Issue 9423
Currently you are allowed to write a lambda literal as in line 3, but you can't omit ref as in line 4: void foo(int delegate(ref int[1]) spam) {} void main() { foo((ref x) = 0); // line3, OK foo(x = 0); // line4, Error } Do you think ref annotation should be required at the call site? This is the Bugzilla thread. Hara has already implemented the ref inference, but he's not sure if it's a good idea: http://d.puremagic.com/issues/show_bug.cgi?id=9423 Bye, bearophile
Re: Regarding Issue 9423
On Wednesday, 30 January 2013 at 11:10:17 UTC, bearophile wrote: Currently you are allowed to write a lambda literal as in line 3, but you can't omit ref as in line 4: void foo(int delegate(ref int[1]) spam) {} void main() { foo((ref x) = 0); // line3, OK foo(x = 0); // line4, Error } Do you think ref annotation should be required at the call site? This is the Bugzilla thread. Hara has already implemented the ref inference, but he's not sure if it's a good idea: http://d.puremagic.com/issues/show_bug.cgi?id=9423 Bye, bearophile I like it. Would be a good time to require this for normal functions and methods also. As C# it does.
Re: Regarding Issue 9423
On Wednesday, 30 January 2013 at 11:17:30 UTC, Namespace wrote: On Wednesday, 30 January 2013 at 11:10:17 UTC, bearophile wrote: Currently you are allowed to write a lambda literal as in line 3, but you can't omit ref as in line 4: void foo(int delegate(ref int[1]) spam) {} void main() { foo((ref x) = 0); // line3, OK foo(x = 0); // line4, Error } Do you think ref annotation should be required at the call site? This is the Bugzilla thread. Hara has already implemented the ref inference, but he's not sure if it's a good idea: http://d.puremagic.com/issues/show_bug.cgi?id=9423 Bye, bearophile I like it. Would be a good time to require this for normal functions and methods also. As C# it does. I prefer the Pascal family way where they are implicit, but lets have what the majority prefers.
Re: Possible @property compromise
On Wednesday, 30 January 2013 at 02:15:09 UTC, Rob T wrote: Even with @property restrictions, I still don't think it will work as expected. For example, if the variable is a struct, then you have to disallow operations on the struct from outside. Example: struct Y { int a; } struct X{ @property Y y; } X x; x.y.a = 4; // - this has to be illegal! Reason? struct X{ Y _y; @property Y y{ return _y; } } // this won't change _y as it did before. x.y.a = 4; Somehow I had missed this post. So, we can bury the idea of restricting the access to a public member variable by making it illegal to take the address of it. And as long as it is possible to take the address of a public member variable, it is possible for the end-user to by-pass all encapsulation that you might later on add over that public member variable. For this reason, my logic says, it is impossible to invent such an implementation of property concept that would make it possible to first put in a public member variable and later on encapsulate it *without* changing the interface.
Re: Possible @property compromise
On Wednesday, 30 January 2013 at 12:04:31 UTC, TommiT wrote: [..] it is impossible to invent such an implementation of property concept that would make it possible to first put in a public member variable and later on encapsulate it *without* changing the interface. And frankly, I think it's a good thing. Because this way we can add to D's documentation: NOTE: properties are *not* inter-changeable with public member variables, and thus, actively discourage people from writing un-encapsulated interfaces which expose public member variables.
Re: Regarding Issue 9423
On Wednesday, 30 January 2013 at 11:10:17 UTC, bearophile wrote: Currently you are allowed to write a lambda literal as in line 3, but you can't omit ref as in line 4: void foo(int delegate(ref int[1]) spam) {} void main() { foo((ref x) = 0); // line3, OK foo(x = 0); // line4, Error } Do you think ref annotation should be required at the call site? Ref isn't at a call site, it is a function declaration and not passing lambda by ref. This is the Bugzilla thread. Hara has already implemented the ref inference, but he's not sure if it's a good idea: http://d.puremagic.com/issues/show_bug.cgi?id=9423 Bye, bearophile int delegate(ref int[1] spam) and int delegate(int[1] spam) are different. True, the proposal makes code writing convenient, but it can lead to troubles when foo has overload with non-ref parameter delegate. This also may probably lead to problems when passed by delegate function modifies its argument but it is unexpected by user because function was not annotated with ref. Moreover, this is a special case in a language.
Re: Possible @property compromise
On Wednesday, 30 January 2013 at 12:11:30 UTC, TommiT wrote: Because this way we can add to D's documentation: NOTE: properties are *not* inter-changeable with public member variables, and thus, actively discourage people from writing un-encapsulated interfaces which expose public member variables. The moral of the story: We should all stop thinking of properties as data, and start thinking properties as functions that you call with a data-like interface. The value of properties is in clearer semantics: Separate accessor and mutator are tied together very loosely, that is, only by the similarity in their naming: getSomething, setSomething. Whereas property getter and setter have the same name, and thus are semantically un-ambiguously tied together.
Re: Implementing Half Floats in D
On 2013-01-30, 09:26, Don wrote: The discussion we had on github agreed that std.halffloat isn't a good place. But OTOH std.numeric needs a complete overhaul, it's a mess. It would be a mistake to throw it in there. So put it somewhere else for the moment, and move it to std.numeric after a while? Boy, does that ever sound stupid. I say stuff it in std.numeric, and announce properly that someone should probably have look at fixing std.numeric, and that HalfFloat in there may be the only thing salvageable (not that I know if it is, but that's how you make it sound). -- Simen
Re: Possible @property compromise
On 2013-01-30 00:55, Rob T wrote: Given how D currently works, I don't see how we can realistically implement a function as a drop in replacement for a variable and expect code to continue working as if nothing had changed. One of the bigger problems is that the getter returns by value, not ref, so everything that expects a ref return will fail. I expect to make precise variable emulation through properties will require a lot of compiler magic, and there will be inevitable bugs and conflicts that follow. I really don't see that there's enough value with the property concept to justify the costs of precise variable emulation. You know a lot more about implementing compiler magic than I do, so I'll ask you if you think the effort is doable enough to justify having property functions that can act like a drop in replacement for existing variables? Implement this: struct Foo { @property int a; } Lowered to: struct Foo { private int a_; @property int a () { return a_; } @property int a (int value) { return a_ = value; } } -- /Jacob Carlborg
convert class of in pascal to D.
Hi, guys? I'm new in D and I come from pascal. The constructor concept is very different, and it's very confusing for me. I want to create some statement in D which in pascal like this. type TMyObjectAClass = class of TMyObject_A; // number 1 TMyObject_A = class constructor Create(AString : String); end; TMyObject_B = class(TMyObject_A) constructor Create(AString : String); override; end; TMyObject_C = class(TMyObject_A) end; - - - - - - - - - - - - - - - - - function Foo(AClass: TMyObjectAClass): TMyObject_A; begin Result:= AClass.Create(AClass.ClassName); //number 2 end; - - - - - - - - - - - - - - - - - var B : TMyObject_B; C : TMyObject_C; begin B:= Foo(TMyObject_B); //number 3 C:= Foo(TMyObject_C); end. === Question 1 How I can make a data type class of in D language Question 2 How to convert number 2, in D language. Question 3 How I passing a class type as argument like number 3, and if D can do same thing like pascal, which one is called by D, TMyObject_A.Create() or TMyObject_B.Create() ? In pascal It should be call TMyObject_B.Create() first Thanks :) Eko
Re: convert class of in pascal to D.
Please post next time in D.learn. In D it is still like in other C like languages: class A { public: this() { writeln(A CTor); } } A a = new A(); create a new object of type A and print A CTor Because D has no standard copy CTor for classes, you must declare your own: class A { public: this() { writeln(A CTor); } this(ref const A a) { writeln(A copy CTor); } } which is called with: A a = new A(); A ac = new A(a); // - calls copy CTor
Re: convert class of in pascal to D.
Piotr Szturmaj wrote: A foo(T : A)() that should be: T foo(T : A)()
Re: convert class of in pascal to D.
Eko Wahyudin wrote: Hi, guys? I'm new in D and I come from pascal. The constructor concept is very different, and it's very confusing for me. I want to create some statement in D which in pascal like this. type TMyObjectAClass = class of TMyObject_A; // number 1 TMyObject_A = class constructor Create(AString : String); end; TMyObject_B = class(TMyObject_A) constructor Create(AString : String); override; end; TMyObject_C = class(TMyObject_A) end; - - - - - - - - - - - - - - - - - function Foo(AClass: TMyObjectAClass): TMyObject_A; begin Result:= AClass.Create(AClass.ClassName); //number 2 end; - - - - - - - - - - - - - - - - - var B : TMyObject_B; C : TMyObject_C; begin B:= Foo(TMyObject_B); //number 3 C:= Foo(TMyObject_C); end. === Question 1 How I can make a data type class of in D language Question 2 How to convert number 2, in D language. Question 3 How I passing a class type as argument like number 3, and if D can do same thing like pascal, which one is called by D, TMyObject_A.Create() or TMyObject_B.Create() ? In pascal It should be call TMyObject_B.Create() first class of in Delphi/OP means type or subtype of a class. You can use template parameters in D to pass class of: // T : A means any type T that is equivalent to A or is subtype of A A foo(T : A)() { return new T(T.stringof); } B b; C c; b = foo!B(); c = foo!C();
Re: Possible @property compromise
On 2013-01-30 02:40, TommiT wrote: I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming? I really don't see much point in properties/methods that just forwards to an instance variable. -- /Jacob Carlborg
Re: Possible @property compromise
On 2013-01-30 03:15, Rob T wrote: Even with @property restrictions, I still don't think it will work as expected. For example, if the variable is a struct, then you have to disallow operations on the struct from outside. Example: struct Y { int a; } struct X{ @property Y y; } X x; x.y.a = 4; // - this has to be illegal! Reason? struct X{ Y _y; @property Y y{ return _y; } } // this won't change _y as it did before. x.y.a = 4; That would require some property rewrite by the compiler. -- /Jacob Carlborg
Re: convert class of in pascal to D.
On Wednesday, 30 January 2013 at 14:48:07 UTC, Eko Wahyudin wrote: Hi, guys? I'm new in D and I come from pascal. The constructor concept is very different, and it's very confusing for me. I want to create some statement in D which in pascal like this. type TMyObjectAClass = class of TMyObject_A; // number 1 TMyObject_A = class constructor Create(AString : String); end; TMyObject_B = class(TMyObject_A) constructor Create(AString : String); override; end; TMyObject_C = class(TMyObject_A) end; - - - - - - - - - - - - - - - - - function Foo(AClass: TMyObjectAClass): TMyObject_A; begin Result:= AClass.Create(AClass.ClassName); //number 2 end; - - - - - - - - - - - - - - - - - var B : TMyObject_B; C : TMyObject_C; begin B:= Foo(TMyObject_B); //number 3 C:= Foo(TMyObject_C); end. === Question 1 How I can make a data type class of in D language Question 2 How to convert number 2, in D language. Question 3 How I passing a class type as argument like number 3, and if D can do same thing like pascal, which one is called by D, TMyObject_A.Create() or TMyObject_B.Create() ? In pascal It should be call TMyObject_B.Create() first Thanks :) Eko There are no class types in D and classes without empty constructors cannot be instantiated directly. The closest solution is to use a templated function for Foo: class TMyObject_A { this(string AString) { } } class TMyObject_B : TMyObject_A { this(string AString) { super(AString); } } class TMyObject_C : TMyObject_A { this(string AString) { super(AString); } //there is no default constructor without parameters in the base class. } TMyObjectAClass Foo(TMyObjectAClass)() if (is(TMyObjectAClass : TMyObject_A)) { return new TMyObjectAClass(TMyObjectAClass.stringof); } int main(string[] argv) { TMyObject_B B = Foo!TMyObject_B(); TMyObject_C C = Foo!TMyObject_C(); return 0; }
Re: Possible @property compromise
On 1/30/13 10:10 AM, Jacob Carlborg wrote: On 2013-01-30 02:40, TommiT wrote: I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming? I really don't see much point in properties/methods that just forwards to an instance variable. Insurance. Andrei
Re: convert class of in pascal to D.
thanks all, I think i am understand, if the closest solution is template, there is no solution in D for my code like this. type TMyObjectClass = class of TMyObjectA; var ClassArray : array of TMyObjectClass; //the content initialized randomly ObjectArray : array of TMyObjectA; i, j : Integer; procedure CreateAllObject; begin J:= length(ClassArray); for I:= 0 to J do begin ObjectArray[I]:= ClassArray[I].Create({some argument}); end; end; if D unable to do this, I think we must do something with D. I'm still thinking, why constructor in D adopt C++ style rather than pascal style, while pascal style is better :-?
Re: Possible @property compromise
On Wednesday, 30 January 2013 at 15:10:37 UTC, Jacob Carlborg wrote: I really don't see much point in properties/methods that just forwards to an instance variable. I assume you mean something like this: struct S { private T _t; ref T get() { return _t; } void set(T t) { ... } } The benefit of the above type of coding versus having a public T variable, is that you can change the implementation of S without changing S's interface. Perhaps I would like to change it to this (or whatever): private static T[5] tees; struct S { private byte _idx; ref T get() { return tees[_idx]; } void set(T t) { ... } }
Re: Property discussion wrap-up
On Sunday, 27 January 2013 at 18:12:48 UTC, Artur Skawina wrote: struct Plain { int a; } struct Tricky { int a; Plain opCall() { return Plain.init } } void func(int) { } // What happens? Tricky t; t.a.func(); I suppose func is called with Tricky.a, because t is a variable not a function. But, by the way, what are the exact rules of this thing we call optional parentheses? Perhaps this: Empty parentheses may be omitted when calling functions with a user-defined name. That leaves operators, delegates, function pointers, and function objects outside of that rule, because they aren't functions with a name. But, parens could be omitted with functions whose all arguments have default values.
Re: Request for comments: std.d.lexer
29-Jan-2013 01:04, Timon Gehr Đ¿Đ¸ÑˆĐµÑ‚: On 01/28/2013 12:59 PM, Dmitry Olshansky wrote: 28-Jan-2013 15:48, Johannes Pfau Đ¿Đ¸ÑˆĐµÑ‚: ... But to be fair that doesn't fit ranges very well. If you don't want to do any allocation but still keep identifiers etc in memory this basically means you have to keep the whole source in memory and this is conceptually an array and not a range. Not the whole source but to construct a table of all identifiers. The source is awfully redundant because of repeated identifiers, spaces, comments and what not. The set of unique identifiers is rather small. Source code is usually small. (Even std.datetime has 'only' 1.6 MB.) My own lexer-parser combination slices directly into the original source code, for every token, in order to remember the exact source location, and the last time I have measured, it ran faster than DMD's. I keep the source around for error reporting anyway: tt.d:27:5: error: no member 'n' for type 'A' a.n=2; ^~~ Since the tokens point directly into the source code, it is not necessary to construct any other data structures in order to allow fast retrieval of the appropriate source code line. But it's clear that a general-purpose library might not want to impose this restriction on storage upon it's clients. I think it is somewhat helpful for speed though. The other thing I do is buffering tokens in a contiguous ring buffer that grows if a lot of lookahead is requested. I think the best course of action is to just provide a hook to trigger on every identifier encountered. That could be as discussed earlier a delegate. ... Maybe. I map identifiers to unique id's later, in the identifier AST node constructor, though. In allocation scheme I proposed that ID could be a 32bit offset into the unique identifiers chunk. Identifiers themselves then would have to be stored with sentinels (e.g. zeros) at end like in C. Then the 'map' process comes for free. The only overhead is actually copying the bytes to this buffer but it only happens once per unique identifier and in exchange you get to lex anything not only 'the whole module in one memory block' kind of thing. On the plus side it's also more cache friendly. Overall I think it's a good trade-off, but I never had the time to exercise it. -- Dmitry Olshansky
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 16:39:55 UTC, TommiT wrote: Empty parentheses may be omitted when calling functions with a user-defined name. Sorry, bad wording. Better one: Empty parentheses may be omitted when calling a function that has a user-defined name.
Re: Request for comments: std.d.lexer
30-Jan-2013 13:49, Brian Schott Đ¿Đ¸ÑˆĐµÑ‚: On Monday, 28 January 2013 at 21:03:21 UTC, Timon Gehr wrote: Better, but still slow. I implemented the various suggestions from a past thread and made the lexer only work ubyte[] (to aviod phobos converting everything to dchar all the time) and gave the tokenizer instance a character buffer that it re-uses. Results: $ avgtime -q -r 200 ./dscanner --tokenCount ../phobos/std/datetime.d Total time (ms): 13861.8 Repetitions: 200 Sample mode: 69 (90 ocurrences) Median time: 69.0745 Avg time : 69.3088 Std dev. : 0.670203 Minimum: 68.613 Maximum: 72.635 95% conf.int. : [67.9952, 70.6223] e = 1.31357 99% conf.int. : [67.5824, 71.0351] e = 1.72633 EstimatedAvg95%: [69.2159, 69.4016] e = 0.0928836 EstimatedAvg99%: [69.1867, 69.4308] e = 0.12207 If my math is right, that means it's getting 4.9 million tokens/second now. According to Valgrind the only way to really improve things now is to require that the input to the lexer support slicing. (Remember the secret of Tango's XML parser...) The bottleneck is now on the calls to .idup to construct the token strings from slices of the buffer. idup -- allocation Instead I suggest to try and allocate a big block of fixed size (say about 16-64K) upfront and copy identifiers one by one there. When it fills just allocate another one and move on. If identifier is exceptionally long then you can just idup it as before. This should bring down the number of calls to GC significantly. I guess that at some point pure nothrow TokenType lookupTokenType(const string input) might become a bottleneck. (DMD does not generate near-optimal string switches, I think.) Right now that's a fairly small box on KCachegrind. -- Dmitry Olshansky
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 16:45:04 UTC, TommiT wrote: Empty parentheses may be omitted when calling a function that has a user-defined name. ... except when the address of the returned value is requested directly after the function call, then parentheses are required.
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 06:46:01 UTC, H. S. Teoh wrote: That page only states the structs nested inside *functions* have a context pointer to the function's local variables. It says nothing about structs nested inside *structs*. (And yes, I looked. I was actually in the middle of writing something about using structs to simulate properties, and decided to look it up to be sure, and found that the spec actually doesn't say what I thought it said.) T Okay, cool. Two questions remain: 1) How hard to implement structs nested in structs to mimic ones nested in functions? 2) How much code breakage?
Re: PDF spec
On Wednesday, 30 January 2013 at 07:19:14 UTC, Jordi Sayol wrote: I've built a chm spec. check it out. http://d-packages.googlecode.com/files/dlangspec.chm Something is wrong with this file - pages dont show up for me. There's an (iexplorer?) error message, but its in my native language, so I can only guess the corresponding english translation. Its something like the user aborted the page loading process. Page links are incorrect maybe? I dont use iexplorer, sorry. :)
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 06:38:32 UTC, Rob T wrote: opCall requires parens, probably to disambiguate from alias this. string A { int i; int opCall() { return _i; } } A a, int i = a; // error int i = a(); // works You can however do this alias opCall this; int i = a; // works int i = a(); // works too --rt I guess that's how to do it. So now we have all three. Mandate parens with opCall. Allow both with alias opCall this, and disallow parens with opGet. So let's go back to my previous argument. Aside from a few language changes, such as making current nested structs into nested static structs, and introducing opGet, a @property is nothing but a poor man's struct. Destroy.
Re: convert class of in pascal to D.
Am 30.01.2013 17:16, schrieb Eko Wahyudin: thanks all, I think i am understand, if the closest solution is template, there is no solution in D for my code like this. type TMyObjectClass = class of TMyObjectA; var ClassArray : array of TMyObjectClass; //the content initialized randomly ObjectArray : array of TMyObjectA; i, j : Integer; procedure CreateAllObject; begin J:= length(ClassArray); for I:= 0 to J do begin ObjectArray[I]:= ClassArray[I].Create({some argument}); end; end; if D unable to do this, I think we must do something with D. I'm still thinking, why constructor in D adopt C++ style rather than pascal style, while pascal style is better :-? sorry but the pascal class of-type and the ctor-derivation isn't that super-mighty at all as long as the ctors of your object are the same everything is fine else - the feature isn't useable anymore, then you need a real object factory in real OOP objects are specialized through its virtual method implementations AND its ctor-parameters (which are similar in very very few rare cases) for example pseudo code class Stream virtual read_bytes()... class FileStream: Stream this(filename) class NetworkStream: Stream this(tcp_ip,timeout) Stream[] streams streams ~= FileStream(c:/temp/test.txt); streams ~= NetworkStream(123.112.2.1, 1000); stream[n].read_bytes() this is a much more common OOP/ctor situation then yours i think its part of pascal/object delphi to ease the VCL development but this can be easily reached with an internal CreateInstance routine like Stream virtual Stream CreateInstance() and FileStream implements CreateInstance() with with return new FileStream NetworkStream with new NetworkStream etc. so whats the realy big deal/feature of this class of-type except for very trivial OOP case
Re: Throwable class design
On Wednesday, January 30, 2013 10:05:21 rumbu wrote: On Wednesday, 30 January 2013 at 08:44:52 UTC, Jonathan M Davis wrote: Exceptions get rethrown all the time. Heck, that's what happens with finally, scope(failure), and scope(exit). It's what you do when you need to react to the fact that the exception was thrown (maybe even to the specific exception) but aren't going to handle it in that section of code. Now, mutating the exception before rethrowing is another thing. I'd tend to think that that was bad practice, but I suppose that it could be useful upon occasion. In general though, if I wanted to add information, I'd wrap the caught exception in a new exception and throw that. - Jonathan M Davis Exceptions are not rethrown, finally block is executed *after* throwing/catching the exception. I don't know the details of the scope(*) implementations, but I doubt that they are rethrowing any exceptions. Exceptions are propagated, not rethrown with a mutated message or field. You seem to think that rethrowing has something to do with mutation. It doesn't. Finally, scope(failure), and scope(exit) all must catch exceptions, run the code within their blocks, and then rethrow the exception. No mutation of the exception is involved. If they didn't rethrow the exception, then it would stop there and never escape those blocks, and if it weren't caught by them, then those blocks wouldn't be executed at all. Also I could easily do something like try throw new Exception(hello); catch(Exception e) { writefln(It says: %s, e.msg); throw e; } I catch and use the exception and then rethrow it, but I don't mutate it. Yes, you can catch an exception, mutate it, and then rethrow it. But the fact that it's rethrown says nothing about whether it was mutated. It just means that the exception continues to propagate up again after it was caught. - Jonathan M Davis
Re: Request for comments: std.d.lexer
On 2013-01-30 17:50, Dmitry Olshansky wrote: Instead I suggest to try and allocate a big block of fixed size (say about 16-64K) upfront and copy identifiers one by one there. When it fills just allocate another one and move on. Yeah, similar to what I suggested, except that probably it would be good to also have a look-up structure for identifiers, so that only unique strings go into those blocks. I wonder what would be a practical data structure for such look-ups: A trie is great except for the implementation hurdle to keep it also in one or a few memory blocks to prevent frequent allocations. A simpler approach would be to make it an array of (hash, string_slice) pairs, sorted by hash (of the identifier) - lots of string scanning though. What do you think?
Re: Regarding Issue 9423
On Wednesday, January 30, 2013 12:51:22 Paulo Pinto wrote: I prefer the Pascal family way where they are implicit, but lets have what the majority prefers. We've had this discussion at length before. It should stay implicit. There's no real point in having it at the call site unless it's required, which would break a lot of code even if you accepted that it was a valuable change. We're not going to do it. But regardless, Bearophile's example doesn't involve having ref at the call site. It's requiring ref on the parameter of a lambda declaration. That's the declaration site, not the call site. - Jonathan M Davis
anyone ever tried to DustMite C++ code?
..and thus already has a working splitter?
Re: Regarding Issue 9423
On Wednesday, 30 January 2013 at 17:26:13 UTC, Jonathan M Davis wrote: On Wednesday, January 30, 2013 12:51:22 Paulo Pinto wrote: I prefer the Pascal family way where they are implicit, but lets have what the majority prefers. We've had this discussion at length before. It should stay implicit. Ehh, where is this discussion and will this change implemented in the near future?
Re: Request for comments: std.d.lexer
30-Jan-2013 21:21, FG Đ¿Đ¸ÑˆĐµÑ‚: On 2013-01-30 17:50, Dmitry Olshansky wrote: Instead I suggest to try and allocate a big block of fixed size (say about 16-64K) upfront and copy identifiers one by one there. When it fills just allocate another one and move on. Yeah, similar to what I suggested, except that probably it would be good to also have a look-up structure for identifiers, so that only unique strings go into those blocks. I wonder what would be a practical data structure for such look-ups: A trie is great except for the implementation hurdle to keep it also in one or a few memory blocks to prevent frequent allocations. Mm trie shouldn't have that many allocations. Typically each node is fixed-sized. Also I don't see keeping it in many memory blocks as a show stopper. The trick is exactly the same as I mentioned above but blocks got to be quite a bit large (say 8 times :) ). Truth be told the trie should be optimal for this, but a lot of effort is required to implement a fast trie compared to rolling out a simple hash-table. That's something I hope to change once my Trie template is polished enough for Phobos proposal. A simpler approach would be to make it an array of (hash, string_slice) pairs, sorted by hash (of the identifier) - lots of string scanning though. Mm since you need to find what's unique as you lex the file I suspect that sorting is out of the window. I'd be modest and for starters just use a hash-table + tune the hash function a bit. -- Dmitry Olshansky
Re: Property discussion wrap-up
30-Jan-2013 21:02, Zach the Mystic Đ¿Đ¸ÑˆĐµÑ‚: On Wednesday, 30 January 2013 at 06:46:01 UTC, H. S. Teoh wrote: That page only states the structs nested inside *functions* have a context pointer to the function's local variables. It says nothing about structs nested inside *structs*. (And yes, I looked. I was actually in the middle of writing something about using structs to simulate properties, and decided to look it up to be sure, and found that the spec actually doesn't say what I thought it said.) T Okay, cool. Two questions remain: 1) How hard to implement structs nested in structs to mimic ones nested in functions? IMO if property is to be implemented in the library it has to include the field itself. (And I suspect properties should enjoy compiler support). Then something like: struct A{ Property!(int, filter, getter) prop; private: void func() { ... prop.raw = xxx; //direct write prop = yyy; //goes through setter } } where .raw is the field itself and there must be a way to let only struct itself have access to it. I have one method to get this but I don't like it - put this in each module: mixin PropertyForModule!(my_module); introducing a Property template in this module, with private .raw accessible thusly only in this module. Getter is then just any function that maps T = T, with x = x by default so can be omitted. Filter is something new but in essence it works like the following setter: void setter(T)(ref T val, T newVal) { val = filter(newVal); //filter may through } It's a bit more restrictive though so feel free to destroy. 2) How much code breakage? A lot + subtly wasting memory. -- Dmitry Olshansky
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 17:02:44 UTC, Zach the Mystic wrote: [..] 1) How hard to implement structs nested in structs to mimic ones nested in functions? Given: struct Outer { struct Inner { int n1; } int n2; } Outer.sizeof should be equal to 2 * int.sizeof, because there's no point in introducing any overhead here. Whereas structs inside functions do their magic by having an implicit pointer, which increases their size. I don't think we want to introduce any memory overhead with something as insignificant as properties.
Re: Throwable class design
On Wed, Jan 30, 2013 at 12:43:49AM -0800, Jonathan M Davis wrote: On Wednesday, January 30, 2013 08:32:47 rumbu wrote: On Wednesday, 30 January 2013 at 07:01:56 UTC, H. S. Teoh wrote: Not true. I use this idiom a lot: a lower level function throws an error message (e.g., integer format error), and a catch-block halfway up the call-chain modifies .msg to include contextual information (e.g., filename, line number) and rethrows the exception, so that at the top level the error message contains both context information and the low-level error message. T I thought exceptions are meant to be catched, not rethrown. If you are the developper of an end user solution, you'll catch the exception and you will display a message some way with the details that you need, or, better, you will silently drop the exception taking the necessary actions to resolve the cause. Throwing exceptions in the user's face is not so friendly. The point is that an error has occurred, and normal processing cannot continue, so an exception is thrown. The catching here is not to throw an exception at the user's face; it is to insert additional information about the problem at an intermediate level up the call-chain. Further up the call chain, the application would still catch the exception and display the message. The rationale for modifying the exception message is that (1) the low-level code that threw the original exception does not have enough context to be able to provide a helpful message (e.g., it doesn't directly know which filename/line number it's processing, it's just a low-level dumb conversion routine), and (2) a little further up the call chain are functions that *do* have enough context to insert helpful information, so they catch the exception, add on the context information, and rethrow the exception to continue propagating the error condition. This way, you will get to see both the exact problem that caused the processing to fail (the original .msg) and also where in the input (filename/line number) that triggered this problem. If you are a library developper, you'll catch the exception and you will rethrow *another* exception wrapping the original exception in the next field through the constructor. Target developpers of your library have no interest in your detailed message, but in the *type* of the exception thrown. Their program flow cannot interpret messages. The message is intended for the end-user, not the library code. Exceptions get rethrown all the time. Heck, that's what happens with finally, scope(failure), and scope(exit). It's what you do when you need to react to the fact that the exception was thrown (maybe even to the specific exception) but aren't going to handle it in that section of code. Now, mutating the exception before rethrowing is another thing. I'd tend to think that that was bad practice, but I suppose that it could be useful upon occasion. In general though, if I wanted to add information, I'd wrap the caught exception in a new exception and throw that. [...] In my case, I guess I didn't really see the need to invent another wrapper exception type just to be able to insert filename/line number information. As far as the application code is concerned, a parsing error is a parsing error; it shouldn't need to know if said parsing error is a wrapper class containing the real exception object. All it cares to know is, a problem occurred, and the .msg field contains a description of the problem that can be displayed to the user. T -- Windows: the ultimate triumph of marketing over technology. -- Adrian von Bidder
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 17:35:25 UTC, Dmitry Olshansky wrote: 2) How much code breakage? A lot + subtly wasting memory. I still have to read your other comments, but the issue of wasting memory has already been addressed by suggesting that the compiler detect that absence of any actual data in the struct and prohibit taking its address or referring to this except perhaps in the case of alias someFunction this to allow it to call that function transparently. It would not give the function a pointer or anything, the goal being to truly harness the power of struct's semantics without paying a price in performance of any kind.
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 17:42:48 UTC, TommiT wrote: On Wednesday, 30 January 2013 at 17:02:44 UTC, Zach the Mystic wrote: [..] 1) How hard to implement structs nested in structs to mimic ones nested in functions? Given: struct Outer { struct Inner { int n1; } int n2; } Outer.sizeof should be equal to 2 * int.sizeof, because there's no point in introducing any overhead here. Whereas structs inside functions do their magic by having an implicit pointer, which increases their size. I don't think we want to introduce any memory overhead with something as insignificant as properties. See my first answer to Dmitri's post. Most properties will hold no data of their own, and the compiler could detect this, thus eliminating the need for the pointer at runtime.
Re: Possible @property compromise
On 01/30/2013 03:29 AM, Jonathan M Davis wrote: ... C# manages it ... Nope.
Re: What am I missin with const?
On 29/01/2013 10:21, Era Scarecrow wrote: On Tuesday, 29 January 2013 at 09:45:17 UTC, Timon Gehr wrote: On 01/29/2013 10:38 AM, deadalnix wrote: Well I think the error message you propose isn't possible as it would cause many problems in generic code. How? const applied to the return type should be the way to go. It is basically what everybody except at first when looking at the code. But it is probably too late to change that. The current behavior emerges because the parser treats const void foo(){} exactly like const{ void foo(){} } Somehow that's what I'd prefer, Consistency. If it's an int, then these two could be very confusing based on location of const. So if const is unattached it is for the whole function const int foo() //misleading vs int foo() const However specifying an item that's const will always result in the correct const of that type. There's never ambiguity following those rules; Although those coming from C++ will need to put the extra effort to specify which is const. const(int) foo() vs int foo() const There is unnecessary syntactic ambiguity for users unaware of the problem (or aware users that are tired so not able to recognize the problem immediately). This is exactly the same reason dmd warns about a dangling else: if (x) if (y){} else {} // warning: dangling else The above is consistent and correct code from the compiler's point of view, but is bug-prone for humans, so the compiler complains. The fact it comes up in the newsgroups periodically is proof the current syntax is confusing.
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 17:35:25 UTC, Dmitry Olshansky wrote: Okay, cool. Two questions remain: 1) How hard to implement structs nested in structs to mimic ones nested in functions? IMO if property is to be implemented in the library it has to include the field itself. (And I suspect properties should enjoy compiler support). Then something like: struct A{ Property!(int, filter, getter) prop; private: void func() { ... prop.raw = xxx; //direct write prop = yyy; //goes through setter } } where .raw is the field itself and there must be a way to let only struct itself have access to it. I have one method to get this but I don't like it - put this in each module: mixin PropertyForModule!(my_module); introducing a Property template in this module, with private .raw accessible thusly only in this module. Getter is then just any function that maps T = T, with x = x by default so can be omitted. Filter is something new but in essence it works like the following setter: void setter(T)(ref T val, T newVal) { val = filter(newVal); //filter may through } It's a bit more restrictive though so feel free to destroy. Does my suggestion about the compiler detecting a struct with no data warm you up a bit to properties as structs? If so, there is really very little need for ANY library support. Strangely, implementing struct-nested structs with actual data could be a significantly harder task than implementing them with no data. No extra pointer need be created. I'll try to summarize the changes required. The first two are necessary. The third is for aesthetic reasons, but as in the case of lambda functions that could make a huge difference. 1. Have non-static struct-nested structs be able to refer to their parent's data. With no-data structs, I suspect this will be easy, and it's actually the primary intended usage, which makes only the corner case tricky, where new pointers must be added, etc. 2. Add opGet to the compiler's list of overloads. It is simply opCall but with parens banned instead of mandated. 3. Enable Highlander structs so that defining a property is as easy as define a new-style lamba: struct __fooHidden {} __fooHidden foo; simply becomes: foo struct {}
Re: Property discussion wrap-up
On 01/30/2013 05:39 PM, TommiT wrote: ... Empty parentheses may be omitted when calling functions with a user-defined name. ... This is subject to 4 exceptions: auto foo() { ... } 1. foo // get function pointer or delegate 2. alias x = foo; // alias to function (same for alias params) 3. typeof(foo)// type of function 4. foo() // function called
Re: Regarding Issue 9423
On 01/30/2013 12:10 PM, bearophile wrote: Currently you are allowed to write a lambda literal as in line 3, but you can't omit ref as in line 4: void foo(int delegate(ref int[1]) spam) {} void main() { foo((ref x) = 0); // line3, OK foo(x = 0); // line4, Error } Do you think ref annotation should be required at the call site? This is the Bugzilla thread. Hara has already implemented the ref inference, but he's not sure if it's a good idea: http://d.puremagic.com/issues/show_bug.cgi?id=9423 Bye, bearophile I think the current behaviour is ok, but I do not really care. BTW, the pull does not contain a test for the case void foo(int delegate(int) dg){ ... } // 1 void foo(int delegate(ref int) dg){ ... } // 2 void main(){ foo(x=0); } // call 1
Re: Property discussion wrap-up
30-Jan-2013 22:05, Zach the Mystic Đ¿Đ¸ÑˆĐµÑ‚: On Wednesday, 30 January 2013 at 17:35:25 UTC, Dmitry Olshansky wrote: Okay, cool. Two questions remain: 1) How hard to implement structs nested in structs to mimic ones nested in functions? IMO if property is to be implemented in the library it has to include the field itself. (And I suspect properties should enjoy compiler support). Then something like: struct A{ Property!(int, filter, getter) prop; private: void func() { ... prop.raw = xxx; //direct write prop = yyy; //goes through setter } } where .raw is the field itself and there must be a way to let only struct itself have access to it. I have one method to get this but I don't like it - put this in each module: mixin PropertyForModule!(my_module); introducing a Property template in this module, with private .raw accessible thusly only in this module. Getter is then just any function that maps T = T, with x = x by default so can be omitted. Filter is something new but in essence it works like the following setter: void setter(T)(ref T val, T newVal) { val = filter(newVal); //filter may through } It's a bit more restrictive though so feel free to destroy. Does my suggestion about the compiler detecting a struct with no data warm you up a bit to properties as structs? If so, there is really very little need for ANY library support. Strangely, implementing struct-nested structs with actual data could be a significantly harder task than implementing them with no data. No extra pointer need be created. I have one key problem - the hidden pointer detail. In other words how should it find the instance of the outer struct to to access it? struct A{ int a; struct B{ void foo(){ a = 42; } } B b; } A a; a.b.foo(); //how that b is supposed to know it's outer struct without the hidden pointer? auto x = a.b; x.foo();// and now what? I'll try to summarize the changes required. The first two are necessary. The third is for aesthetic reasons, but as in the case of lambda functions that could make a huge difference. 1. Have non-static struct-nested structs be able to refer to their parent's data. With no-data structs, I suspect this will be easy, and it's actually the primary intended usage, which makes only the corner case tricky, where new pointers must be added, etc. 2. Add opGet to the compiler's list of overloads. It is simply opCall but with parens banned instead of mandated. 3. Enable Highlander structs so that defining a property is as easy as define a new-style lamba: struct __fooHidden {} __fooHidden foo; simply becomes: foo struct {} -- Dmitry Olshansky
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 18:06:47 UTC, Timon Gehr wrote: This is subject to 4 exceptions: auto foo() { ... } 1. foo // get function pointer or delegate 2. alias x = foo; // alias to function (same for alias params) 3. typeof(foo)// type of function 4. foo() // function called I'd count only 1. and 3. as exceptions to the rule. I don't see how is 4. is an exception - it's just a regular function call without omitting the parens. I'm not sure if it's possible to create an alias to an expression like: alias x = foo; ...but if it's possible, then I think it's fine to allow it. It will work as if x were the expression it aliases, and would work like: int value = x; // this is same as writing int value = foo; ...given that foo() returns something that's convertible to int.
Re: PDF spec
Am 30.01.2013 18:08, schrieb kiskami: On Wednesday, 30 January 2013 at 07:19:14 UTC, Jordi Sayol wrote: I've built a chm spec. check it out. http://d-packages.googlecode.com/files/dlangspec.chm Something is wrong with this file - pages dont show up for me. There's an (iexplorer?) error message, but its in my native language, so I can only guess the corresponding english translation. Its something like the user aborted the page loading process. Page links are incorrect maybe? I dont use iexplorer, sorry. :) Have you unblocked the file? chm files can contain ActiveXs, so as security measure since the XP security overall you need to explicitly allow chm files that you downloaded to be secure. Check the file properties. -- Paulo
Re: convert class of in pascal to D.
Am 30.01.2013 18:18, schrieb dennis luehring: Am 30.01.2013 17:16, schrieb Eko Wahyudin: thanks all, I think i am understand, if the closest solution is template, there is no solution in D for my code like this. type TMyObjectClass = class of TMyObjectA; var ClassArray : array of TMyObjectClass; //the content initialized randomly ObjectArray : array of TMyObjectA; i, j : Integer; procedure CreateAllObject; begin J:= length(ClassArray); for I:= 0 to J do begin ObjectArray[I]:= ClassArray[I].Create({some argument}); end; end; if D unable to do this, I think we must do something with D. I'm still thinking, why constructor in D adopt C++ style rather than pascal style, while pascal style is better :-? sorry but the pascal class of-type and the ctor-derivation isn't that super-mighty at all as long as the ctors of your object are the same everything is fine else - the feature isn't useable anymore, then you need a real object factory in real OOP objects are specialized through its virtual method implementations AND its ctor-parameters (which are similar in very very few rare cases) for example pseudo code class Stream virtual read_bytes()... class FileStream: Stream this(filename) class NetworkStream: Stream this(tcp_ip,timeout) Stream[] streams streams ~= FileStream(c:/temp/test.txt); streams ~= NetworkStream(123.112.2.1, 1000); stream[n].read_bytes() this is a much more common OOP/ctor situation then yours i think its part of pascal/object delphi to ease the VCL development but this can be easily reached with an internal CreateInstance routine like Stream virtual Stream CreateInstance() and FileStream implements CreateInstance() with with return new FileStream NetworkStream with new NetworkStream etc. so whats the realy big deal/feature of this class of-type except for very trivial OOP case Actually there are many definitions what real OOP means. As for Delphi's case, if I am not mistaken it tries to follow the metaclass concept that Smalltalk has, and Java/.NET have to a certain extent. You can do lots of cool tricks with metaclass programming, specially in Smalltalk. -- Paulo
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 18:06:47 UTC, Timon Gehr wrote: 2. alias x = foo; // alias to function (same for alias params) Oh, yeah, now I see what you mean. It would be impossible to alias the function name if foo is considered a function call in that case. Would it be possible that an alias would have multiple interpretations, depending on the context where it's used? E.g. int foo() {...} alias x = foo; int value = x; auto func = x; // function pointer Or is that too weird.
Re: Property discussion wrap-up
I kind of like this strange love child of a namespace and a variable that you're talking about. But I wouldn't call it a struct. I wouldn't make empty structs be these weird special cases which behave completely differently. Instead, I'd introduce a new keyword for this... thing.
Re: convert class of in pascal to D.
Am 30.01.2013 19:58, schrieb Paulo Pinto: Am 30.01.2013 18:18, schrieb dennis luehring: in real OOP objects are specialized through its virtual method implementations AND its ctor-parameters (which are similar in very very few rare cases) for example pseudo code class Stream virtual read_bytes()... class FileStream: Stream this(filename) class NetworkStream: Stream this(tcp_ip,timeout) Stream[] streams streams ~= FileStream(c:/temp/test.txt); streams ~= NetworkStream(123.112.2.1, 1000); stream[n].read_bytes() this is a much more common OOP/ctor situation then yours i think its part of pascal/object delphi to ease the VCL development but this can be easily reached with an internal CreateInstance routine like Stream virtual Stream CreateInstance() and FileStream implements CreateInstance() with with return new FileStream NetworkStream with new NetworkStream etc. so whats the realy big deal/feature of this class of-type except for very trivial OOP case Actually there are many definitions what real OOP means. As for Delphi's case, if I am not mistaken it tries to follow the metaclass concept that Smalltalk has, and Java/.NET have to a certain extent. no there aren't many definitions but many many missuse of the concept you interface is the adaptor, your virtual method code is the special behavior, your ctors parameters are the intialisers of the special behavior - everything else is just a pseudo-procedural style - its not OOP if you need to use casts and ifs on your object-type, thats procedural programming with class-based fake-namespaces can you give me a small example of the metaclass concept of smalltalk - related to my simple stream example?
Re: Property discussion wrap-up
On 01/30/2013 07:49 PM, TommiT wrote: On Wednesday, 30 January 2013 at 18:06:47 UTC, Timon Gehr wrote: This is subject to 4 exceptions: auto foo() { ... } 1. foo // get function pointer or delegate 2. alias x = foo; // alias to function (same for alias params) 3. typeof(foo)// type of function 4. foo() // function called I'd count only 1. and 3. as exceptions to the rule. They are all exceptions that an implementation does need to consider. I don't see how is 4. is an exception - it's just a regular function call without omitting the parens. It is an exception because foo means call foo, and foo() means call foo, and not call foo and then the result of foo. I'm not sure if it's possible to create an alias to an expression like: alias x = foo; ...but if it's possible, That is mostly a compiler implementation detail. (Create a hidden enum symbol vs store the value in the alias directly.) Expressions may bind to template alias params. I think rule 2. should probably be replaced/extended by: 2. Foo!foo // direct template argument template Bar(int x) { ... } int foo(){ ... } mixin Bar!foo; // error (Alternatively DMD may be declared to be in error here.) then I think it's fine to allow it. It will work as if x were the expression it aliases, ... That is how it works for identifiers.
Re: Property discussion wrap-up
On 01/30/2013 07:55 PM, TommiT wrote: On Wednesday, 30 January 2013 at 18:06:47 UTC, Timon Gehr wrote: 2. alias x = foo; // alias to function (same for alias params) Oh, yeah, now I see what you mean. It would be impossible to alias the function name if foo is considered a function call in that case. Would it be possible that an alias would have multiple interpretations, depending on the context where it's used? E.g. int foo() {...} alias x = foo; int value = x; auto func = x; // function pointer Or is that too weird. The above code is equivalent to int value = foo; auto func = foo; So I do not see what could be considered weird.
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 19:26:01 UTC, Timon Gehr wrote: So I do not see what could be considered weird. Right, I just don't know much about aliases.
Re: Regarding Issue 9423
On Wednesday, January 30, 2013 18:35:29 Namespace wrote: On Wednesday, 30 January 2013 at 17:26:13 UTC, Jonathan M Davis wrote: On Wednesday, January 30, 2013 12:51:22 Paulo Pinto wrote: I prefer the Pascal family way where they are implicit, but lets have what the majority prefers. We've had this discussion at length before. It should stay implicit. Ehh, where is this discussion I don't remember when it was discussed before. It's happened at least a couple of times, and I'd have to go digging through the archives. But after those discussions, I believe that it was pretty clear that we're not going to start supporting ref at the call site. and will this change implemented in the near future? What change? My point was that it's _not_ changing. Function parameters can be marked with ref, but the call site doesn't use ref, and it isn't going to start using ref. - Jonathan M Davis
Re: Possible @property compromise
On Wednesday, January 30, 2013 18:54:20 Timon Gehr wrote: On 01/30/2013 03:29 AM, Jonathan M Davis wrote: ... C# manages it ... Nope. It was my understanding that it did. Everything that I've read on it indicated that it did. But I have used C# minimally (and not recently), so I could easily be wrong when it comes to much of anything about C#. - Jonathan M Davis
Re: convert class of in pascal to D.
On Wednesday, 30 January 2013 at 16:16:49 UTC, Eko Wahyudin wrote: thanks all, I think i am understand, if the closest solution is template, there is no solution in D for my code like this. type TMyObjectClass = class of TMyObjectA; var ClassArray : array of TMyObjectClass; //the content initialized randomly ObjectArray : array of TMyObjectA; i, j : Integer; procedure CreateAllObject; begin J:= length(ClassArray); for I:= 0 to J do begin ObjectArray[I]:= ClassArray[I].Create({some argument}); end; end; if D unable to do this, I think we must do something with D. I'm still thinking, why constructor in D adopt C++ style rather than pascal style, while pascal style is better :-? The only problem for translating your code is the parameterized constructor. Otherwise, your code will look in D like this an no template is involved: TypeInfo_Class[] ClassArray; TMyObjectA[] ObjectArray; void CreateAllObject() { foreach(int i = 0; i ClassArray.length; i++) ObjectArray[i] = ClassArray[i].create(); } Anyway, you can transform your constructor parameter in a field or property and set it in the for statement for each new object.
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 18:05:08 UTC, Zach the Mystic wrote: [..] How about using this new namespace_thingy keyword: struct S { private int value; namespace_thingy prop { int get() { return value; } prop opAssign(int v) { value = v; return prop; } // int data; // error: can't have data here } } The compiler would implicitly create something like: struct S { private int value; int prop_get() { return value; } int prop_opAssign(int v) { value = v; return prop_get(); } } ... S s; int v1 = s.prop;// lowered to s.prop_get() int v2 = (s.prop = v1); // lowered to s.prop_opAssign(v1) assert(v1 == v2);
Re: Possible @property compromise
On 01/30/2013 08:44 PM, Jonathan M Davis wrote: On Wednesday, January 30, 2013 18:54:20 Timon Gehr wrote: On 01/30/2013 03:29 AM, Jonathan M Davis wrote: ... C# manages it ... Nope. It was my understanding that it did. Everything that I've read on it indicated that it did. But I have used C# minimally (and not recently), so I could easily be wrong when it comes to much of anything about C#. - Jonathan M Davis (C# has ref parameters. Properties cannot be passed by ref, but public fields can.)
Re: Regarding Issue 9423
On Wednesday, 30 January 2013 at 11:10:17 UTC, bearophile wrote: Currently you are allowed to write a lambda literal as in line 3, but you can't omit ref as in line 4: void foo(int delegate(ref int[1]) spam) {} void main() { foo((ref x) = 0); // line3, OK foo(x = 0); // line4, Error } Do you think ref annotation should be required at the call site? This is the Bugzilla thread. Hara has already implemented the ref inference, but he's not sure if it's a good idea: http://d.puremagic.com/issues/show_bug.cgi?id=9423 Bye, bearophile By the way, recently problem with functions taking by ref and returning passed ref was discussed and was considered to be a @safity hole. If your proposal is accepted, issue with ref and @safe may be needed to be taken into account in application to your proposal.
Re: Throwable class design
Ok, maybe my thoughts are polluted by some C# programming practices, but I learnt that exceptions are never intended for the end user (one of the reasons is that the exception mesages are in most cases displayed in english language). In Windows world, throwing an exception displays a message with a nice two buttons: Close and Debug. This will make the accountant using my software very eager to click on Debug :) My way to deal now with *unattended* exceptions is to log them for further investigation, but I will never display a raw exception message, considering the fact that my LOB applications are in most cases multilanguage.
Re: Possible @property compromise
On 2013-01-30 20:44, Jonathan M Davis wrote: It was my understanding that it did. Everything that I've read on it indicated that it did. But I have used C# minimally (and not recently), so I could easily be wrong when it comes to much of anything about C#. Last time I used C# it didn't have property rewrite when returning structs. -- /Jacob Carlborg
Re: Possible @property compromise
On 2013-01-30 17:26, TommiT wrote: I assume you mean something like this: struct S { private T _t; ref T get() { return _t; } void set(T t) { ... } } The benefit of the above type of coding versus having a public T variable, is that you can change the implementation of S without changing S's interface. Perhaps I would like to change it to this (or whatever): private static T[5] tees; struct S { private byte _idx; ref T get() { return tees[_idx]; } void set(T t) { ... } } Sure, but I think that's what properties are for. We currently don't have that in D but I think it would be great if fields could be exchanged with methods without breaking the API. -- /Jacob Carlborg
Re: Throwable class design
On Wed, Jan 30, 2013 at 09:03:31PM +0100, rumbu wrote: Ok, maybe my thoughts are polluted by some C# programming practices, but I learnt that exceptions are never intended for the end user (one of the reasons is that the exception mesages are in most cases displayed in english language). In Windows world, throwing an exception displays a message with a nice two buttons: Close and Debug. This will make the accountant using my software very eager to click on Debug :) Maybe that is accepted convention in the Windows world, but I consider exceptions as an excellent way of conveying what went wrong to the user. Such as could not calculate cell value, expecting number in cell A5 but got 'adfsdfas' instead. Throwing an exception is the cleanest way to abort potentially deeply-nested calculation code and give the user a useful message in the meantime. I would hate to manually propagate such user errors by hand, just because of the convention that exception messages should never be seen by the user! OTOH, I do understand that *some* exceptions aren't intended for user consumption, such as internal errors in the program that are useful only to the programmer. In such cases, I would use separate branches of the exception class hierarchy, one for user-consumable exceptions, one for exceptions that should only be logged and replaced with a generic message (like The application has encountered an internal problem, please report the problem to technical support. Though honestly, I can never stand these sorts of messages... but I do know some people prefer that than to seeing raw exception messages). My way to deal now with *unattended* exceptions is to log them for further investigation, but I will never display a raw exception message, considering the fact that my LOB applications are in most cases multilanguage. I guess it depends on the application, but you could always use i18n-keyed string in your exception messages instead of plain English. (Or use a gettext-like system where the English string is the key to the translation files.) Then you can translate the message before displaying it to the user. T -- Real programmers can write assembly code in any language. :-) -- Larry Wall
Re: Regarding Issue 9423
What change? My point was that it's _not_ changing. Function parameters can be marked with ref, but the call site doesn't use ref, and it isn't going to start using ref. - Jonathan M Davis My fault. I thought that the optional call site ref/out whatever might be implemented in the future. The C# way makes more sense, so I thought many users here would see something like this also. Even if it would be optional.
Re: Throwable class design
On Wednesday, January 30, 2013 12:40:26 H. S. Teoh wrote: On Wed, Jan 30, 2013 at 09:03:31PM +0100, rumbu wrote: Ok, maybe my thoughts are polluted by some C# programming practices, but I learnt that exceptions are never intended for the end user (one of the reasons is that the exception mesages are in most cases displayed in english language). In Windows world, throwing an exception displays a message with a nice two buttons: Close and Debug. This will make the accountant using my software very eager to click on Debug :) Maybe that is accepted convention in the Windows world, but I consider exceptions as an excellent way of conveying what went wrong to the user. Such as could not calculate cell value, expecting number in cell A5 but got 'adfsdfas' instead. Throwing an exception is the cleanest way to abort potentially deeply-nested calculation code and give the user a useful message in the meantime. I would hate to manually propagate such user errors by hand, just because of the convention that exception messages should never be seen by the user! I would never show an exception to a user, even in Linux. I might show the exception's message, but I would never let the exception escape and end up showing the stack trace and whatnot to the user. I see no problem in showing an exception's message to a user if that's what it was intended for. The fact that it was an exception which delivered the message is an implementation detail that the user doesn't care about and shouldn't know. But I suspect that the two of you pretty much agree about that but are thinking of different things when you're talking about showing the exception to the user. - Jonathan M Davis
Re: Regarding Issue 9423
On Wednesday, January 30, 2013 21:51:19 Namespace wrote: What change? My point was that it's _not_ changing. Function parameters can be marked with ref, but the call site doesn't use ref, and it isn't going to start using ref. - Jonathan M Davis My fault. I thought that the optional call site ref/out whatever might be implemented in the future. The C# way makes more sense, so I thought many users here would see something like this also. Even if it would be optional. No, it's been argued before, and IMHO optional ref does more harm than having none. The real benefit is when it's required, but even if it were generally agreed that that were better, it wouldn't get changed at this point, since it would break too much code. I suspect that it would cause problems with generic code though, regardless. - Jonathan M Davis
Re: Possible @property compromise
On Wednesday, 30 January 2013 at 20:28:32 UTC, Jacob Carlborg wrote: Sure, but I think that's what properties are for. We currently don't have that in D but I think it would be great if fields could be exchanged with methods without breaking the API. The problem is that genie is out of the bottle once you have committed yourself to an interface where there is a public member variable. And you can't put the genie back in the bottle any more. This means that your interface can't add any encapsulation over this public member variable afterwards without changing the interface.
Re: Throwable class design
On Wed, Jan 30, 2013 at 04:07:31PM -0500, Jonathan M Davis wrote: On Wednesday, January 30, 2013 12:40:26 H. S. Teoh wrote: On Wed, Jan 30, 2013 at 09:03:31PM +0100, rumbu wrote: Ok, maybe my thoughts are polluted by some C# programming practices, but I learnt that exceptions are never intended for the end user (one of the reasons is that the exception mesages are in most cases displayed in english language). In Windows world, throwing an exception displays a message with a nice two buttons: Close and Debug. This will make the accountant using my software very eager to click on Debug :) Maybe that is accepted convention in the Windows world, but I consider exceptions as an excellent way of conveying what went wrong to the user. Such as could not calculate cell value, expecting number in cell A5 but got 'adfsdfas' instead. Throwing an exception is the cleanest way to abort potentially deeply-nested calculation code and give the user a useful message in the meantime. I would hate to manually propagate such user errors by hand, just because of the convention that exception messages should never be seen by the user! I would never show an exception to a user, even in Linux. I might show the exception's message, but I would never let the exception escape and end up showing the stack trace and whatnot to the user. I see no problem in showing an exception's message to a user if that's what it was intended for. The fact that it was an exception which delivered the message is an implementation detail that the user doesn't care about and shouldn't know. But I suspect that the two of you pretty much agree about that but are thinking of different things when you're talking about showing the exception to the user. [...] Ah, the hilarity of English ambiguity... I meant display the exception message, of course. Uncaught exceptions with stack traces in any application are Very Bad(tm). T -- Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -- Brian W. Kernighan
Re: Possible @property compromise
As interface api good practice is usage virtual public functions of classes. So, (virtual) properties add an additional usefulness.
Re: Possible @property compromise
On Wednesday, 30 January 2013 at 21:07:56 UTC, TommiT wrote: The problem is that genie is out of the bottle once you have committed yourself to an interface where there is a public member variable. And you can't put the genie back in the bottle any more. This means that your interface can't add any encapsulation over this public member variable afterwards without changing the interface. A bit more code, a bit less metaphors: struct S { T data; } // end-user code: S s; *s.data = 42; End-user thus by-passes any encapsulation that could be possible added over S.data field later on, like the following: struct S { private T _data; @property ref T data() { return _data; } @property ref T data(int v) { assert(v != 42); _data = v; return _data; } }
Re: Possible @property compromise
On 01/30/2013 09:10 AM, Jacob Carlborg wrote: On 2013-01-30 02:40, TommiT wrote: I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming? I really don't see much point in properties/methods that just forwards to an instance variable. Me either. I mean yes, for anything that is part of a public api you should probably double check everything. But insisting on getters and setters regardless of the requirements of what you are getting and setting? Sounds like an excuse to not think, to me.
Re: Possible @property compromise
On Wednesday, January 30, 2013 15:26:32 1100110 wrote: On 01/30/2013 09:10 AM, Jacob Carlborg wrote: On 2013-01-30 02:40, TommiT wrote: I always thought that having public member variables is a bad style of programming because of the lack of encapsulation. So, if there's a language feature that enables you to write public member variables, and later on, replace them with property functions, wouldn't that mean that the language is encouraging this particular kind of bad style of programming? I really don't see much point in properties/methods that just forwards to an instance variable. Me either. I mean yes, for anything that is part of a public api you should probably double check everything. But insisting on getters and setters regardless of the requirements of what you are getting and setting? Sounds like an excuse to not think, to me. The main reason for it is that you can add additional code later when it no longer needs to just get or set the variable. But one of the goals of properties is to make it so that you can just make it a public variable to begin with and then swap it out with a property function later when you need to add code like that. However, that never quite seems to work perfectly, as there's always something that you can do with a variable that you can't do with a property function (e.g. take its address or pass it by ref). Without properties though, you definitely want the getters and setters so that you don't lock yourself out of being able to properly protect the variable when you actually need to later. - Jonathan m Davis
Re: Possible @property compromise
On Wednesday, 30 January 2013 at 21:26:34 UTC, 1100110 wrote: Me either. I mean yes, for anything that is part of a public api you should probably double check everything. But insisting on getters and setters regardless of the requirements of what you are getting and setting? Sounds like an excuse to not think, to me. Putting in public variables sounds like not thinking, to me. Interface should expose the minimum amount of access possible, whereas public variables expose the maximum amount of access.
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 18:36:17 UTC, Dmitry Olshansky wrote: I have one key problem - the hidden pointer detail. In other words how should it find the instance of the outer struct to to access it? struct A{ int a; struct B{ void foo(){ a = 42; } } B b; } A a; a.b.foo(); //how that b is supposed to know it's outer struct without the hidden pointer? auto x = a.b; x.foo();// and now what? It seems struct B does need a pointer... and yet it only needs it in compile time. auto x = a.b is no different from alias a.b x, because when you have no data, you have no data to worry about! a.b is nothing but a namespace with full struct semantics. I can only say that my intuition tells me that this is easily managed. I cannot tell you what adjustments need to be made to the compiler to get this to come out right. But what if B actually had some data? The only solution is to have one pointer for every struct it's nested inside of. I can imagine it getting tricky in this case. If it were so tricky as to be prohibitive to implement, then all is not lost. You can still implement zero-data structs as properties. In that case, I suggest weaving the implementation in directly with the Highlanders, because Highlanders will be much less appealing for any other use.
Re: Throwable class design
On Wednesday, 30 January 2013 at 21:07:41 UTC, Jonathan M Davis wrote: On Wednesday, January 30, 2013 12:40:26 H. S. Teoh wrote: On Wed, Jan 30, 2013 at 09:03:31PM +0100, rumbu wrote: Ok, maybe my thoughts are polluted by some C# programming practices, but I learnt that exceptions are never intended for the end user (one of the reasons is that the exception mesages are in most cases displayed in english language). In Windows world, throwing an exception displays a message with a nice two buttons: Close and Debug. This will make the accountant using my software very eager to click on Debug :) Maybe that is accepted convention in the Windows world, but I consider exceptions as an excellent way of conveying what went wrong to the user. Such as could not calculate cell value, expecting number in cell A5 but got 'adfsdfas' instead. Throwing an exception is the cleanest way to abort potentially deeply-nested calculation code and give the user a useful message in the meantime. I would hate to manually propagate such user errors by hand, just because of the convention that exception messages should never be seen by the user! I would never show an exception to a user, even in Linux. I might show the exception's message, but I would never let the exception escape and end up showing the stack trace and whatnot to the user. I see no problem in showing an exception's message to a user if that's what it was intended for. The fact that it was an exception which delivered the message is an implementation detail that the user doesn't care about and shouldn't know. But I suspect that the two of you pretty much agree about that but are thinking of different things when you're talking about showing the exception to the user. - Jonathan M Davis I would much rather show a stacktrace to the user than Unknown error or some other little usable message. When a user copy/paste a stacktrace for a hard-to-reproduce problem, it's a *lot* simpler to fix the error or give a custom error message.
Re: New std.process?
On Saturday, 20 October 2012 at 18:17:31 UTC, Alex Rønne Petersen wrote: It's time for the periodic new std.process ping. ;) Seriously, though, what's the state of it? Can we get it into the review queue soon? It would be great to have it in 2.060. I just created a small script using std.process, and the *pain*.. Took a look at the new std.process which easily lets you spawn a process using custom stdin/out/err, get the result etc.etc.. Looks a lot better than what we currently have. Unfortunately, it needs some druntime changes, so I couldn't just plug it in without building dmd myself. So.. Ping? :) Inclusion in 2.062?
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 19:44:43 UTC, TommiT wrote: On Wednesday, 30 January 2013 at 18:05:08 UTC, Zach the Mystic wrote: [..] How about using this new namespace_thingy keyword: struct S { private int value; namespace_thingy prop { int get() { return value; } prop opAssign(int v) { value = v; return prop; } // int data; // error: can't have data here } } The compiler would implicitly create something like: struct S { private int value; int prop_get() { return value; } int prop_opAssign(int v) { value = v; return prop_get(); } } ... S s; int v1 = s.prop;// lowered to s.prop_get() int v2 = (s.prop = v1); // lowered to s.prop_opAssign(v1) assert(v1 == v2); I think you're thinking along the right lines, but this is no better than what's already been suggested. From everything I've read, reusing old keywords to do new things in new places is a time-honored D tradition, and adding new ones is very much frowned upon. Also, because the namespace_thingys have so much in common with structs, I think it would be misleading to call them something else. The lowering you're talking about already happens, in its own way, with the operator overloads. In fact, these overloads were designed *specifically* to allow struct and class instances to meld in seamlessly with built-in types. Just look at Walter's recent article for half floats. The whole article demonstrates D's ability to do exactly what everybody is trying to get their properties to do. Now we just have to get rid of the performance overhead by treating structs with no data as namespaces instead of the more commonly held perception that they are only supposed to work on their own data! Hurrah!
Re: Property discussion wrap-up
On Wednesday, 30 January 2013 at 21:41:58 UTC, Zach the Mystic wrote: But what if B actually had some data? The only solution is to have one pointer for every struct it's nested inside of. I can imagine it getting tricky in this case. If it were so tricky as to be prohibitive to implement, then all is not lost. You can still implement zero-data structs as properties. In that case, I suggest weaving the implementation in directly with the Highlanders, because Highlanders will be much less appealing for any other use. I should correct myself, I think. You need one pointer for every struct nested which actually holds data. And I take back the connection between Highlanders and zero-data structs. The other possible use for Highlanders which I was thinking of is for quick prototyping, since foo struct {} is much easier to type than struct Foo {}; Foo foo;. I see no real problem with these even if non-static, non-zero-data nested structs are not allowed access to their parent structs.
Re: Regarding Issue 9423
Maxim Fomin: By the way, recently problem with functions taking by ref and returning passed ref was discussed and was considered to be a @safity hole. If your proposal is accepted, issue with ref and @safe may be needed to be taken into account in application to your proposal. I see. I am willing to close down that request 9423, if you want, it's not important. Bye, bearophile
Re: convert class of in pascal to D.
Am 30.01.2013 20:11, schrieb dennis luehring: Am 30.01.2013 19:58, schrieb Paulo Pinto: Am 30.01.2013 18:18, schrieb dennis luehring: in real OOP objects are specialized through its virtual method implementations AND its ctor-parameters (which are similar in very very few rare cases) for example pseudo code class Stream virtual read_bytes()... class FileStream: Stream this(filename) class NetworkStream: Stream this(tcp_ip,timeout) Stream[] streams streams ~= FileStream(c:/temp/test.txt); streams ~= NetworkStream(123.112.2.1, 1000); stream[n].read_bytes() this is a much more common OOP/ctor situation then yours i think its part of pascal/object delphi to ease the VCL development but this can be easily reached with an internal CreateInstance routine like Stream virtual Stream CreateInstance() and FileStream implements CreateInstance() with with return new FileStream NetworkStream with new NetworkStream etc. so whats the realy big deal/feature of this class of-type except for very trivial OOP case Actually there are many definitions what real OOP means. As for Delphi's case, if I am not mistaken it tries to follow the metaclass concept that Smalltalk has, and Java/.NET have to a certain extent. no there aren't many definitions but many many missuse of the concept Well, Smalltalk, Simula, C++/Java/C#, OCaml, CLOS, JavaScript, BETA, Modula-3, Eiffel, Ada, Sather, and many others. All have different concepts what OO should really be. Enough material to write a few OOPSLA papers I would say. you interface is the adaptor, your virtual method code is the special behavior, your ctors parameters are the intialisers of the special behavior - everything else is just a pseudo-procedural style - its not OOP if you need to use casts and ifs on your object-type, thats procedural programming with class-based fake-namespaces There I agree with you. Casts should only be a kind of last resort and are mostly a sign of bad design. can you give me a small example of the metaclass concept of smalltalk - related to my simple stream example? Your simple example was correct, as this is not the use case of metaclasses. Maybe my post was a bit off topic. In case you are not familiar with the concept, in Smalltalk everything is an object. Every object is of course represented by a class description and you create instances of the said classes. Additionally each class also has a class that represents it. In a simple description it allows to manipulate the set of methods, instances and other information that represents the real class. It is also the container for what is known as static methods/variables in other languages. However, given Smalltalk's dynamic behavior, you can on the fly change a class's metaclass and with it simulate multiple inheritance, method call delegation or other tricks. If I am not mistaken, Objective-C and Ruby allow similar tricks, given their Smalltalk influence. -- Paulo