Re: Another SQLite3 wrapper
Thanks for the reply, Russel! Ok, I'll add unit tests and some example. As for support for other databases, it's complex enough task to design good common database layer, while I currently need only SQLite. Apart from that, there are very few types in SQLite, and these tipes map into D's intenal types very well. To support other databases I need to do something with all those DateTime, Timestamp, Decimal... Usually I don't use them, so do not have any experience with them and fardly can correctly design work with them/ I still can build basic common logic and add support to MySQL (at least I know it and use sometimes), but I'm pretty new to D and want to receive better feel of a language before trying to design some generic database-access library. Also, generic APIs tend to be more verbose than I like, and I never seen in practise easy switch from one database to another - eiher you need to rewrite all your SQL or you use ORM and lose 3/4 of speed... I don't know Groovy, but in examples I found something interesting. Besides variable expansion (I don't understend how to implement it in D) I see something that can be done. Using standart interface for iterating dataset - it can be interesting to allow algorithms run on datasets, and I can implement forward iterator easily. But access to values (types of values are unknown in compile-time) will be tricky. My be, I'll convert all values into strings for this type of interface. Support for name-based arguments. I like it, but I'm thinking on interface now. There is some ideas: - use associative array approach like st.bind([id:1, name:Alex Khmara] - but this will limit argument types to be string, and I will need to conver them automatically when doing biding. - another aproach would be do someting like st.bind(id,1).(name.Alex Khmara), but it's ugly for me. - may be preferred way - use tuples, like (st.bindNamed([id: 1] [name: Alex Khmara]). With first case we are able to fill array with some cycles, and with other two variants we cannot, but first case limits us to common type for all arguments - i.e. string. So I'm thinking on this. May be I need to start use library-based tuples for all this machinery... I definitely do not plan to add anything with automatic SQL generation - I don't seen any that is easy and fast, but may be it would be good to support some compile-time generation of datasets with felds of known type. D wold be good in this field. I'll will think on it. 2010/11/16 Russel Winder rus...@russel.org.uk: Alexey, On Tue, 2010-11-16 at 01:14 +, Alexey Khmara wrote: Hello! I tried to find any module to work with SQLite3 in D2, and failed. I found either just bindings to old SQLite versions or D1 modules with craft-SQL-on-the-fly interface, all abandoned. So I want to add just another D2 SQLite3 bindings and OO-wrapper and uploaded to GitHub: https://github.com/bayun/SQLite3-D I cloned the repository which gets the sqlite.d file but there seems to be no unit tests, system tests or examples? Also should the API be retargetable to any SQL resource rather than just being targeted at SQLite? It seems that no-one wants to support bindings for current SQLite version.. Well, I'll try to do this. But I currently use very small subset of it's features, so it's mostly mechanical translation without further testing. My tiny OO interface supports prepare/bind style of statements, and seems to work good :-) But I'm new to D, and will be grateful to somebody who can check, if my code is correct and don't have subtle bugs. Can you put some examples of how to use your package? Reading the source tells me a lot, but not how you intend things to be used. [ . . . ] You may want to look at the way Groovy handles this sort of stuff. Most languages bind at a very low level so that people end up simply embedding SQL statements in strings, or if you are lucky template strings. Groovy adds a layer above this using the meta-object protocol features to create a very nice builder approach to interacting with the database. Basically you code up everything in Groovy code and the infrastructure handles composing the SQL and all the connections and cursors. I am about to look at Python's SQLAlchemy, Python also has other stuff for trying to raise the level. In terms of support in D, there needs to be a low level drivers I am sure, but having a way of interacting with SQLite, DB2, Oracle, even SQL Server all from the same source code would be good. -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Road m: +44 7770 465 077 xmpp: rus...@russel.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder -- С уважением, Алексей Хмара
Re: Another SQLite3 wrapper
From user side it's not hard to make it simple. Differences could be minimized, plugins added etc. I'll try to add MySQL, and if it's possible to implement common interface, I'll do it. But I'm not sure that it will be easy. 2010/11/16 Diego Cano Lagneaux d.cano.lagne...@gmail.com: [ ... ] In terms of support in D, there needs to be a low level drivers I am sure, but having a way of interacting with SQLite, DB2, Oracle, even SQL Server all from the same source code would be good. On one hand, I agree with this. It's nice to be able to easily switch the DB backend without modifying the code. On the other hand, sqlite is a very small, lighweight, external-server-less DB backend, which makes it useful for projects where other systems aren't. Sometimes I want to use sqlite in a small project, and I don't need nor want the extra complexity. I just want sqlite. This actually led me to use directly the C library instead of DDBI in a D1 small project of mine a couple of years ago. Just one .d file dropped into my project dir. So maybe, it's possible to make the DB framework use plugins, and only install the one we want; or maybe two different projects with same syntax (more convenient for the user but bound to fail in the longer term). -- С уважением, Алексей Хмара
Re: Utah Valley University teaches D (using TDPL)
bearophile Wrote: He also gives a quite useful unittest that the student implementation must pass, this is a good usage of unittests. The unit test ends like this: ... writeln(unit test passed); } Indeed, a person needs feedback that the unittests have run (and have succeed), I have used similar things in my dlbs1 (but more refined). This kind of need for feedback is so natural that something like that will be better somehow done on default by D. I'd like unit tests to be optionally named: unittest(name). The rest could then be done in library code.
Re: The D Scripting Language
On 2010-11-16 01:10, Daniel Murphy wrote: I think allowing the second expression in the ternary operator to be omitted would be a better fit for D, and provide the same function. ie. auto x = a ? a : b; auto x = a ? : b; Personally I had '|||' in mind, but I'm OK with '?:'. I think it should be one single token and not an extension of the tertiary operator, though: auto x = condition ? a : b; // tertiary operator auto x = condition ? : b; // error, did you forget the middle operand? auto x = a ?: b; // OK -- Cheers, Per Å.
Re: DDMD not update£¬why£ ¿
Why do not you update it? GDC has been updated to dmd2.049 . Why don't you contribute? It's a lot of work.
Re: forbid field name conflict in class hierarchy
On Mon, 15 Nov 2010 12:32:07 -0800 Jonathan M Davis jmdavisp...@gmx.com wrote: On Monday 15 November 2010 11:44:11 spir wrote: On Mon, 15 Nov 2010 09:45:26 -0800 Jonathan M Davis jmdavisp...@gmx.com wrote: On Monday, November 15, 2010 06:00:33 Manfred_Nowak wrote: Jonathan M Davis wrote: Having public fields shadow each other is problematic. Detecting a problem requires having a model. What does your model look like? You're going to have to be more specific in your question than that. It's not at all clear what you're asking. Public and protected functions use polymorphism. Public and protected member variables do not. So, it becomes error prone to have public or protected member variables which shadow each other. It becomes easy to end up in a situation where you're not using the one that you think that you're using - especially when code gets changed. True. There is an issue in the static model of OO, with class hierarchy: methods are dispatched, data fields are not. If there are same fields (same name type), then the one of the superclass is used. The only safe alternative would be to have runtime dispatch of fields like of methods, but this is indeed costly. (This staticity also leads to the side-effect that one cannot write generic routines which variables (from parameters or result of calls) have the superclass as declared type but also use subclass fields. To be able to do it, I end up adding subclass fields to the superclass. I know it's wrong, but haven't found the right way to do it. I don't feel like downcasting most variables in most routines.) I'm not sure that pure OO would even allow for public variables. [...] That just screams that it shouldn't be a public member variable (and truth be told, public member variables are generally considered bad practice except in simple objects - which would generally be structs in D). The issue does not require fields to be public. The same problem happens when writing methods of the class hierarchy. I do really have to wonder what you're doing though that you feel the need to access subclass fields using super class references. [...] And if you really need the subclass type, then you should be using the subclass type, not the super class type For instance a nested/recursive structure analog to a tree. There may be leaf nodes (only element), branch nodes (only subnodes), both, special ones with different kinds of values, etc... Custom routines may need to use other methods to explore a branch's children, get its leaves, filter, or whatever. All these tool methods are generic (meaning must use the top Node type), but the custom routines need to access subtype-specific fields. Thus, down-casting all the time. I find it tiresome (and bug-prone, because sometimes the absence of a fields seems not caught, for any reason), so I add fields to the top type. Also, return types are covariant, so you can return a subclass from overridden functions instead of the super class like the function which was overridden does. Maybe that would help. It would depend on what exactly you're doing though. Yes, but doesn't this mean I should override all tool methods for all subtypes, just so that I don't need to down-cast their results (in the routines that use them)? I think a better solution would be that the compiler does not prevent us to use subtype fields. Why does it do so? In the worst case, if the field does not exist, we'll get an error, anyway. - Jonathan M Davis Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: DDMD not update£¬why£¿
Am 16.11.2010 03:33, schrieb DOLIVE: Why do not you update it? GDC has been updated to dmd2.049 . please, please - learn a little bit more english all your posts are just sounding like commands
Re: forbid field name conflict in class hierarchy
spir: (and bug-prone, because sometimes the absence of a fields seems not caught, for any reason), so I add fields to the top type. What do you mean? Do you have an example? (Adding fields to the top type doesn't look like a good idea, generally). Bye, bearophile
Re: DDMD not update��why��
== Quote from dennis luehring (dl.so...@gmx.net)'s article Am 16.11.2010 03:33, schrieb DOLIVE: Why do not you update it? GDC has been updated to dmd2.049 . please, please - learn a little bit more english pour qui?
Re: The D Scripting Language
On Tue, 16 Nov 2010 09:44:06 +0100 Per Ångström d-n...@autark.se wrote: On 2010-11-16 01:10, Daniel Murphy wrote: I think allowing the second expression in the ternary operator to be omitted would be a better fit for D, and provide the same function. ie. auto x = a ? a : b; auto x = a ? : b; Personally I had '|||' in mind, but I'm OK with '?:'. I think it should be one single token and not an extension of the tertiary operator, though: auto x = condition ? a : b; // tertiary operator auto x = condition ? : b; // error, did you forget the middle operand? auto x = a ?: b; // OK Yes, then it becomes a binary operator :-) Read a if defined, else b. Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: DDMD not update£¬why£¿
dennis luehring дµ½: Am 16.11.2010 03:33, schrieb DOLIVE: Why do not you update it? GDC has been updated to dmd2.049 . please, please - learn a little bit more english all your posts are just sounding like commands haha... : )
Re: DDMD not update£¬why£¿
dennis luehring дµ½: Am 16.11.2010 03:33, schrieb DOLIVE: Why do not you update it? GDC has been updated to dmd2.049 . please, please - learn a little bit more english all your posts are just sounding like commands haha... sory ! : )
Re: forbid field name conflict in class hierarchy
On Tue, 16 Nov 2010 05:37:52 -0500 bearophile bearophileh...@lycos.com wrote: spir: (and bug-prone, because sometimes the absence of a fields seems not caught, for any reason), so I add fields to the top type. What do you mean? Do you have an example? (Adding fields to the top type doesn't look like a good idea, generally). Bye, bearophile For instance, I have 2 sub-classes of nodes: one leaf kind with element (here called slice), one branch kind with an array of (child) nodes. They are exclusive, and none of the data fields should appear on the top Node type. But everywhere the Node class must be used, since a branch (as the top tree) can indifferently hold leaves or sub-branches, right? Each time I need to post-process results, since I apparently get Nodes (even if I know they are actually of one or the other type), I would first have to down-cast each node to the proper kind before doing anything. Else, I would get compiler errors, or plain bugs, for not having the proper field. So, I ended up setting fake fields on Node (and remove them from the sub-classes). And yes, I agree it's A Bad Thing to do. Just tell me of an elegant solution, and I apply it at once. Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: forbid field name conflict in class hierarchy
On Tue, 16 Nov 2010 05:37:52 -0500 bearophile bearophileh...@lycos.com wrote: spir: (and bug-prone, because sometimes the absence of a fields seems not caught, for any reason), so I add fields to the top type. What do you mean? Do you have an example? (Adding fields to the top type doesn't look like a good idea, generally). Bye, bearophile PS: And I guess clients of the lib face the same issues. denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: RFC, ensureHeaped
On Mon, 15 Nov 2010 17:02:27 -0500, bearophile bearophileh...@lycos.com wrote: Steven Schveighoffer: To have the language continually working against that goal is going to great for inexperienced programmers but hell for people trying to squeeze performance out of it. The experienced programmers may write scope int[] a..., and have no heap allocations. This is a good idea. This isn't what I thought spir was saying, I thought he wanted the function to always allocate. At first glance, I thought your idea might be bad, because duping an array decouples it from the original, but then I realized -- there *is* no original. This is the only reference to that data, so you can't change any expectations. The only issue I see here is that scope should really be the default, because that is what you want most of the time. However, the compiler cannot prove that the data doesn't escape so it can't really enforce that as the default. I have the same issue with closures (the compiler is too eager to allocate closures because it is too conservative). But I don't know how this can be fixed without redesigning the compilation model. I think what we need however, is a way to specify intentions inside the function. If you intend to escape this data, then the runtime/compiler should make it easy to avoid re-duping something. This is like for the automatic closures. The right design in a modern language is to use the safer strategy on default, and the less safe on request. This is not always possible, I still see a good need for ensuring heaped data. For example: int[] y; foo(int[] x...) { y = ensureHeaped(x); } bar(int[] x) { foo(x); } baz() { int[3] x; bar(x); } I believe the compiler cannot really be made to enforce that all passed-in data will be heap-allocated when passed to foo. A runtime check would be a very good safety net. If you want, a new compiler switch may be added that lists all the spots in the code where a closure or hidden heap allocation occurs, useful for performance tuning (an idea by Denis Koroskin): http://d.puremagic.com/issues/show_bug.cgi?id=5070 Also a good idea. I have even suggested a transitive @noheap annotation, similar to @nothrow, that makes sure a function contains no heap allocations and doesn't call other things that perform heap allocations: http://d.puremagic.com/issues/show_bug.cgi?id=5219 The proliferation of function attributes produces interesting results: @noheap @safe nothrow pure real sin(in real x) { ... } This is a bit much. Introducing these attributes is viral -- once you go @noheap, anything you call must be @noheap, and the majority of functions will need to be marked @noheap. The gain is marginal at best anyways. To be fair, it was easy to spot when you gave us the pertinent code :) I didn't even know/remember that that array data is on the stack. That error will give bad surprises to some D newbies that are not fluent in C. I didn't know until about a month and a half ago (in dcollections, this bug was prominent in all the array-based classes). Only after inspecting the disassembly did I realize. I agree we need some sort of protection or alert for this -- it's too simple to make this mistake. -Steve
Re: forbid field name conflict in class hierarchy
On 16.11.2010 14:40, spir wrote: On Tue, 16 Nov 2010 05:37:52 -0500 bearophilebearophileh...@lycos.com wrote: spir: (and bug-prone, because sometimes the absence of a fields seems not caught, for any reason), so I add fields to the top type. What do you mean? Do you have an example? (Adding fields to the top type doesn't look like a good idea, generally). Bye, bearophile For instance, I have 2 sub-classes of nodes: one leaf kind with element (here called slice), one branch kind with an array of (child) nodes. They are exclusive, and none of the data fields should appear on the top Node type. But everywhere the Node class must be used, since a branch (as the top tree) can indifferently hold leaves or sub-branches, right? Each time I need to post-process results, since I apparently get Nodes (even if I know they are actually of one or the other type), I would first have to down-cast each node to the proper kind before doing anything. Else, I would get compiler errors, or plain bugs, for not having the proper field. So, I ended up setting fake fields on Node (and remove them from the sub-classes). And yes, I agree it's A Bad Thing to do. Just tell me of an elegant solution, and I apply it at once. Looks like a good question for D.learn. That's what opApply is made for. Namely: internal iteration. Idea - basically what you need is apply some block of code (delegate) on each element. If you provide in your node-like classes function opApply with signature: int opApply(int delegate(ref A)); //where A is your data-type foreach(a; node){ writeln(a);//here a is element of data not Node or some such } Is rewritten as node.opApply((ref a){ writeln(a); return 0;}); compiler rewrites code with breaks and so on to return 1, while at the normal end of flow to return 0 To get that idea better, try this example program import std.stdio; class Node{ abstract int opApply(int delegate(ref int)); } class Leaf: Node{ this(int _data){ data = _data; } int data; int opApply(int delegate(ref int) dg){ return dg(data); } } class Branch: Node{ Node[] nodes; this(Node[] _nodes...){ nodes = _nodes.dup; } int opApply(int delegate (ref int) dg){ Node[] n = nodes; while(n.length){ int result = n[0].opApply(dg); if(result) return result; ///to handle breaks n = n[1..$]; } return 0; } } void main(){ Branch b = new Branch(new Leaf(17), new Leaf(19)); Node n = new Branch(new Leaf(10),new Leaf(20),b); foreach(val;n){ if(val == 17)//try playing around with break break; writeln(val); } } Also check the section 12.10 in TDPL if you have one, it goes in great detail about it. Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com -- Dmitry Olshansky
Re: The D Scripting Language
Daniel Murphy, el 16 de noviembre a las 10:10 me escribiste: Per �ngstr�m d-n...@autark.se wrote in message news:ibr8bs$22m...@digitalmars.com... return s || default; I think allowing the second expression in the ternary operator to be omitted would be a better fit for D, and provide the same function. ie. auto x = a ? a : b; auto x = a ? : b; I think bearophile might have already proposed this? Yes, the elvis operator ?: -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- Sometimes I think the sure sign that life exists elsewhere in the universe Is that that none of them tried to contact us
Re: Type-safe channels (Re: One year of Go)
Graham Fawcett Wrote: On Fri, 12 Nov 2010 18:15:15 -0500, Sean Kelly wrote: To be honest, I haven't spent much time with Go because my cursory exposure to the language hasn't shown it to solve the problems I care about better than the languages I currently use. I think Go is in the right ballpark with channels though, and the rest is passable. I'm trying to withhold my opinion about the lack of generics and such and evaluate the language based on what's there. Since you brought up channels... One thing I very much like about Go (and Haskell, etc.) that I don't think has a counterpart in Phobos is type-safe message passing. I like the flexibility of the current mailbox design. But I'd really like an alternative that could enforce type-safety on messages. I don't think per-thread mailboxes could accommodate this, but Channel objects could; e.g.: struct Channel(T) { T receive() { ... } void send(T val) { ... } } It shouldn't be too difficult to wrap send/receive with such a design to provide type safety. In fact, it's one reason I wanted to use the flexible model. Of course, using channels would be a matter of convention, since both would be available. (I am guessing that tricks might have to be played to pass Channel objects around as pure values across threads, but I'm also guessing this is surmountable...) It should be possible to pass shared classes as well. If the Channel is non-shared then you'll have to do some casting in the implementation for send/receive to allow it though.
Re: Compiler optimization breaks multi-threaded code
Kagamin s...@here.lot wrote: Sean Kelly Wrote: shared uint cnt; void atomicInc ( ) { uint o; while ( !cas( cnt, o, o + 1 ) ) o = cnt; } is compiled with dmd -O to something like: shared uint cnt; void atomicInc ( ) { while ( !cas( cnt, cnt, cnt + 1 ) ) { } } What a mess. DMD isn't supposed to optimize across asm blocks. There're no asm blocks in the code. It's a violated contract of shared data access. cas() contains an asm block. Though I guess in this case the compiler isn't actually optimizing across it. Does atomic!+=(cnt, 1) work correctly? I know the issue with shared would still have to be fixed, but that code uses asm for the load as well, so it probably won't be optimized the same way.
std.algorithm.remove using SwapStrategy.unstable doesn't works
I'm trying to use remove() from std.algorithm to remove item from an array and when I tried to use SwapStrategy.unstable (as I don't need to maintain order of items in array and I want to optimize where ever I can) I came to surprising results. In the example below one would expect that item at index 2 (number 3 in example) will be removed but instead item at index 0 is removed from array. Is this a bug or I'm missing a point? - import std.stdio, std.algorithm; void main(string[] args) { auto a = [1,2,3,4]; foreach (e; a) writef(%s , e); writefln((%s), a.length); // 1 2 3 4 (4) auto i = a.indexOf(3); writefln(%s, i); // 2 if (i -1) { a = remove!(SwapStrategy.unstable)(a, i); } foreach (e; a) writef(%s , e); writefln((%s), a.length); // 4 2 3 (3) !?! } - thx in advance, Aleksandar
Re: The D Scripting Language
Script mode (actually - simple wrapper) would be better: It could do simple parsing of script, bringing all import clauses to the beginning and add some default imports (like std.stdio). It seems that all code below imports can be wrapped into main declaration. So for writeln(hello, world!); we get import std.stdio; int main(char[] argv) { writeln(hello, world!); return 0; } Trick will be to intercept error messages and change line numbers in them to correct. 2010/11/16 gooba go...@digitalmars.com: spir Wrote: On Tue, 16 Nov 2010 09:44:06 +0100 Per Ångström d-n...@autark.se wrote: On 2010-11-16 01:10, Daniel Murphy wrote: I think allowing the second expression in the ternary operator to be omitted would be a better fit for D, and provide the same function. ie. auto x = a ? a : b; auto x = a ? : b; Personally I had '|||' in mind, but I'm OK with '?:'. I think it should be one single token and not an extension of the tertiary operator, though: auto x = condition ? a : b; // tertiary operator auto x = condition ? : b; // error, did you forget the middle operand? auto x = a ?: b; // OK Yes, then it becomes a binary operator :-) Read a if defined, else b. Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com They now added Scala to scriptometer http://rigaux.org/language-study/scripting-language/ it sees abomination i/o classes don't stop it being better script language then d. What can do? Scala bad competition and straight better. Next release has std.script? -- С уважением, Алексей Хмара
modulus and array.length
Hi, I've noticed that the modulus operator acts differently when the divisor is the length of an array and the dividend is negative. For instance, this code: import std.stdio; const int x = 4; void main(){ int[x] arr = [0, 1, 2, 3]; writeln(Using arr.length); for(int i = -3; i = 0; i++){ writefln(%d mod %d = %d, i, arr.length, i % arr.length); } writeln(Using x); for(int i = -3; i = 0; i++){ writefln(%d mod %d = %d, i, x, i % x); } } Produces this output: Using arr.length -3 mod 4 = 1 -2 mod 4 = 2 -1 mod 4 = 3 0 mod 4 = 0 Using x -3 mod 4 = -3 -2 mod 4 = -2 -1 mod 4 = -1 0 mod 4 = 0 Which is a useful (but undocumented?) feature that lets you loop through arrays backwards. However, when the length of the array is odd... const int x = 3; ... int[x] arr = [0, 1, 2]; It looks like this: Using arr.length -3 mod 3 = 1 -- this should be 0 -2 mod 3 = 2 -- this should be 1 -1 mod 3 = 0 -- this should be 2 0 mod 3 = 0 Using x -3 mod 3 = 0 -2 mod 3 = -2 -1 mod 3 = -1 0 mod 3 = 0 Does anyone know of a reason for this? It doesn't seem like a bug, but I don't know why it would do something like that. Upon further investigation, I found that when arr.length is even, i acts like (x*(abs(i)/x + 1) + i) , and when arr.length is odd, i acts like (x*(abs(i)/x - 1) + i) (I'm using dmd 2.049 on linux) ~Dave
assert(false) with -unittest
Hi, assert(false) should generate the hlt instruction in release mode. I.e. assert.d: void hlt() { assert(false); } $ dmd -release -c assert.d $ obj2asm assert.o | grep -w hlt works. But $ dmd -unittest -release -c assert.d $ obj2asm assert.o | grep -w hlt fails. Can't one have hlt together with unittest? Is it a bug in the compiler or correct behavior? Jens
Re: The D Scripting Language
Script mode (actually - simple wrapper) would be better: It could do simple parsing of script, bringing all import clauses to the beginning and add some default imports (like std.stdio). It seems that all code below imports can be wrapped into main declaration. My rund.d program does this. http://arsdnet.net/dcode/rund.d As you can see, it's a trivial program.
DMD Automatic Dependency Linking
DMD currently follows a fairly standard compiler methodology: - Compile a bunch of source files into binary objects (to generate .o). - Act as a front end to an archiver (to generate .a). - Act as a front end to a linker (to generate final binary). This makes integration with most build systems and IDEs not only possible, but in most cases reasonably trivial. The one thing I have been wondering however is why doesn't DMD have a flag for easy project building which compiles dependencies in a single command. DMD already can generate a recursive list of module dependencies (-deps=), why not go one step towards a full build system and have it build those dependencies (and check timestamps). This could create behaviours similar to that of simple dsss/rebuild/bud/xfBuild configuration but keep up to date with the DMD syntax. The behaviour I am thinking/suggesting for the '-R' flag (recursive) is: - Generate dependency tree of each .d file provided on the command line - If -o- is provided on the command line, treat each dependant .d file in the dependency tree as if it was provided on the command line. - If -o- is not provided on the command line only compile the .d files that are newer than the .o files. - Link/Archive the resulting .o files. Adding in pragma('link', 'foo') would also be really nice to add in as well for this sort of system. Even better would be some way of passing command line arguments to dmd via a pragma such as pragma('cmd', '-Jfoo') which would add a string imports path relative to the file being compiled. I think this sort of feature would allow alot of newcomers to D to get writing modular code faster without learning build systems and all of the crap associated cross platform issues. I don't know the dmd internals well enough to implement it myself, but I'd love to hear Walter's or Andrei's input on a feature like this. From what I do know about dmd's current functionality, it seems like it would be a fairly easy feature to implement. Thanks, tbone
Re: assert(false) with -unittest
== Quote from Jens Mueller (jens.k.muel...@gmx.de)'s article Hi, assert(false) should generate the hlt instruction in release mode. I.e. assert.d: void hlt() { assert(false); } $ dmd -release -c assert.d $ obj2asm assert.o | grep -w hlt works. But $ dmd -unittest -release -c assert.d $ obj2asm assert.o | grep -w hlt fails. Can't one have hlt together with unittest? Is it a bug in the compiler or correct behavior? Jens I think this is correct. The -unittest switch implicitly turns on asserts, and as far as I can tell makes the -release switch ignored. This means that assert(false) is no longer special and works just like a regular assert as per TDPL. Is this a problem in practice? If so, please explain.
Re: assert(false) with -unittest
dsimcha wrote: == Quote from Jens Mueller (jens.k.muel...@gmx.de)'s article Hi, assert(false) should generate the hlt instruction in release mode. I.e. assert.d: void hlt() { assert(false); } $ dmd -release -c assert.d $ obj2asm assert.o | grep -w hlt works. But $ dmd -unittest -release -c assert.d $ obj2asm assert.o | grep -w hlt fails. Can't one have hlt together with unittest? Is it a bug in the compiler or correct behavior? Jens I think this is correct. The -unittest switch implicitly turns on asserts, and as far as I can tell makes the -release switch ignored. This means that assert(false) is no longer special and works just like a regular assert as per TDPL. I see. Is this a problem in practice? If so, please explain. Haven't thought about it. Found this by accident. Jens
Re: modulus and array.length
Hi, I've noticed that the modulus operator acts differently when the divisor is the length of an array and the dividend is negative. For instance, this code: import std.stdio; const int x = 4; void main(){ int[x] arr = [0, 1, 2, 3]; writeln(Using arr.length); for(int i = -3; i = 0; i++){ writefln(%d mod %d = %d, i, arr.length, i % arr.length); } writeln(Using x); for(int i = -3; i = 0; i++){ writefln(%d mod %d = %d, i, x, i % x); } } Produces this output: Using arr.length -3 mod 4 = 1 -2 mod 4 = 2 -1 mod 4 = 3 0 mod 4 = 0 Using x -3 mod 4 = -3 -2 mod 4 = -2 -1 mod 4 = -1 0 mod 4 = 0 Which is a useful (but undocumented?) feature that lets you loop through arrays backwards. arr.length is type size_t. size_t length = 4; writeln(Using size_t); for(int i = -3; i = 0; i++){ writefln(%d mod %d = %d, i, length, i % length); } So it's due to the size_t. Because it's unsigned. However, when the length of the array is odd... const int x = 3; ... int[x] arr = [0, 1, 2]; It looks like this: Using arr.length -3 mod 3 = 1 -- this should be 0 -2 mod 3 = 2 -- this should be 1 -1 mod 3 = 0 -- this should be 2 0 mod 3 = 0 Using x -3 mod 3 = 0 -2 mod 3 = -2 -1 mod 3 = -1 0 mod 3 = 0 Does anyone know of a reason for this? It doesn't seem like a bug, but I don't know why it would do something like that. Here I have no idea. Jens
Re: RFC, ensureHeaped
Steven Schveighoffer: The experienced programmers may write scope int[] a..., and have no heap allocations. This is a good idea. This isn't what I thought spir was saying, I thought he wanted the function to always allocate. I have also suggested that when scope is not present, DMD may automatically add a runtime test similar to the one done by ensureHeaped and dup the array data only if it's on the stack. So even when you don't use scope it doesn't always copy. The only issue I see here is that scope should really be the default, because that is what you want most of the time. If the variadics is in the signature of a free function then I agree with you. But if it's inside the this() of a class, then often you want that data on the heap. However, the compiler cannot prove that the data doesn't escape so it can't really enforce that as the default. If you look at my original answer I have suggested something like @heaped, that's attached to an array and makes sure its data is on the heap. This is done with a mix (when possible) of static analysis and runtime tests (in the other cases). But I have not added this idea to the enhancement request of scoped variadics because it looks too much hard to implement in D/DMD. I believe the compiler cannot really be made to enforce that all passed-in data will be heap-allocated when passed to foo. A runtime check would be a very good safety net. Static analysis is able to do this and more, but it requires some logic added to the compiler (and such logic probably doesn't work in all cases). I have even suggested a transitive @noheap annotation, similar to @nothrow, that makes sure a function contains no heap allocations and doesn't call other things that perform heap allocations: http://d.puremagic.com/issues/show_bug.cgi?id=5219 The proliferation of function attributes produces interesting results: @noheap @safe nothrow pure real sin(in real x) { ... } This is a bit much. Introducing these attributes is viral -- once you go @noheap, anything you call must be @noheap, and the majority of functions will need to be marked @noheap. The gain is marginal at best anyways. Indeed, it's a lot, and I am not sure it's a good idea. I have had this idea reading one or two articles written by people that write high performance games in C++. They need to keep the frame rate constantly higher than a minimum, like 30/s or 60/s. To do this they have to avoid C heap allocations inside certain large loops (D GC heap allocations may be even worse). Using @noheap is a burden, but it may help you write code with a more deterministic performance. Maybe someday it will be possible to implement @noheap with user-defined attributes plus static reflection, in D. But then the standard library will not use that user-defined @noheap attribute, making it not so useful. So if you want it to be transitive, Phobos needs to be aware of it. Bye, bearophile
Re: RFC, ensureHeaped
On 11/16/10 4:40 AM, Steven Schveighoffer wrote: On Mon, 15 Nov 2010 17:02:27 -0500, bearophile bearophileh...@lycos.com wrote: I have even suggested a transitive @noheap annotation, similar to @nothrow, that makes sure a function contains no heap allocations and doesn't call other things that perform heap allocations: http://d.puremagic.com/issues/show_bug.cgi?id=5219 The proliferation of function attributes produces interesting results: @noheap @safe nothrow pure real sin(in real x) { ... } This is a bit much. Introducing these attributes is viral -- once you go @noheap, anything you call must be @noheap, and the majority of functions will need to be marked @noheap. The gain is marginal at best anyways. Hm, interestingly a data qualifier @noheap would not need to be transitive as data on the stack may refer to data on the heap. Andrei
Re: std.algorithm.remove using SwapStrategy.unstable doesn't works
On 11/16/10 4:24 AM, Aleksandar Ružičić wrote: I'm trying to use remove() from std.algorithm to remove item from an array and when I tried to use SwapStrategy.unstable (as I don't need to maintain order of items in array and I want to optimize where ever I can) I came to surprising results. In the example below one would expect that item at index 2 (number 3 in example) will be removed but instead item at index 0 is removed from array. Is this a bug or I'm missing a point? - import std.stdio, std.algorithm; void main(string[] args) { auto a = [1,2,3,4]; foreach (e; a) writef(%s , e); writefln((%s), a.length); // 1 2 3 4 (4) auto i = a.indexOf(3); writefln(%s, i);// 2 if (i -1) { a = remove!(SwapStrategy.unstable)(a, i); } foreach (e; a) writef(%s , e); writefln((%s), a.length); // 4 2 3 (3) !?! } - thx in advance, Aleksandar Looks like a bug. Could you please file it to bugzilla? Thanks, Andrei
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
Andrei Alexandrescu Wrote: I am sorry for the inadvertent change, it wasn't meant to change semantics of existing code. I'm not sure whether one of my unrelated 64-bit changes messed things up. You may want to file a bug report. There are a number of good reasons for which I was compelled to split std.regex from std.regexp. I'm sure you or others would have found them just as compelling if you saw things the same way. Phobos 1 has experimented in std.string and std.regexp with juxtaposing APIs of various languages (PHP, Ruby, Python). The reasoning was that people familiar with either of those languages could feel right at home by using APIs with similar nomenclatures and semantics. The result was some strange bedfellows in std.string such as column or capwords and an outright mess in std.regexp. The interface of std.regexp is without a doubt the worst I've ever seen, by a long shot. I have never been able to use it without poring through the documentation _several times_ and without confirming to myself via a small test case that I'm doing the right thing. The simplest problem is this: std.regexp uses the words exec, find, match, search, and test - all to mean regular expression matching. There is absolutely no logic to how meanings are ascribed to words, and there is absolutely no recourse than rote memorization of various arbitrary decisions. The resulting FrankenAPI is likely familiar to anyone except those who've actually spent time learning it, in spite of it trying to be familiar to anyone. So I spawned std.regex in an attempt to sanitize the API (I made minor, if any, changes to the engine; I am in fact having significant trouble maintaining it). The advantages of std.regex are: * No more class definition. Nobody is supposed to inherit RegExp anyway so it's useless to brand the object as a class. * Engine is separated from matches, which means that engines can be memoized for efficiency. Currently regex() only memoizes the last engine. * The new engine works with any character size. * Simpler API: create a regex, call match() against that regex and a string, look at the resulting RegexMatch object. If this all annoys you more than the old API, I will need to disagree. If you have suggestions on how std.regex can be improved, I'm all ears. Andrei Andrei, Maybe it is time that the structure of the standard library became more generalized. At the moment we have std... and core... Perhaps we need another branch in the hierarchy, like ranges... Then there could be a std.range module that was the gateway into ranges... The library could then expand in an orderly fashion, with a wider range of users becoming responsible for the maintenance of of different branches against changes in the language, not against changes in fashion. Then you could have ranges.regex, that suits you, and the people who were happy with the status quo, could continue to use std.regexp, which should continue to behave like it did in DMD2.029 or whatever it was when I wrote my 'legacy' code. The current system, where modules of the library can get arbitrarily deprecated and at some point removed because they are unfashionable, is very unfriendly. I recognize that you are young, hyper-intelligent, and motivated toward fame. But there are other users, like me, who are older, but not senile, and have more conservative attitudes, including the desire to use code they wrote in the past at some point in the future. Steve
Re: modulus and array.length
On Tue, 16 Nov 2010 10:55:24 -0500, David Osborne krendilbo...@gmail.com wrote: Hi, I've noticed that the modulus operator acts differently when the divisor is the length of an array and the dividend is negative. For instance, this code: import std.stdio; const int x = 4; void main(){ int[x] arr = [0, 1, 2, 3]; writeln(Using arr.length); for(int i = -3; i = 0; i++){ writefln(%d mod %d = %d, i, arr.length, i % arr.length); } writeln(Using x); for(int i = -3; i = 0; i++){ writefln(%d mod %d = %d, i, x, i % x); } } Produces this output: Using arr.length -3 mod 4 = 1 -2 mod 4 = 2 -1 mod 4 = 3 0 mod 4 = 0 Using x -3 mod 4 = -3 -2 mod 4 = -2 -1 mod 4 = -1 0 mod 4 = 0 Which is a useful (but undocumented?) feature that lets you loop through arrays backwards. However, when the length of the array is odd... const int x = 3; ... int[x] arr = [0, 1, 2]; It looks like this: Using arr.length -3 mod 3 = 1 -- this should be 0 -2 mod 3 = 2 -- this should be 1 -1 mod 3 = 0 -- this should be 2 0 mod 3 = 0 Using x -3 mod 3 = 0 -2 mod 3 = -2 -1 mod 3 = -1 0 mod 3 = 0 Does anyone know of a reason for this? It doesn't seem like a bug, but I don't know why it would do something like that. Upon further investigation, I found that when arr.length is even, i acts like (x*(abs(i)/x + 1) + i) , and when arr.length is odd, i acts like (x*(abs(i)/x - 1) + i) (I'm using dmd 2.049 on linux) Simple, array.length is an unsigned value, so the signed operands are promoted to unsigned through normal integer promotion: cast(uint)-3 - 4_294_967_293u 4_294_967_293u % 3u - 1 I don't think this undocumented feature is valid. In fact, it may not be valid for evens as well that aren't powers of 2. -Steve
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
On Tue, 16 Nov 2010 13:16:13 -0500, Steve Teale steve.te...@britseyeview.com wrote: Andrei, Maybe it is time that the structure of the standard library became more generalized. At the moment we have std... and core... Perhaps we need another branch in the hierarchy, like ranges... Then there could be a std.range module that was the gateway into ranges... The library could then expand in an orderly fashion, with a wider range of users becoming responsible for the maintenance of of different branches against changes in the language, not against changes in fashion. Then you could have ranges.regex, that suits you, and the people who were happy with the status quo, could continue to use std.regexp, which should continue to behave like it did in DMD2.029 or whatever it was when I wrote my 'legacy' code. The current system, where modules of the library can get arbitrarily deprecated and at some point removed because they are unfashionable, is very unfriendly. I recognize that you are young, hyper-intelligent, and motivated toward fame. But there are other users, like me, who are older, but not senile, and have more conservative attitudes, including the desire to use code they wrote in the past at some point in the future. The standard library should not have something to please everyone. If there is 5 different styles to do the same thing, it will be a failure. Can you just copy std.regex from 2.029 and compile it in your project? I.e. instead of phobos adding range branch for the new range style, you add branch Teale for your style and copy what you like in there. Then you have what you want (may take a little effort on your part, but then you control the results). Also, 2.029 is still available via download, you can still use it. -Steve
Re: RFC, ensureHeaped
On Tue, 16 Nov 2010 13:04:32 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 11/16/10 4:40 AM, Steven Schveighoffer wrote: On Mon, 15 Nov 2010 17:02:27 -0500, bearophile bearophileh...@lycos.com wrote: I have even suggested a transitive @noheap annotation, similar to @nothrow, that makes sure a function contains no heap allocations and doesn't call other things that perform heap allocations: http://d.puremagic.com/issues/show_bug.cgi?id=5219 The proliferation of function attributes produces interesting results: @noheap @safe nothrow pure real sin(in real x) { ... } This is a bit much. Introducing these attributes is viral -- once you go @noheap, anything you call must be @noheap, and the majority of functions will need to be marked @noheap. The gain is marginal at best anyways. Hm, interestingly a data qualifier @noheap would not need to be transitive as data on the stack may refer to data on the heap. I think he means transitive the same way pure is transitive. Not sure what the term would be, functionally transitive? in other words, if your function is marked @noheap, it cannot allocate any memory, which means it cannot call any *other* functions that allocate memory. -Steve
std.socket and std.socketstream
Users who consider using these two modules in conjunction should beware of clashes. I used std.socketstream in a micro-server context to read the individual lines of an http request. After that I reverted to socket level to keep the connection open for some time so that the client could re-use it. At that point, Socket.select() became completely broken, always returning immediately, regardless of the timeout argument. Creating the SocketStream within a block cured this to some extent, but then there appeared to be some persistence of the object after the closing brace of the block, possibly before the garbage collector killed it, and after an unknown timeout period, everything broke again. I would therefore suggest that use of SocketStream be restricted to circumstances where the socket connection is local and reliable, and not intermingled with the direct use of Socket.select(). I can't be more specific at the moment, but even this little knowledge might save somebody a lot of wasted time. Steve
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
Steven Schveighoffer Wrote: On Tue, 16 Nov 2010 13:16:13 -0500, Steve Teale steve.te...@britseyeview.com wrote: Andrei, Maybe it is time that the structure of the standard library became more generalized. At the moment we have std... and core... Perhaps we need another branch in the hierarchy, like ranges... Then there could be a std.range module that was the gateway into ranges... The library could then expand in an orderly fashion, with a wider range of users becoming responsible for the maintenance of of different branches against changes in the language, not against changes in fashion. Then you could have ranges.regex, that suits you, and the people who were happy with the status quo, could continue to use std.regexp, which should continue to behave like it did in DMD2.029 or whatever it was when I wrote my 'legacy' code. The current system, where modules of the library can get arbitrarily deprecated and at some point removed because they are unfashionable, is very unfriendly. I recognize that you are young, hyper-intelligent, and motivated toward fame. But there are other users, like me, who are older, but not senile, and have more conservative attitudes, including the desire to use code they wrote in the past at some point in the future. The standard library should not have something to please everyone. If there is 5 different styles to do the same thing, it will be a failure. Can you just copy std.regex from 2.029 and compile it in your project? I.e. instead of phobos adding range branch for the new range style, you add branch Teale for your style and copy what you like in there. Then you have what you want (may take a little effort on your part, but then you control the results). Also, 2.029 is still available via download, you can still use it. -Steve Yes Steve, of course I can, but other much more popular languages like for instance PHP seem to do OK with the suit-everyone style. I am just upset that code I put a lot of effort into gets broken because somebody else does not like the style of the library. Which should be preserved - style, or substance? Steve
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
On 11/16/2010 01:30 PM, Steven Schveighoffer wrote: On Tue, 16 Nov 2010 13:16:13 -0500, Steve Teale steve.te...@britseyeview.com wrote: Andrei, Maybe it is time that the structure of the standard library became more generalized. At the moment we have std... and core... Perhaps we need another branch in the hierarchy, like ranges... Then there could be a std.range module that was the gateway into ranges... The library could then expand in an orderly fashion, with a wider range of users becoming responsible for the maintenance of of different branches against changes in the language, not against changes in fashion. Then you could have ranges.regex, that suits you, and the people who were happy with the status quo, could continue to use std.regexp, which should continue to behave like it did in DMD2.029 or whatever it was when I wrote my 'legacy' code. The current system, where modules of the library can get arbitrarily deprecated and at some point removed because they are unfashionable, is very unfriendly. I recognize that you are young, hyper-intelligent, and motivated toward fame. But there are other users, like me, who are older, but not senile, and have more conservative attitudes, including the desire to use code they wrote in the past at some point in the future. The standard library should not have something to please everyone. If there is 5 different styles to do the same thing, it will be a failure. Can you just copy std.regex from 2.029 and compile it in your project? I.e. instead of phobos adding range branch for the new range style, you add branch Teale for your style and copy what you like in there. Then you have what you want (may take a little effort on your part, but then you control the results). Also, 2.029 is still available via download, you can still use it. -Steve This actually sounds interesting. If I'm understanding things right, std.range.* would provide a range interface to specific libraries, such as regex. So, in theory, there could be different interfaces to the same functionality. E.g. std.range.regex, std.oo.regex, and std.proc.regex for a range interface, a OO interface, or a procedural interface. Underneath, you could have the same core functionality, but people can access it in the way they feel most comfortable or that better fits the design of the program being written. As new paradigms are invented, they can be added as well and be based on the existing interfaces. Is this something we want to do? Don't know. I don't even know how feasible it is. However, I do like the concept and if the goal is to make the language as friendly as possible, perhaps it should be looked into. There's the chance that it will cause some confusion, but how much will actually occur? The biggest issue I see is having certain libraries that don't fit well into all of the different paradigms. E.g. a date library can have a nice OO interface and a nice procedural interface, but it doesn't make much sense to have a range interface. Anyway, food for thought. Casey
Re: DMD Automatic Dependency Linking
Am 16.11.2010 18:38, schrieb Travis: The one thing I have been wondering however is why doesn't DMD have a flag for easy project building which compiles dependencies in a single command. [...] Thanks, tbone Have you tried 'rdmd' ?
std.date
I have moaned several times about the fact that this module does not have a method for creating a date from the system clock. It provides a parse method to convert a string in a limited number of formats. In the course of doing that, it calls the OS primitive to get the time zone offset. So why the omission? If it's going to use the OS, why not go the whole hog. It also strikes me as odd that it does not include a table of leap seconds. As it stands, some of its methods could return values that were out by a year for up to four or five seconds on January 1 2011. I'm no expert on UTC, Gregorian Calendar and such, so I could well be wrong, but Phobos doesn't really need the burden of such tasks. Most OS's provide regular upgrades that cover this stuff. Steve
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
On Tue, 16 Nov 2010 13:46:48 -0500, Steve Teale steve.te...@britseyeview.com wrote: Steven Schveighoffer Wrote: On Tue, 16 Nov 2010 13:16:13 -0500, Steve Teale steve.te...@britseyeview.com wrote: Andrei, Maybe it is time that the structure of the standard library became more generalized. At the moment we have std... and core... Perhaps we need another branch in the hierarchy, like ranges... Then there could be a std.range module that was the gateway into ranges... The library could then expand in an orderly fashion, with a wider range of users becoming responsible for the maintenance of of different branches against changes in the language, not against changes in fashion. Then you could have ranges.regex, that suits you, and the people who were happy with the status quo, could continue to use std.regexp, which should continue to behave like it did in DMD2.029 or whatever it was when I wrote my 'legacy' code. The current system, where modules of the library can get arbitrarily deprecated and at some point removed because they are unfashionable, is very unfriendly. I recognize that you are young, hyper-intelligent, and motivated toward fame. But there are other users, like me, who are older, but not senile, and have more conservative attitudes, including the desire to use code they wrote in the past at some point in the future. The standard library should not have something to please everyone. If there is 5 different styles to do the same thing, it will be a failure. Can you just copy std.regex from 2.029 and compile it in your project? I.e. instead of phobos adding range branch for the new range style, you add branch Teale for your style and copy what you like in there. Then you have what you want (may take a little effort on your part, but then you control the results). Also, 2.029 is still available via download, you can still use it. -Steve Yes Steve, of course I can, but other much more popular languages like for instance PHP seem to do OK with the suit-everyone style. I don't object to having multiple styles to do things, I even maintain a library (dcollections) that is not even close to the style of std.container. I just object to everything being included in the standard library. The standard library should do things one way, and if you want something different, use an add-on library. I'm guessing you are referring to php's pcre vs posix regex? I think posix is marked as deprecated... I am just upset that code I put a lot of effort into gets broken because somebody else does not like the style of the library. Well, the library isn't finished. As much as I understand your pain, I also don't think phobos should be write-only. We should not be stuck with mistakes or designs of the past until we have stated the library is released, and then we can deal with backwards compatibility in a reasonable way. Until then, you shouldn't expect everything to be set in stone. Sorry if this is confusing or annoying. That being said, if std.regexp is broken, I don't think it was intentional. In fact, in the bug report, someone mentions a one-line fix, does that solve your problem? AFAIK, regexp is not even deprecated yet, which means it should be supported. I think Andrei said as much. Which should be preserved - style, or substance? substance. AFAIK, substance is preserved, or am I misunderstanding you? -Steve
Re: RFC, ensureHeaped
On Tuesday, November 16, 2010 10:31:43 Steven Schveighoffer wrote: On Tue, 16 Nov 2010 13:04:32 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 11/16/10 4:40 AM, Steven Schveighoffer wrote: On Mon, 15 Nov 2010 17:02:27 -0500, bearophile bearophileh...@lycos.com wrote: I have even suggested a transitive @noheap annotation, similar to @nothrow, that makes sure a function contains no heap allocations and doesn't call other things that perform heap allocations: http://d.puremagic.com/issues/show_bug.cgi?id=5219 The proliferation of function attributes produces interesting results: @noheap @safe nothrow pure real sin(in real x) { ... } This is a bit much. Introducing these attributes is viral -- once you go @noheap, anything you call must be @noheap, and the majority of functions will need to be marked @noheap. The gain is marginal at best anyways. Hm, interestingly a data qualifier @noheap would not need to be transitive as data on the stack may refer to data on the heap. I think he means transitive the same way pure is transitive. Not sure what the term would be, functionally transitive? in other words, if your function is marked @noheap, it cannot allocate any memory, which means it cannot call any *other* functions that allocate memory. Pure is hard enough to deal with (especially since it we probably have made it the default, but it's too late for that now). We shouldn't even consider adding anything more like that without a _really_ good reason. - Jonathan M Davis
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
On 11/16/10 10:16 AM, Steve Teale wrote: Andrei Alexandrescu Wrote: I am sorry for the inadvertent change, it wasn't meant to change semantics of existing code. I'm not sure whether one of my unrelated 64-bit changes messed things up. You may want to file a bug report. There are a number of good reasons for which I was compelled to split std.regex from std.regexp. I'm sure you or others would have found them just as compelling if you saw things the same way. Phobos 1 has experimented in std.string and std.regexp with juxtaposing APIs of various languages (PHP, Ruby, Python). The reasoning was that people familiar with either of those languages could feel right at home by using APIs with similar nomenclatures and semantics. The result was some strange bedfellows in std.string such as column or capwords and an outright mess in std.regexp. The interface of std.regexp is without a doubt the worst I've ever seen, by a long shot. I have never been able to use it without poring through the documentation _several times_ and without confirming to myself via a small test case that I'm doing the right thing. The simplest problem is this: std.regexp uses the words exec, find, match, search, and test - all to mean regular expression matching. There is absolutely no logic to how meanings are ascribed to words, and there is absolutely no recourse than rote memorization of various arbitrary decisions. The resulting FrankenAPI is likely familiar to anyone except those who've actually spent time learning it, in spite of it trying to be familiar to anyone. So I spawned std.regex in an attempt to sanitize the API (I made minor, if any, changes to the engine; I am in fact having significant trouble maintaining it). The advantages of std.regex are: * No more class definition. Nobody is supposed to inherit RegExp anyway so it's useless to brand the object as a class. * Engine is separated from matches, which means that engines can be memoized for efficiency. Currently regex() only memoizes the last engine. * The new engine works with any character size. * Simpler API: create a regex, call match() against that regex and a string, look at the resulting RegexMatch object. If this all annoys you more than the old API, I will need to disagree. If you have suggestions on how std.regex can be improved, I'm all ears. Andrei Andrei, Maybe it is time that the structure of the standard library became more generalized. At the moment we have std... and core... Perhaps we need another branch in the hierarchy, like ranges... Then there could be a std.range module that was the gateway into ranges... The library could then expand in an orderly fashion, with a wider range of users becoming responsible for the maintenance of of different branches against changes in the language, not against changes in fashion. Then you could have ranges.regex, that suits you, and the people who were happy with the status quo, could continue to use std.regexp, which should continue to behave like it did in DMD2.029 or whatever it was when I wrote my 'legacy' code. I think that's not a good design. Ranges are a cross-cutting abstraction. One wouldn't put all code using exception under std.exceptions or code using floating point under std.floating_point. Better, ranges, exceptions, or floating point should be used wherever it makes sense to use them. The current system, where modules of the library can get arbitrarily deprecated and at some point removed because they are unfashionable, is very unfriendly. I agree we need to have a rather long deprecation schedule. Fashionable has, however, little to do with the rationale for deprecation. You may want to tune to the Phobos developers' mailing list for more details. I recognize that you are young, hyper-intelligent, and motivated toward fame. I have enumerated a list of technical reasons for which std.regexp is inadequate, followed by a list of improvements brought about by std.regex. Ranges are nowhere on that list, nor is being fashionable. It's all good old design stuff that I'm sure you have down better than me: make an API small and simple, separate concerns (engine/matches), use the right tool for the job (struct not class), generalize within reason (character width). Would have been great to have a discussion along those lines. Instead, I see you chose to ignore all technical arguments and go with a presupposition, no matter how assuming and stereotypical. But there are other users, like me, who are older, but not senile, and have more conservative attitudes, including the desire to use code they wrote in the past at some point in the future. Backward compatibility is indeed important, and again we need to have a long deprecation schedule. At the same time, I think there are much more many users in D's future than in its past, and I cannot inflict std.regexp on them. Andrei
Re: std.date
On Tue, 16 Nov 2010 14:11:05 -0500, Steve Teale steve.te...@britseyeview.com wrote: I have moaned several times about the fact that this module does not have a method for creating a date from the system clock. It provides a parse method to convert a string in a limited number of formats. In the course of doing that, it calls the OS primitive to get the time zone offset. So why the omission? If it's going to use the OS, why not go the whole hog. It also strikes me as odd that it does not include a table of leap seconds. As it stands, some of its methods could return values that were out by a year for up to four or five seconds on January 1 2011. I'm no expert on UTC, Gregorian Calendar and such, so I could well be wrong, but Phobos doesn't really need the burden of such tasks. Most OS's provide regular upgrades that cover this stuff. Jonathan Davis has been creating a date/time library that will replace std.time. See earlier posts on this newsgroup about std.datetime updates Please comment if you think there are problems with it. -Steve
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
Steven Schveighoffer Wrote: I'm guessing you are referring to php's pcre vs posix regex? I think posix is marked as deprecated... Steve, No. I just meant that the library that comes with PHP seems happy to provide different ways of doing the same thing, as in for example, CURL, DOMDocument, and standard file operation wrappers. I've been following D on and off for about seven or eight years now, so I don't subscribe too much to the 'when it's finished' argument. By now, it needs to work for real projects. But I've had my gripe - I'll shut up for now. Steve
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
On Tuesday, November 16, 2010 10:30:03 Steven Schveighoffer wrote: The standard library should not have something to please everyone. If there is 5 different styles to do the same thing, it will be a failure. Agreed. Ideally, the standard library would be very uniform in approach. That makes it easier to learn and use. If it's schizophrenic about it's approach - especially if it has multiple ways of doing everything - then it's going to be much harder to learn and use. Everyone would be asking why you'd choose one way over another and what the differences between them are. It would just cause confusion. Ranges are a key element of how Phobos does things in D2. The truth of the matter is that if you want to effectively use Phobos, you're going to have to use ranges. If ranges aren't appropriate for a particular module or problem, then they shouldn't be used, but Phobos is generally being built around using them, and the more of Phobos which functions in essentially the same way, the easier it will be to understand, learn, and use. The old code is indeed available for modules which are going to be deprecated/removed, and the license is usually Boost, so you're pretty free to do what you want with it if you prefer it. And there's nothing wrong with creating your own libraries if you'd prefer. Plenty of folks have done that in the past. The standard library needs to be fairly uniform in approach, however, and some of the current modules are older and don't follow that approach or have licensing or design issues which were not addressed in the past. Once all of those modules have been updated, replaced, or removed, Phobos will be more uniform and its parts will interact better. And over time, it's unlikely that modules will continue to be deprecated like that. It's happening now because D2 Phobos is still fairly early in its evolution. - Jonathan M Davis
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
On 11/16/10 10:46 AM, Steve Teale wrote: Steven Schveighoffer Wrote: On Tue, 16 Nov 2010 13:16:13 -0500, Steve Teale steve.te...@britseyeview.com wrote: Andrei, Maybe it is time that the structure of the standard library became more generalized. At the moment we have std... and core... Perhaps we need another branch in the hierarchy, like ranges... Then there could be a std.range module that was the gateway into ranges... The library could then expand in an orderly fashion, with a wider range of users becoming responsible for the maintenance of of different branches against changes in the language, not against changes in fashion. Then you could have ranges.regex, that suits you, and the people who were happy with the status quo, could continue to use std.regexp, which should continue to behave like it did in DMD2.029 or whatever it was when I wrote my 'legacy' code. The current system, where modules of the library can get arbitrarily deprecated and at some point removed because they are unfashionable, is very unfriendly. I recognize that you are young, hyper-intelligent, and motivated toward fame. But there are other users, like me, who are older, but not senile, and have more conservative attitudes, including the desire to use code they wrote in the past at some point in the future. The standard library should not have something to please everyone. If there is 5 different styles to do the same thing, it will be a failure. Can you just copy std.regex from 2.029 and compile it in your project? I.e. instead of phobos adding range branch for the new range style, you add branch Teale for your style and copy what you like in there. Then you have what you want (may take a little effort on your part, but then you control the results). Also, 2.029 is still available via download, you can still use it. -Steve Yes Steve, of course I can, but other much more popular languages like for instance PHP seem to do OK with the suit-everyone style. I am just upset that code I put a lot of effort into gets broken because somebody else does not like the style of the library. Which should be preserved - style, or substance? Steve It's probably common courtesy that should be preserved. I just committed the fix prompted by Lutger (thanks). Andrei
Re: std.algorithm.remove using SwapStrategy.unstable doesn't works
No problem, just to isolate the code and to confirm it's not something to other parts of my code (but I'm pretty sure it's not). On Tue, Nov 16, 2010 at 7:03 PM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 11/16/10 4:24 AM, Aleksandar Ružičić wrote: I'm trying to use remove() from std.algorithm to remove item from an array and when I tried to use SwapStrategy.unstable (as I don't need to maintain order of items in array and I want to optimize where ever I can) I came to surprising results. In the example below one would expect that item at index 2 (number 3 in example) will be removed but instead item at index 0 is removed from array. Is this a bug or I'm missing a point? - import std.stdio, std.algorithm; void main(string[] args) { auto a = [1,2,3,4]; foreach (e; a) writef(%s , e); writefln((%s), a.length); // 1 2 3 4 (4) auto i = a.indexOf(3); writefln(%s, i); // 2 if (i -1) { a = remove!(SwapStrategy.unstable)(a, i); } foreach (e; a) writef(%s , e); writefln((%s), a.length); // 4 2 3 (3) !?! } - thx in advance, Aleksandar Looks like a bug. Could you please file it to bugzilla? Thanks, Andrei
Re: std.date
On Tuesday, November 16, 2010 11:11:05 Steve Teale wrote: I have moaned several times about the fact that this module does not have a method for creating a date from the system clock. It provides a parse method to convert a string in a limited number of formats. In the course of doing that, it calls the OS primitive to get the time zone offset. So why the omission? If it's going to use the OS, why not go the whole hog. It also strikes me as odd that it does not include a table of leap seconds. As it stands, some of its methods could return values that were out by a year for up to four or five seconds on January 1 2011. I'm no expert on UTC, Gregorian Calendar and such, so I could well be wrong, but Phobos doesn't really need the burden of such tasks. Most OS's provide regular upgrades that cover this stuff. As Steven points out, I've been working on a date/time module which will become std.datetime once its review process is finished. It's far more advanced than std.date. However, I would point out though that virtually nothing computer-wise cares about leap seconds. Posix even specifically ignores them. This currently means that UTC according to your typical computer is technically 24 seconds off of UTC. But for the most part, since they all ignore leap seconds, it's not an issue. However, with the future std.datetime, if you use PosixTimeZone with a time zone which has leap seconds (which are generally the ones whose names start with right/), you can have leap seconds. In any case, feel free to try out the code and comment on it. The most recent thread on it is datetime review part 2, so please post any comments that you have on it there. The most recent code which I've posted can be found here: http://is.gd/gSwDv HTML documentation for it can be found in the Doc folder while the source is in Src. It should be a huge step up from using std.date (which is highly buggy at present regardless of whether the design as any good or not). - Jonathan M Davis
Re: std.algorithm.remove using SwapStrategy.unstable doesn't works
filed as Issue #5224 - http://d.puremagic.com/issues/show_bug.cgi?id=5224 regards, Aleksandar 2010/11/16 Aleksandar Ružičić ruzicic.aleksan...@gmail.com: No problem, just to isolate the code and to confirm it's not something to other parts of my code (but I'm pretty sure it's not). On Tue, Nov 16, 2010 at 7:03 PM, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 11/16/10 4:24 AM, Aleksandar Ružičić wrote: I'm trying to use remove() from std.algorithm to remove item from an array and when I tried to use SwapStrategy.unstable (as I don't need to maintain order of items in array and I want to optimize where ever I can) I came to surprising results. In the example below one would expect that item at index 2 (number 3 in example) will be removed but instead item at index 0 is removed from array. Is this a bug or I'm missing a point? - import std.stdio, std.algorithm; void main(string[] args) { auto a = [1,2,3,4]; foreach (e; a) writef(%s , e); writefln((%s), a.length); // 1 2 3 4 (4) auto i = a.indexOf(3); writefln(%s, i); // 2 if (i -1) { a = remove!(SwapStrategy.unstable)(a, i); } foreach (e; a) writef(%s , e); writefln((%s), a.length); // 4 2 3 (3) !?! } - thx in advance, Aleksandar Looks like a bug. Could you please file it to bugzilla? Thanks, Andrei
Re: Function, signatures and tuples
On 11/13/2010 11:43 AM, Russel Winder wrote: On Sat, 2010-11-13 at 08:18 +, Iain Buclaw wrote: [ . . . ] import std.typecons; ? Hummm... I thought I had put that in but clearly I had not :-(( OK so that explains the bulk of the problems on this code, I knew it was something stupid on my part, thanks for spotting it. However, now we may be getting to something more serious. The line: foreach ( i ; 0 .. numberOfTasks ) { inputData[i] = tuple ( 1 + i * sliceSize , ( i + 1 ) * sliceSize , delta ) ; } now results in the error: /home/users/russel/lib.Linux.x86_64/DMD2/bin/../../src/phobos/std/typecons.d(662): Error: can only initialize const member _field_field_2 inside constructor /home/users/russel/lib.Linux.x86_64/DMD2/bin/../../src/phobos/std/typecons.d(26): Error: template instance std.typecons.tuple!(long,long,immutable(double)) error instantiating Which at first sight seems to indicate an error in the typecons package of Phobos. On the other hand, it is probably more reasonable to assume I still have something stupid wrong in my code. It's not your code, you can work around it with cast(double)delta, or using tuple!(long,long,double) explicitly, I think. Tuple doesn't handle immutable or const really well, yet.
Re: RFC, ensureHeaped
Jonathan M Davis: Pure is hard enough to deal with (especially since it we probably have made it the default, but it's too late for that now). Weakly pure on default isn't good for a language that is supposed to b e somewhat compatible with C syntax, I think it breaks too many C functions. Bye, bearophile
std.container.BinaryHeap + refCounted = WTF???
I'm trying to use BinaryHeap in a multithreaded programming using std.parallelism/parallelfuture. I kept getting ridiculous segfaults and stuff, and when I looked into it in a debugger, I realized the crashes had to do with reference counting, probably caused by this line in BinaryHeap: private RefCounted!(Tuple!(Store, _store, size_t, _length), RefCountedAutoInitialize.no) _payload; Why the heck are the payload and the length being stored in such a weird way? IMHO BinaryHeap shouldn't use reference counting unless Store does. More generally, anything that uses reference counting, especially where unexpected, should come with a very strong warning in its ddoc so that people are aware of the hidden caveats, like copying it using memcpy() and sharing it across threads.
Re: std.date
Steve Teale Wrote: It also strikes me as odd that it does not include a table of leap seconds. As it stands, some of its methods could return values that were out by a year for up to four or five seconds on January 1 2011. I'm no expert on UTC, Gregorian Calendar and such, so I could well be wrong, but This depends on how the library imports time from system. If it imports in nominal form: receives actual hours, minutes and seconds as separate values, it will precisely represent the time point in nominal and string forms. Only time intervals will be off by leap seconds that were introduces during the intervals.
Re: RFC, ensureHeaped
On Tuesday 16 November 2010 12:37:10 bearophile wrote: Jonathan M Davis: Pure is hard enough to deal with (especially since it we probably have made it the default, but it's too late for that now). Weakly pure on default isn't good for a language that is supposed to b e somewhat compatible with C syntax, I think it breaks too many C functions. Well, like I said, it's too late at this point, and really, it would be good to have a nice way to deal with C functions and purity (particularly since most of them are pure anyway), but the result at present is that most functions should be marked with pure. And if you're marking more functions with pure than not, that would imply that the default should be (at least ideally) impure. Regardless, however, it's not reasonable for D to go for impure rather than pure at this point. - Jonathan M Davis
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
On Tue, 16 Nov 2010 11:24:02 -0800 Jonathan M Davis jmdavisp...@gmx.com wrote: On Tuesday, November 16, 2010 10:30:03 Steven Schveighoffer wrote: The standard library should not have something to please everyone. If there is 5 different styles to do the same thing, it will be a failure. Agreed. Ideally, the standard library would be very uniform in approach. That makes it easier to learn and use. If it's schizophrenic about it's approach - especially if it has multiple ways of doing everything - then it's going to be much harder to learn and use. Everyone would be asking why you'd choose one way over another and what the differences between them are. It would just cause confusion. Ranges are a key element of how Phobos does things in D2. The truth of the matter is that if you want to effectively use Phobos, you're going to have to use ranges. If ranges aren't appropriate for a particular module or problem, then they shouldn't be used, but Phobos is generally being built around using them, and the more of Phobos which functions in essentially the same way, the easier it will be to understand, learn, and use. The old code is indeed available for modules which are going to be deprecated/removed, and the license is usually Boost, so you're pretty free to do what you want with it if you prefer it. And there's nothing wrong with creating your own libraries if you'd prefer. Plenty of folks have done that in the past. The standard library needs to be fairly uniform in approach, however, and some of the current modules are older and don't follow that approach or have licensing or design issues which were not addressed in the past. Once all of those modules have been updated, replaced, or removed, Phobos will be more uniform and its parts will interact better. And over time, it's unlikely that modules will continue to be deprecated like that. It's happening now because D2 Phobos is still fairly early in its evolution. - Jonathan M Davis +++ Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: assert(false) with -unittest
dsimcha: I think this is correct. The -unittest switch implicitly turns on asserts, and as far as I can tell makes the -release switch ignored. This means that assert(false) is no longer special and works just like a regular assert as per TDPL. Is this a problem in practice? If so, please explain. We have recently discussed a related topic. That works according to the specs. But mixing the halt with asserts is not tidy and it's not good. The conclusion was that the design is bad, but apparently it's not bad enough to justify a fix. Bye, bearophile
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
Steve Teale: The current system, where modules of the library can get arbitrarily deprecated and at some point removed because they are unfashionable, is very unfriendly. We are in the initial phase of Phobos develpment, so frequent large changes are expected. Surely one year from now Phobos will be more careful in its changes. The other things you have said are too much silly to comment. And thank you to Andrei to the improvements to the D regex API, I'd love to see other good people give other similar improvements to Phobos :-) We must be grateful with Andrei for improving that API. Bye, bearophile
Re: modulus and array.length
David Osborne wrote: Using arr.length -3 mod 3 = 1 -- this should be 0 -2 mod 3 = 2 -- this should be 1 -1 mod 3 = 0 -- this should be 2 0 mod 3 = 0 Like others have said, this is due to the fact that when one operand is unsigned (here the length), then all operands get casted to unsigned before the operation. Several people have asked that array length be changed to a signed value because of that (bearophile probably has a bug report for it ;) ) Using x -3 mod 3 = 0 -2 mod 3 = -2 -1 mod 3 = -1 0 mod 3 = 0 This is consistent with the C behaviour. Note that according to the C standard, the result of the modulus operation with negative arguments is undefined. I don't remember if Walter has specified the expected behaviour for D or if he left it undefined... Note that from a strictly mathematical point of view, this result is valid: for all x and all n, x-(x%n) is a multiple of n. Jerome -- mailto:jeber...@free.fr http://jeberger.free.fr Jabber: jeber...@jabber.fr signature.asc Description: OpenPGP digital signature
Re: std.container.BinaryHeap + refCounted = WTF???
On 11/16/10 12:47 PM, dsimcha wrote: I'm trying to use BinaryHeap in a multithreaded programming using std.parallelism/parallelfuture. I kept getting ridiculous segfaults and stuff, and when I looked into it in a debugger, I realized the crashes had to do with reference counting, probably caused by this line in BinaryHeap: private RefCounted!(Tuple!(Store, _store, size_t, _length), RefCountedAutoInitialize.no) _payload; Why the heck are the payload and the length being stored in such a weird way? IMHO BinaryHeap shouldn't use reference counting unless Store does. More generally, anything that uses reference counting, especially where unexpected, should come with a very strong warning in its ddoc so that people are aware of the hidden caveats, like copying it using memcpy() and sharing it across threads. BinaryHeap being a container it has reference semantics. In order to also be sealed, it needs to be reference counted. The fact that the store uses itself reference counting is not relevant because BinaryHeap has two fields. Andrei
Re: modulus and array.length
Jérôme M. Berger Wrote: -3 mod 3 = 0 -2 mod 3 = -2 -1 mod 3 = -1 0 mod 3 = 0 Note that from a strictly mathematical point of view, this result is valid: for all x and all n, x-(x%n) is a multiple of n. It's rather (x/n)+(x%n)==x
Re: The D Scripting Language
I really think that it would be good to ship something like this with dmd and promote it default D script handler. May be, parsing must be more complicated (I'm not sure that all features will work inside main()), but as D is easy for parsing I see no big problems.Of cource, we can add more complicated code wrapper - for example, something that will give null when trying to get non-existant arg, or default key hadling, or something else. Of cource, special module also could be useful for this purpose. Hmm, it's interesting to write this toy... Compiled language being as easy as script at least looks interesting, so this can help to promote D with minimal resources involved. 2010/11/16 Adam Ruppe destructiona...@gmail.com: Script mode (actually - simple wrapper) would be better: It could do simple parsing of script, bringing all import clauses to the beginning and add some default imports (like std.stdio). It seems that all code below imports can be wrapped into main declaration. My rund.d program does this. http://arsdnet.net/dcode/rund.d As you can see, it's a trivial program. -- С уважением, Алексей Хмара
Re: modulus and array.length
Kagamin wrote: Jérôme M. Berger Wrote: -3 mod 3 = 0 -2 mod 3 = -2 -1 mod 3 = -1 0 mod 3 = 0 Note that from a strictly mathematical point of view, this result is valid: for all x and all n, x-(x%n) is a multiple of n. It's rather (x/n)+(x%n)==x That is (part of) the definition of the *remainder* operation. The definition of *modulus* is looser. Jerome -- mailto:jeber...@free.fr http://jeberger.free.fr Jabber: jeber...@jabber.fr signature.asc Description: OpenPGP digital signature
Re: Compiler optimization breaks multi-threaded code
Am 16.11.2010 18:09, schrieb Sean Kelly: cas() contains an asm block. Though I guess in this case the compiler isn't actually optimizing across it. Does atomic!+=(cnt, 1) work correctly? I know the issue with shared would still have to be fixed, but that code uses asm for the load as well, so it probably won't be optimized the same way. Thanks for looking into the issue around here. Just three comments from my side, Sean. Disclaimer: based on a couple of hours chasing a bug and not much D experience (but some optimizing C++ compiler experience - so the issue looked familiar :-) ) 1) atomicOp is not concerned. You only read memory once in the function call. Whether from a local variable that was loaded from something global or directly from a global, doesn't really matter (except for timing, maybe). 2) You are right, the compiler seems to not optimize across asm statements. So, the example can be fixed with the following hack: void atomicInc ( ) { uint o; while ( !cas( cnt, o, o + 1 ) ) { asm { nop; } o = cnt; } } This is however more brittle than it looks, because it is not always clear what optimizing across an asm block. This version has the issue again: void atomicInc ( ) { uint o = cnt; do { asm { nop; } o = cnt; } while ( !cas( cnt, o, o + 1 ) ) } While this case might look somewhat obvious, I encountered some problems in more complex code, and finally went for the all-inline-assembler solution to be on the safe side. 3) During my debugging, I believe that I saw the optimizer not only re-ordering reads of shared variables, but also writes to shared variables. IIRC, my Dekker example on SO (which fails for the missing s/l/mfence instructions), also sports a re-ordering of the lines cnt++; turn2 = true; flag1 = false; into turn2 = true; cnt++; flag1 = false; which in this case is not really important, but might introduce another bug if I was prepared to live with the risk of starvation (and remove turn2). If the compiler would still re-order (haven't tested), cnt++ would be outside of the critical section. Hope this helps cheers, Stephan
Re: modulus and array.length
J. M. Berger: (bearophile probably has a bug report for it ;) ) Yup, bug 3843. Bye, bearophile
Re: std.container.BinaryHeap + refCounted = WTF???
On 2010-11-16 15:47:07 -0500, dsimcha dsim...@yahoo.com said: I'm trying to use BinaryHeap in a multithreaded programming using std.parallelism/parallelfuture. I kept getting ridiculous segfaults and stuff, and when I looked into it in a debugger, I realized the crashes had to do with reference counting, probably caused by this line in BinaryHeap: private RefCounted!(Tuple!(Store, _store, size_t, _length), RefCountedAutoInitialize.no) _payload; Why the heck are the payload and the length being stored in such a weird way? IMHO BinaryHeap shouldn't use reference counting unless Store does. More generally, anything that uses reference counting, especially where unexpected, should come with a very strong warning in its ddoc so that people are aware of the hidden caveats, like copying it using memcpy() and sharing it across threads. RefCounted, and many other things in Phobos, aren't thread-safe because of those reference counters. This problem can occur even if you don't share it with other threads, as the GC may destroy objects in another thread. See bug 4624: http://d.puremagic.com/issues/show_bug.cgi?id=4624 Also bug 4621 about the compiler not catching the problem at compile-time (as it should catch low-level races): http://d.puremagic.com/issues/show_bug.cgi?id=4621 I suggest you try to make RefCounted use an atomic reference counter to see if it removes your segfaults. Andrei acknowledged the issue recently (Walter too, I think), so I trust it'll be fixed at some point. One idea was to change the GC so it knows in which thread it should call destructors... -- Michel Fortin michel.for...@michelf.com http://michelf.com/
Re: modulus and array.length
Thanks for the info, everyone. I guess I'll just have to be more careful what I use modulus with :) ~Dave
Re: forbid field name conflict in class hierarchy
On Tuesday, November 16, 2010 03:40:24 spir wrote: On Tue, 16 Nov 2010 05:37:52 -0500 bearophile bearophileh...@lycos.com wrote: spir: (and bug-prone, because sometimes the absence of a fields seems not caught, for any reason), so I add fields to the top type. What do you mean? Do you have an example? (Adding fields to the top type doesn't look like a good idea, generally). Bye, bearophile For instance, I have 2 sub-classes of nodes: one leaf kind with element (here called slice), one branch kind with an array of (child) nodes. They are exclusive, and none of the data fields should appear on the top Node type. But everywhere the Node class must be used, since a branch (as the top tree) can indifferently hold leaves or sub-branches, right? Each time I need to post-process results, since I apparently get Nodes (even if I know they are actually of one or the other type), I would first have to down-cast each node to the proper kind before doing anything. Else, I would get compiler errors, or plain bugs, for not having the proper field. So, I ended up setting fake fields on Node (and remove them from the sub-classes). And yes, I agree it's A Bad Thing to do. Just tell me of an elegant solution, and I apply it at once. Well, I think that I'd have to study your code to get quite what you're doing. However, I would consider _any_ case in code where you specifically cast to a derived class from a base class to be a code smell. My general reaction is that there _has_ to be a better, cleaner way to do it, and that it stinks of bad design. However, I'd have to really understand what you're doing to give a better suggestion, and just because it's _almost_ always a bad idea doesn't mean that it's _always_ a bad idea. - Jonathan M Davis
Re: std.date
On Tuesday, November 16, 2010 13:00:17 Kagamin wrote: Steve Teale Wrote: It also strikes me as odd that it does not include a table of leap seconds. As it stands, some of its methods could return values that were out by a year for up to four or five seconds on January 1 2011. I'm no expert on UTC, Gregorian Calendar and such, so I could well be wrong, but This depends on how the library imports time from system. If it imports in nominal form: receives actual hours, minutes and seconds as separate values, it will precisely represent the time point in nominal and string forms. Only time intervals will be off by leap seconds that were introduces during the intervals. Of course, the annoying thing about leap seconds is that because they're unpredictable, it's _impossible_ to give correct interval lengths (with regards to leap seconds) for intervals which cover future dates. Right now, leap seconds introduce a difference of 24 seconds, and a new leap second has generally been added about once every two years, but that could easily change. A year or two from now, it could be pretty much any number within a few seconds of 24 (even numbers less than 24 like 22 or 23). So, only intervals entirely in the past can be completely correct with regards to leap seconds (or ones so near in the future that there's no way that a leap second would have been added or removed between now and then). Honestly, leap seconds are complete stupidity with regards to computers. They just complicate things. Of course, time in general has various issues when it comes to computers (DST is one of the stupidest ideas even IMHO; I don't even want to _think_ about how many bugs it's created), but leap seconds are definitely on my list of time-related stuff that should be abolished (and there are those lobbying for it, so it may happen eventually). On the bright side, computers generally ignore them, so you don't have to care (unless you're one of those extremely rare people who do, at which point, you have my condolences). - Jonathan M Davis
Re: RFC, ensureHeaped
On Tue, 16 Nov 2010 16:04:18 -0500, Jonathan M Davis jmdavisp...@gmx.com wrote: On Tuesday 16 November 2010 12:37:10 bearophile wrote: Jonathan M Davis: Pure is hard enough to deal with (especially since it we probably have made it the default, but it's too late for that now). Weakly pure on default isn't good for a language that is supposed to b e somewhat compatible with C syntax, I think it breaks too many C functions. Well, like I said, it's too late at this point, and really, it would be good to have a nice way to deal with C functions and purity (particularly since most of them are pure anyway), but the result at present is that most functions should be marked with pure. And if you're marking more functions with pure than not, that would imply that the default should be (at least ideally) impure. Regardless, however, it's not reasonable for D to go for impure rather than pure at this point. everything you are saying seems to be backwards, stop it! ;) 1. currently, the default is impure. 2. Most functions will naturally be weakly pure, so making *pure* the default would seem more useful. It seems backwards to me to think pure functions should be the default, I mean, this isn't a functional language! But you also have to forget everything you know about pure, because a weakly pure function is a very useful idiom, and it is most certainly not compatible with functional languages. It's both imperative and can accept and return mutable data. It makes me think that this is going to be extremely confusing for a while, because people are so used to pure being equated with a functional language, so when they see a function is pure but takes mutable data, they will be scratching their heads. It would be awesome to make weakly pure the default, and it would also make it so we have to change much less code. -Steve
Re: Compiler optimization breaks multi-threaded code
stephan Wrote: Am 16.11.2010 18:09, schrieb Sean Kelly: cas() contains an asm block. Though I guess in this case the compiler isn't actually optimizing across it. Does atomic!+=(cnt, 1) work correctly? I know the issue with shared would still have to be fixed, but that code uses asm for the load as well, so it probably won't be optimized the same way. Thanks for looking into the issue around here. Just three comments from my side, Sean. Disclaimer: based on a couple of hours chasing a bug and not much D experience (but some optimizing C++ compiler experience - so the issue looked familiar :-) ) 1) atomicOp is not concerned. You only read memory once in the function call. Whether from a local variable that was loaded from something global or directly from a global, doesn't really matter (except for timing, maybe). atomicOp uses a CAS loop for the RMW operations. The load in asm code was actually to bypass the synchronization generated by the compiler since it isn't needed in this case, but I guess it helped anyway. I'm wondering if I should change the binary op to use asm too, so the compiler doesn't do anything evil there until shared is implemented more fully. 2) You are right, the compiler seems to not optimize across asm statements. So, the example can be fixed with the following hack: void atomicInc ( ) { uint o; while ( !cas( cnt, o, o + 1 ) ) { asm { nop; } o = cnt; } } This is however more brittle than it looks, because it is not always clear what optimizing across an asm block. This version has the issue again: void atomicInc ( ) { uint o = cnt; do { asm { nop; } o = cnt; } while ( !cas( cnt, o, o + 1 ) ) } While this case might look somewhat obvious, I encountered some problems in more complex code, and finally went for the all-inline-assembler solution to be on the safe side. 3) During my debugging, I believe that I saw the optimizer not only re-ordering reads of shared variables, but also writes to shared variables. IIRC, my Dekker example on SO (which fails for the missing s/l/mfence instructions), also sports a re-ordering of the lines cnt++; turn2 = true; flag1 = false; into turn2 = true; cnt++; flag1 = false; which in this case is not really important, but might introduce another bug if I was prepared to live with the risk of starvation (and remove turn2). If the compiler would still re-order (haven't tested), cnt++ would be outside of the critical section. I'm thinking of exposing atomicStore and atomicLoad in core.atomic so folks have something to use until the compiler work is taken care of. At least then your code could still look somewhat normal.
Re: std.regexp vs std.regex [Re: RegExp.find() now crippled]
On Tue, 16 Nov 2010 14:24:32 -0500, Steve Teale steve.te...@britseyeview.com wrote: Steven Schveighoffer Wrote: I'm guessing you are referring to php's pcre vs posix regex? I think posix is marked as deprecated... Steve, No. I just meant that the library that comes with PHP seems happy to provide different ways of doing the same thing, as in for example, CURL, DOMDocument, and standard file operation wrappers. I don't know much about php's lib because I haven't used it enough to know the tendencies of library acceptance. But two different APIs for doing regex strike me as way more overlapping than CURL and file operation wrappers. I've been following D on and off for about seven or eight years now, so I don't subscribe too much to the 'when it's finished' argument. By now, it needs to work for real projects. D2 is much younger than that. D1 is complete (to use the term loosely), if you want to use that, its API will not change. There are quite a few projects using D1 for real work (I wrote one a few years ago). D2 is changing monthly, to the point where newer versions of phobos require newer versions of the compiler due to compiler bugs fixed or features added. I can't see how it can be considered finished. Don has recently brought up on the mailing list that we should identify the status of each module in the ddoc so people can understand the plans for that module before basing their work on it. I can see how spending lots of time working with something only to have it disappear can be hugely frustrating. -Steve
Re: std.date
On Tue, 16 Nov 2010 20:17:53 -0500, Jonathan M Davis jmdavisp...@gmx.com wrote: (DST is one of the stupidest ideas even IMHO; I don't even want to _think_ about how many bugs it's created) No, the stupidest idea was to *change* DST a few years ago. That had absolutely no purpose, I can't even believe we wasted tax dollars on pushing that through congress. -Steve
In praise of Go discussion on ycombinator
http://news.ycombinator.com/item?id=1912728 Andrei
Re: std.container.BinaryHeap + refCounted = WTF???
On Tue, 16 Nov 2010 15:47:07 -0500, dsimcha dsim...@yahoo.com wrote: I'm trying to use BinaryHeap in a multithreaded programming using std.parallelism/parallelfuture. I kept getting ridiculous segfaults and stuff, and when I looked into it in a debugger, I realized the crashes had to do with reference counting, probably caused by this line in BinaryHeap: private RefCounted!(Tuple!(Store, _store, size_t, _length), RefCountedAutoInitialize.no) _payload; Why the heck are the payload and the length being stored in such a weird way? IMHO BinaryHeap shouldn't use reference counting unless Store does. More generally, anything that uses reference counting, especially where unexpected, should come with a very strong warning in its ddoc so that people are aware of the hidden caveats, like copying it using memcpy() and sharing it across threads. I think in general containers don't work across multiple threads unless specifically designed to do that. dcollections containers would probably all fail if you tried to use them from multiple threads. That being said, I'm not a huge fan of reference counting period. Containers have no business being reference counted anyways, since their resource is memory, and should be handled by the GC. This doesn't mean pieces of it shouldn't be reference counted or allocated via malloc or whatever, but the object itself's lifetime should be managed by the GC IMO. Not coincidentally, this is how dcollections is set up. -Steve
Another Go vs Python vs D thread
http://news.ycombinator.com/item?id=1912728
Re: In praise of Go discussion on ycombinator
On Wed, 17 Nov 2010 00:10:54 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: http://news.ycombinator.com/item?id=1912728 Andrei I like go because every single feature go has is the best ever! yawn... -Steve
Re: In praise of Go discussion on ycombinator
On 11/16/10 9:21 PM, Steven Schveighoffer wrote: On Wed, 17 Nov 2010 00:10:54 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: http://news.ycombinator.com/item?id=1912728 Andrei I like go because every single feature go has is the best ever! yawn... -Steve I'm curious what the response to my example will be. So far I got one that doesn't even address it. Andrei
Re: In praise of Go discussion on ycombinator
On Wed, 17 Nov 2010 00:24:50 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 11/16/10 9:21 PM, Steven Schveighoffer wrote: On Wed, 17 Nov 2010 00:10:54 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: http://news.ycombinator.com/item?id=1912728 Andrei I like go because every single feature go has is the best ever! yawn... -Steve I'm curious what the response to my example will be. So far I got one that doesn't even address it. It's possible that you left your point as an exercise for the reader, so it may be lost. But it's not important. It's unlikely that you will convince goers that the language deficiencies are not worth the advantages. Only time will tell how popular/useful it will be. That one point you made would be a deal-killer for me (not that I'm close to using Go or anything, but no need to invest any more time on it after that). (cue retard's comment about D zealots not having any open mindedness) -Steve
Re: std.date
On Tuesday 16 November 2010 21:08:48 Steven Schveighoffer wrote: On Tue, 16 Nov 2010 20:17:53 -0500, Jonathan M Davis jmdavisp...@gmx.com wrote: (DST is one of the stupidest ideas even IMHO; I don't even want to _think_ about how many bugs it's created) No, the stupidest idea was to *change* DST a few years ago. That had absolutely no purpose, I can't even believe we wasted tax dollars on pushing that through congress. Granted, that was definitely stupid, but DST does cause bugs all over the place. Of course, for getting rid of it to help, you'd have to get rid of it globally, and even then, it wouldn't really help except in apps that didn't care about historic dates at all, because we've had DST in the past. Not to mention, many programs which work properly with DST would probably break if it were abolished. So, getting rid of it at this point probably wouldn't help anywhere near as much as it would seem (though it still wouldn't hurt my feelings any if they did). Regardless, its existence has caused all kinds of bugs for computers over the years. Now, changing it just causes bugs without fixing _anything_ as far as software is concerned, so that was just stupid, but I can dream of a world without DST... - Jonathan M Davis
Re: In praise of Go discussion on ycombinator
On 11/16/10 9:58 PM, Steven Schveighoffer wrote: On Wed, 17 Nov 2010 00:24:50 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 11/16/10 9:21 PM, Steven Schveighoffer wrote: On Wed, 17 Nov 2010 00:10:54 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: http://news.ycombinator.com/item?id=1912728 Andrei I like go because every single feature go has is the best ever! yawn... -Steve I'm curious what the response to my example will be. So far I got one that doesn't even address it. It's possible that you left your point as an exercise for the reader, so it may be lost. But it's not important. It's unlikely that you will convince goers that the language deficiencies are not worth the advantages. Only time will tell how popular/useful it will be. That one point you made would be a deal-killer for me (not that I'm close to using Go or anything, but no need to invest any more time on it after that). (cue retard's comment about D zealots not having any open mindedness) -Steve I think as soon as that defect registers at Go's creators, they will scramble to fix it one way or another. It's a blatant syntax design mistake. Andrei
Re: In praise of Go discussion on ycombinator
On 11/16/2010 22:24, Andrei Alexandrescu wrote: I'm curious what the response to my example will be. So far I got one that doesn't even address it. I really don't see the problem with requiring that '{' goes on the same line as 'if'. It's something you learn once and never forget because it is reinforced through constant exposure. After a day or two, '{' on a separate line will just feel wrong and raise an immediate alarm in your mind. I would even argue that Go's syntax actually makes code /easier/ to read and write. Let's say I see something like this in C/C++/D: if(blah()) { x++; } This is not my usual style, so I have to stop and think. It could be correct code written in another style, or it could be code that has been mangled during editing and now needs to be fixed. In Go, I /know/ it's mangled code, and I'm far less likely to encounter it, so I can find mangled code much more easily. A compiler error would be even better, but Go's syntax is already an improvement over C/C++/D. There are huge problems with Go that will probably keep me from ever using the language. This isn't one of them. -- Rainer Deyke - rain...@eldwood.com
Re: RFC, ensureHeaped
On 11/16/2010 21:53, Steven Schveighoffer wrote: It makes me think that this is going to be extremely confusing for a while, because people are so used to pure being equated with a functional language, so when they see a function is pure but takes mutable data, they will be scratching their heads. It would be awesome to make weakly pure the default, and it would also make it so we have to change much less code. Making functions weakly pure by default means that temporarily adding a tiny debug printf to any function will require a shitload of cascading 'impure' annotations. I would consider that completely unacceptable. (Unless, of course, purity is detected automatically without the use of annotations at all.) -- Rainer Deyke - rain...@eldwood.com
Re: RFC, ensureHeaped
On Tuesday 16 November 2010 20:53:04 Steven Schveighoffer wrote: On Tue, 16 Nov 2010 16:04:18 -0500, Jonathan M Davis jmdavisp...@gmx.com wrote: On Tuesday 16 November 2010 12:37:10 bearophile wrote: Jonathan M Davis: Pure is hard enough to deal with (especially since it we probably have made it the default, but it's too late for that now). Weakly pure on default isn't good for a language that is supposed to b e somewhat compatible with C syntax, I think it breaks too many C functions. Well, like I said, it's too late at this point, and really, it would be good to have a nice way to deal with C functions and purity (particularly since most of them are pure anyway), but the result at present is that most functions should be marked with pure. And if you're marking more functions with pure than not, that would imply that the default should be (at least ideally) impure. Regardless, however, it's not reasonable for D to go for impure rather than pure at this point. everything you are saying seems to be backwards, stop it! ;) 1. currently, the default is impure. 2. Most functions will naturally be weakly pure, so making *pure* the default would seem more useful. It seems backwards to me to think pure functions should be the default, I mean, this isn't a functional language! But you also have to forget everything you know about pure, because a weakly pure function is a very useful idiom, and it is most certainly not compatible with functional languages. It's both imperative and can accept and return mutable data. It makes me think that this is going to be extremely confusing for a while, because people are so used to pure being equated with a functional language, so when they see a function is pure but takes mutable data, they will be scratching their heads. It would be awesome to make weakly pure the default, and it would also make it so we have to change much less code. II was not trying to separate out weakly pure and strongly pure. pure is pure as far as marking the functions go. Whether that purity strong or weak depends on the parameters. And since most functions should at least be weakly pure, you end up marking most functions with pure. Ideally, you'd be marking functions for the uncommon case rather than the common one. I do think that a serious downside to using pure to mark weak purity is that it's pretty much going to bury the difference. You're not using global variables, so you mark the function as pure. Whether it's actually strongly pure and thus the compiler can optimize it is then an optimization detail (though you can of course figure it out if you want to). I expect that that's pretty much what the situation is going to end up being. Of course, the fact that C functions aren't marked as pure (even though in most cases they are) tends to put a damper on things, and the fact that you have to create multiple versions of the same function in different static if blocks when the purity depends on a templated function or type that the function is using also puts a major damper on things. However, the overall trend will likely be to mark next to everything as pure. It would certainly be cool to have weakly pure be the default, but that would require adding impure or something similar for cases where a function can't even be weakly pure. I would think that ideally, you'd make the default weakly pure, have impure (or something similar) to mark functions which can't even be weakly pure, and have full-on pure just be detected by the compiler (since it should be able to do that if weakly pure is the default). pure could be dropped entirely, or you could keep it to enforce that a function actually be strongly pure, forcing you to change the function if something changes to make it only weakly pure or outright impure. But I don't see that change having any chance of being made. Even if you kept pure and made it strongly pure only, adding impure (or whatever you wanted to call it) would mean adding a keyword, which always seems to go over badly around here. It would also mean changing a fair bit of code (mostly due to stdin, stdout, and C functions I expect). I think that it would be ultimately worth it though, as long as we were willing to pay the pain up front. - Jonathan M Davis
Re: RFC, ensureHeaped
On Tuesday 16 November 2010 23:03:05 Rainer Deyke wrote: On 11/16/2010 21:53, Steven Schveighoffer wrote: It makes me think that this is going to be extremely confusing for a while, because people are so used to pure being equated with a functional language, so when they see a function is pure but takes mutable data, they will be scratching their heads. It would be awesome to make weakly pure the default, and it would also make it so we have to change much less code. Making functions weakly pure by default means that temporarily adding a tiny debug printf to any function will require a shitload of cascading 'impure' annotations. I would consider that completely unacceptable. (Unless, of course, purity is detected automatically without the use of annotations at all.) It has already been argued that I/O should be exempt (at least for debugging purposes), and I think that that would could be acceptable for weakly pure functions. But it's certainly true that as it stands, dealing with I/O and purity doesn't work very well. And since you have to try and mark as much as possible pure (to make it weakly pure at least) if you want much hope of being able to have much of anything be strongly pure, it doesn't take long before you can't actually have I/O much of anywhere - even for debugging. It's definitely a problem. - Jonathan M Davis
Re: In praise of Go discussion on ycombinator
On Tuesday 16 November 2010 22:55:42 Rainer Deyke wrote: On 11/16/2010 22:24, Andrei Alexandrescu wrote: I'm curious what the response to my example will be. So far I got one that doesn't even address it. I really don't see the problem with requiring that '{' goes on the same line as 'if'. It's something you learn once and never forget because it is reinforced through constant exposure. After a day or two, '{' on a separate line will just feel wrong and raise an immediate alarm in your mind. I would even argue that Go's syntax actually makes code /easier/ to read and write. Let's say I see something like this in C/C++/D: if(blah()) { x++; } This is not my usual style, so I have to stop and think. It could be correct code written in another style, or it could be code that has been mangled during editing and now needs to be fixed. In Go, I /know/ it's mangled code, and I'm far less likely to encounter it, so I can find mangled code much more easily. A compiler error would be even better, but Go's syntax is already an improvement over C/C++/D. There are huge problems with Go that will probably keep me from ever using the language. This isn't one of them. Personally, I _hate_ the style of putting the brace on the same line, so I'm instantly biased as far as that goes, but the fact that the language does not actually require that you put the braces in a particular place and yet you have to to make it work properly is definitely a big problem. It's one that can be gotten around easily enough with strict formatting guidelines, but C-based languages are supposed to be pretty much freely formattable (otherwise why even make it optional), so it's a definite faux pas on their part. It's one that they should be able to fix without too much trouble, so hopefully it won't really be an issue in the long run, but it's definitely troubling. At least with a language like Python, it's extremely clear that formatting matters. - Jonathan M Davis
Re: std.date
Jonathan M Davis Wrote: Honestly, leap seconds are complete stupidity with regards to computers. They just complicate things. I think, it's ok, computers work with nominal time and synchronize with world as needed. Hardly you can catch a bug with leap seconds.
Re: In praise of Go discussion on ycombinator
On Wed, 17 Nov 2010 00:58:28 -0500, Steven Schveighoffer wrote: On Wed, 17 Nov 2010 00:24:50 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: On 11/16/10 9:21 PM, Steven Schveighoffer wrote: On Wed, 17 Nov 2010 00:10:54 -0500, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: http://news.ycombinator.com/item?id=1912728 Andrei I like go because every single feature go has is the best ever! yawn... -Steve I'm curious what the response to my example will be. So far I got one that doesn't even address it. It's possible that you left your point as an exercise for the reader, so it may be lost. But it's not important. It's unlikely that you will convince goers that the language deficiencies are not worth the advantages. Only time will tell how popular/useful it will be. That one point you made would be a deal-killer for me (not that I'm close to using Go or anything, but no need to invest any more time on it after that). The problem pointed out can readily be fixed by requiring statements to have at least one token. go has much more severe problems than that. And there are plenty of bugs and mistakes in D, harder to fix, that could be deemed deal-killers by someone with an axe to grind. It's not an intellectually honest approach. (cue retard's comment about D zealots not having any open mindedness) -Steve No zealots are open minded. That's why I'm a supporter of various things but not a zealot about anything.
Re: explore current scope, or other hack
On Mon, 15 Nov 2010 21:35:19 +0100 Simen kjaeraas simen.kja...@gmail.com wrote: spir denis.s...@gmail.com wrote: On Mon, 15 Nov 2010 12:44:24 -0500 bearophile bearophileh...@lycos.com wrote: spir: 1. name objects automatically I need some objects to know their name (as field on themselves). the only solution I can else imagine is for the user write: x = ...; x.name = x; What if you have two or more references to the same object? I'm not sure what you mean. The said objects are patterns (instances of a Pattern class hierachy). And indeed, they are multiply referenced (that's precisely the point of writing a grammar ;-). The two (or more) references could not be referred to by the same name. Sure, they would point to the same object, but how could the object know whether its functions were called from x or from y? While you may use the same name everywhere for the same object, the x in function foo is a different one from that in function bar, not to mention across modules. Oh, yes! I see the point, now, thank you. But in the present case (and a few others where I had to name objects), only the birth name is relevant. Here is an example from written using the library I'm writing, I'm sure it's self-explaining. I overloaded opCall in the top Pattern class so that it names the object: == test code auto digits = new String(new Klass(0-9)); digits.name = digits; auto DOT = new Literal(.); DOT.name = DOT; auto integer = new Compose(digits,DOT,digits); integer.name = integer; // output writeln(digits.view()); writeln(integer.view()); writeln-); integer.test(123.45); writeln-); integer.test(123.); === output == digits=[0-9]+ integer=(digits DOT digits) - pattern : integer=(digits DOT digits) text : 123.45 outcome : (123 . 45) - Test Error: see outcome below. - pattern : integer=(digits DOT digits) text : 123. outcome : *failure* - * End Of Text Error: end of text reached while matching pattern digits=[0-9]+ at index 4 * If I may come with a solution, it would be something like this: mixin template New!( T, string name ) { mixin( auto ~ name ~ = new T(\ ~ name ~ \)); } Thank you again, I'll explore this path. Denis -- -- -- -- -- -- -- vit esse estrany ☣ spir.wikidot.com
Re: effect of a label on following block
On Mon, 15 Nov 2010 19:34:46 +0300, Ellery Newcomer ellery-newco...@utulsa.edu wrote: My gut feeling is that the if statement's behavior is wrong and the while statement's is correct, but it could go either way. I agree, I think case with 'when' works as specs say. No need for a rationale for what can be adequately explained as a compiler bug There is still correct but unexpected behaviour. I found this on bugtracker http://d.puremagic.com/issues/show_bug.cgi?id=199 The rationale was I don't want to change this because it could break existing code, and there doesn't seem to be a compelling reason to do so. Well. :( Please to report to bugzilla I'll report about if/while inconsistency. -- Using Opera's revolutionary email client: http://www.opera.com/mail/
[Issue 2954] [tdpl] Appalling bug in associative arrays (D2 only)
http://d.puremagic.com/issues/show_bug.cgi?id=2954 Don clugd...@yahoo.com.au changed: What|Removed |Added Keywords||patch CC||clugd...@yahoo.com.au --- Comment #3 from Don clugd...@yahoo.com.au 2010-11-16 01:10:11 PST --- The fix for bug 2684 was incorrect; it was too general. We can't skip the implicit conversion in all cases where the arrays are equality comparable. For example, this code: char[char[3]] ac; dchar[3] d = abcd; ac[d] = 'w'; gives a poor error message: bug.d(6): Error: array equality comparison type mismatch, dchar[3u] vs char [3u] instead of cannot implicitly convert PATCH: (1) Add this function to cast.c /*** * See if both types are arrays that can be compared * for equality without any casting. Return !=0 if so. * This is to enable comparing things like an immutable * array with a mutable one. */ int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2) { t1 = t1-toBasetype(); t2 = t2-toBasetype(); if ((t1-ty == Tarray || t1-ty == Tsarray || t1-ty == Tpointer) t2-ty == t1-ty) { if (t1-nextOf()-implicitConvTo(t2-nextOf()) = MATCHconst || t2-nextOf()-implicitConvTo(t1-nextOf()) = MATCHconst) return 1; } return 0; } (2) expression.c line 8580 case Taarray: { TypeAArray *taa = (TypeAArray *)t1; +/* We can skip the implicit conversion if they differ only by + * constness (Bugzilla 2684, see also bug 2954b) + */ +if (!arrayTypeCompatibleWithoutCasting(e2-loc, e2-type, taa-index) ) -if (!arrayTypeCompatible(e2-loc, e2-type, taa-index)) { e2 = e2-implicitCastTo(sc, taa-index);// type checking } type = taa-next; -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 4414] ICE(cgcs.c) Taking item of static array returned by function
http://d.puremagic.com/issues/show_bug.cgi?id=4414 Per �ngstr�m d-bugzi...@autark.se changed: What|Removed |Added CC||d-bugzi...@autark.se --- Comment #4 from Per �ngstr�m d-bugzi...@autark.se 2010-11-16 03:41:16 PST --- (Digital Mars D Compiler v2.050) I have a variation on this theme: int f(lazy int[2] iarr) { return iarr[1]; } void main() { int[2] iarr; f(iarr); } Internal error: ../ztc/cgcs.c 359 It works if I remove the lazy keyword. Of course, lazy is quite meaningless in this context, but anyhow. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 2828] Typedef'ed template struct incorrectly recognized as an inner struct
http://d.puremagic.com/issues/show_bug.cgi?id=2828 Don clugd...@yahoo.com.au changed: What|Removed |Added Status|NEW |RESOLVED Resolution||FIXED --- Comment #2 from Don clugd...@yahoo.com.au 2010-11-16 04:59:58 PST --- Fixed svn 614. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 5221] New: entity.c: Merge Walter's list with Thomas'
http://d.puremagic.com/issues/show_bug.cgi?id=5221 Summary: entity.c: Merge Walter's list with Thomas' Product: D Version: D1 D2 Platform: All OS/Version: All Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: ibuc...@ubuntu.com --- Comment #0 from Iain Buclaw ibuc...@ubuntu.com 2010-11-16 05:35:25 PST --- Created an attachment (id=815) Merge Walter's list with Thomas' Thought it might prove useful to DMD to merge the lists, and remove that dumb, slow linear search of theirs in entity.c Regards -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 5221] entity.c: Merge Walter's list with Thomas'
http://d.puremagic.com/issues/show_bug.cgi?id=5221 --- Comment #1 from Iain Buclaw ibuc...@ubuntu.com 2010-11-16 05:45:59 PST --- Random examples of tests that fail on DMD: static assert('\check;'==10003); static assert('\lsim;'==8818); static assert('\numero;'==8470); static assert('\urcorn;'==8989); static assert('\Zdot;'==379); Regards -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 5221] entity.c: Merge Walter's list with Thomas'
http://d.puremagic.com/issues/show_bug.cgi?id=5221 --- Comment #2 from Iain Buclaw ibuc...@ubuntu.com 2010-11-16 06:07:53 PST --- (From update of attachment 815) diff -ur src.orig/entity.c src/entity.c --- src.orig/entity.c2010-03-31 01:26:18.0 +0100 +++ src/entity.c2010-11-16 14:01:58.423055202 + @@ -9,6 +9,7 @@ #include string.h +#include ctype.h /* * Convert from named entity to its encoding. @@ -23,7 +24,6 @@ unsigned short value; }; -#if IN_GCC static NameId namesA[]={ Aacgr,0x0386, aacgr,0x03AC, @@ -42,7 +42,9 @@ agr, 0x03B1, Agrave, 0x00C0, agrave, 0x00E0, +alefsym, 0x2135, aleph,0x2135, +Alpha,0x0391, alpha,0x03B1, Amacr,0x0100, amacr,0x0101, @@ -76,9 +78,11 @@ bcong,0x224C, Bcy, 0x0411, bcy, 0x0431, +bdquo,0x201E, becaus, 0x2235, bepsi,0x220D, bernou, 0x212C, +Beta, 0x0392, beta, 0x03B2, beth, 0x2136, Bgr, 0x0392, @@ -162,6 +166,7 @@ CHcy, 0x0427, chcy, 0x0447, check,0x2713, +Chi, 0x03A7, chi, 0x03C7, cir, 0x25CB, circ, 0x005E, @@ -178,6 +183,7 @@ coprod, 0x2210, copy, 0x00A9, copysr, 0x2117, +crarr,0x21B5, cross,0x2717, cuepr,0x22DE, cuesc,0x22DF, @@ -281,17 +287,21 @@ Eogon,0x0118, eogon,0x0119, epsi, 0x220A, +Epsilon, 0x0395, +epsilon, 0x03B5, epsis,0x220A, epsiv,0x03B5, equals, 0x003D, equiv,0x2261, erDot,0x2253, esdot,0x2250, +Eta, 0x0397, eta, 0x03B7, ETH, 0x00D0, eth, 0x00F0, Euml, 0x00CB, euml, 0x00EB, +euro, 0x20AC, excl, 0x0021, exist,0x2203, NULL, 0 @@ -325,6 +335,7 @@ frac56, 0x215A, frac58, 0x215D, frac78, 0x215E, +frasl,0x2044, frown,0x2322, NULL, 0 }; @@ -425,6 +436,7 @@ iocy, 0x0451, Iogon,0x012E, iogon,0x012F, +Iota, 0x0399, iota, 0x03B9, iquest, 0x00BF, isin, 0x220A, @@ -450,6 +462,7 @@ }; static NameId namesK[]={ +Kappa,0x039A, kappa,0x03BA, kappav, 0x03F0, Kcedil, 0x0136, @@ -523,7 +536,9 @@ lozf, 0x2726, lpar, 0x0028, lrarr2, 0x21C6, +lrm, 0x200E, lrhar2, 0x21CB, +lsaquo, 0x2039, lsh, 0x21B0, lsim, 0x2272, lsqb, 0x005B, @@ -561,6 +576,7 @@ mldr, 0x2026, mnplus, 0x2213, models, 0x22A7, +Mu, 0x039C, mu, 0x03BC, mumap,0x22B8, NULL, 0 @@ -573,8 +589,7 @@ nap, 0x2249, napos,0x0149, natur,0x266E, -// nbsp, 0x00A0, -nbsp, 32,// make non-breaking space appear as space +nbsp, 0x00A0, Ncaron, 0x0147, ncaron, 0x0148, Ncedil, 0x0145, @@ -631,6 +646,7 @@ nsupE,0x2289, Ntilde, 0x00D1, ntilde, 0x00F1, +Nu, 0x039D, nu, 0x03BD, num, 0x0023, numero, 0x2116, @@ -671,10 +687,13 @@ ohgr, 0x03C9, ohm, 0x2126, olarr,0x21BA, +oline,0x203E, Omacr,0x014C, omacr,0x014D, Omega,0x03A9, omega,0x03C9, +Omicron, 0x039F, +omicron, 0x03BF, ominus, 0x2296, oplus,0x2295, or, 0x2228, @@ -709,6 +728,7 @@ PHgr, 0x03A6, phgr, 0x03C6, Phi, 0x03A6, +phi, 0x03C6, phis, 0x03C6, phiv, 0x03D5, phmmat, 0x2133, @@ -780,13 +800,16 @@ rgr, 0x03C1, rhard,0x21C1, rharu,0x21C0, +Rho, 0x03A1, rho, 0x03C1,
[Issue 5222] New: label prepending block in 'ThenStatement' breaks creating new scope
http://d.puremagic.com/issues/show_bug.cgi?id=5222 Summary: label prepending block in 'ThenStatement' breaks creating new scope Product: D Version: D1 D2 Platform: x86 OS/Version: Windows Status: NEW Severity: minor Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: elfy...@gmail.com --- Comment #0 from Nick Voronin elfy...@gmail.com 2010-11-16 07:17:46 PST --- //case 1 { l1: { int v; } v = 5; // works, block after label does not introduce new scope } // case 2 { while(1) l2: { int v; } v = 5; // error, v is undefined, seems correct as // WhileStatement: //while ( Expression ) ScopeStatement } // case 3 { if(1) l3: { int v; } v = 5; // works! seems inconsistent and incorrect as // ThenStatement: //ScopeStatement } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 5223] New: [qtd] Cannot use default value with function parameter of struct type
http://d.puremagic.com/issues/show_bug.cgi?id=5223 Summary: [qtd] Cannot use default value with function parameter of struct type Product: D Version: D2 Platform: Other OS/Version: Linux Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: samu...@voliacable.com --- Comment #0 from Max Samukha samu...@voliacable.com 2010-11-16 09:36:29 PST --- Struct constructors are disregarded when a struct parameter is constructed out of a default value: struct S2 { } struct S { int x; this(S2 s2) { } void foo(S s = S(S2)) { } } void main() { S s; s.foo(); // error } Error: cannot implicitly convert expression (S2()) of type S2 to int. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 5223] [qtd] Cannot use default value with function parameter of struct type
http://d.puremagic.com/issues/show_bug.cgi?id=5223 --- Comment #1 from Max Samukha samu...@voliacable.com 2010-11-16 09:48:10 PST --- Even simpler test-case: struct S { this(int x) { } void foo(S s = S(42)) { } } void main() { S s; s.foo(); // error } Error: more initializers than fields of S -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 5224] New: std.algorithm.remove!(SwapStrategy.unstable) doesn't work
http://d.puremagic.com/issues/show_bug.cgi?id=5224 Summary: std.algorithm.remove!(SwapStrategy.unstable) doesn't work Product: D Version: D2 Platform: x86_64 OS/Version: Windows Status: NEW Severity: normal Priority: P2 Component: Phobos AssignedTo: nob...@puremagic.com ReportedBy: ruzicic.aleksan...@gmail.com --- Comment #0 from Aleksandar Ruzicic ruzicic.aleksan...@gmail.com 2010-11-16 20:52:45 CET --- Example code below shows that there is a bug in remove() using unstable SwapStrategy - it removes wrong element from an array. Using default swap strategy works as expected. --- module test; import std.algorithm; import std.stdio, std.algorithm; void main(string[] args) { auto a = [1, 2, 3, 4]; print(initial, a); auto i = a.indexOf(3); writefln(indexOf(3) = %s, i); if (i -1) { print(remove!(SwapStrategy.unstable), remove!(SwapStrategy.unstable)(a, i)); } /* Tested with DMD v2.049 under Windows 7: dmd -run test.d initial: 1 2 3 4 (length = 4) indexOf(3) = 2 remove!(SwapStrategy.unstable): 4 2 3 (length = 3) it removed element at index 0 rather than element at index 2 */ } void print(string name, int[] array) { writef(%s: , name); foreach (elem; array) { writef(%s , elem); } writefln((length = %s), array.length); } --- -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---