Re: Weak story about D's relationship to garbage collection?
On Tuesday, 17 November 2015 at 02:28:04 UTC, Brian wrote: about one article: https://www.quora.com/Which-language-has-the-brightest-future-in-replacement-of-C-between-D-Go-and-Rust-And-Why/answer/Andrei-Alexandrescu really? In this respect will be improved? I don't like Go, but I hope to have improved D. D has two problems with garbage collection one: There's little ways to work around it when /necessary/ two: The current GC is slow and bad. Both are actively being worked on, even if it doesn't seem so. I should have an alternate GC to demo soon-ish and I believe deadalnix is also working on an alternate GC. Meanwhile, there has been a lot of talk(and some work) on ownership semantics, compiler lifetime analysis, and RC implementation. Bye.
Re: Persistent list
On Monday, 16 November 2015 at 00:00:18 UTC, Andrei Alexandrescu wrote: This illustrates a simple procedural problem. The entire point of my posting a simple example of a complete container was to avoid hypotheticals such as this. The code is there and shows that no, physical const does not suffice. At least I don't know how to do it. If you think it does there's one way to show it, it's easy - write the code that does it. We could sit on our testes all day long, speculate how things ought to work, and feel awfully smart in the process. It's very easy to do. Hell, I've done it more than too many times. What's more difficult is have a positive, constructive approach that builds on a weak solution to improve it. This is the kind of dialog we need to foster. Sadly, design I would love to see also doesn't seem to be implementable but because of different issue - missing scope control. I gave a quick go to implement something that shows my desired semantics - https://gist.github.com/mihails-strasuns-sociomantic/1d7529eef723b1132564 (only essential functionality to show stuff). As you may see it is totally different from your initial proposal - this is why making constructive feedback is rather hard :) But chosing between breaking physical const via @mutable and waiting until we finally get lond wanted scope control tools I am very much in favor of the latter.
Re: Persistent list
On 11/16/15 9:00 PM, Meta wrote: On Tuesday, 17 November 2015 at 01:49:05 UTC, Steven Schveighoffer wrote: I think it's quite clear that inout in its current form is a point of huge confusion. I want to work to fix this perception (and fix the broken corners of the implementation). What I would ask is for those who at the moment dislike it keep an open mind, and hold back on your pitchforks. I need to prepare a suitable defense, and it's difficult to shake off the "confusing and complex" albatross without having sufficient time to create something that is easy to understand/explain for something that is conceptually simple, but requires a complex proof. What I am afraid of is that someone makes a decision that something is bad, and by the time a good defense, or workable proposal is mounted, the answer is "we already discussed that, it's bad. Let's move on." At least with this, we have a feature that is part of the language, so is unlikely to go away. But I'd hate to see a mob of PR requests that remove inout from all of phobos/druntime before I can counter this. I think inout is worth saving, it needs a few tweaks and a good explanation. Regarding my question on StackOverflow, I understand that I had an inaccurate picture of how inout works, which was causing my problem. These are also problems with const and immutable to a degree. I can understand the confusion. However, here is the truth: you only need to define opEquals for const or mutable. You don't need both (if your wrapped type defines both, then the const one can be called in both cases), and you don't need an inout version. Here is why: inout is simply *equivalent to const* (but without the implicit casting) when there is no inout on the return type. Originally this was flagged as an error, but because of templates and IFTI, it made writing template functions much harder. But here is a working system that has no inout: struct Wrapper(T) { T t; static if(is(typeof(const(T).init == const(T).init))) { bool opEquals(const(Wrapper) other) const { return t == other.t; } bool opEquals(const(T) val) const { return t == val; } } else { bool opEquals(Wrapper other) { return t == other.t; } bool opEquals(T val) { return t == val; } } } struct Test { bool opEquals(Test t) { return true; } } struct Test2 { bool opEquals(inout(Test2) t) inout { return true; } } struct Test3 { bool opEquals(const(Test3) t) const { return true; } } void foo(T)() { Wrapper!T a, b; assert(a == b); assert(a == T()); } void main() { foo!Test(); foo!Test2(); foo!Test3(); } This doesn't solve the case that has only a mutable and immutable opEquals, and no const version, but you get the idea. However, inout is like a fourth qualifier that you have to deal with that is separate from const and immutable, due to how it currently works. In that light, I still don't think it pulls its weight. What user will have the presence of mind to define their Foobar type with an inout/const/immutable toString function? Almost none, and so Nullable!Foobar.opEquals cannot be inout. In almost all cases I've come across, inout isn't another thing that needs handling. It's simply an alternative to const (when applicable). In cases where it is applicable, you write MUCH LESS code. Where it breaks down is composition (i.e. creating a type with an inout member) and nested functions. I first encountered this problem trying to get Nullable.toString to work with inout, and couldn't. That's my main gripe with inout. This may have hit one of the warts of inout. -Steve
Weak story about D's relationship to garbage collection?
about one article: https://www.quora.com/Which-language-has-the-brightest-future-in-replacement-of-C-between-D-Go-and-Rust-And-Why/answer/Andrei-Alexandrescu really? In this respect will be improved? I don't like Go, but I hope to have improved D.
Re: Persistent list
On Tuesday, 17 November 2015 at 01:49:05 UTC, Steven Schveighoffer wrote: I think it's quite clear that inout in its current form is a point of huge confusion. I want to work to fix this perception (and fix the broken corners of the implementation). What I would ask is for those who at the moment dislike it keep an open mind, and hold back on your pitchforks. I need to prepare a suitable defense, and it's difficult to shake off the "confusing and complex" albatross without having sufficient time to create something that is easy to understand/explain for something that is conceptually simple, but requires a complex proof. What I am afraid of is that someone makes a decision that something is bad, and by the time a good defense, or workable proposal is mounted, the answer is "we already discussed that, it's bad. Let's move on." At least with this, we have a feature that is part of the language, so is unlikely to go away. But I'd hate to see a mob of PR requests that remove inout from all of phobos/druntime before I can counter this. I think inout is worth saving, it needs a few tweaks and a good explanation. -Steve Regarding my question on StackOverflow, I understand that I had an inaccurate picture of how inout works, which was causing my problem. These are also problems with const and immutable to a degree. However, inout is like a fourth qualifier that you have to deal with that is separate from const and immutable, due to how it currently works. In that light, I still don't think it pulls its weight. What user will have the presence of mind to define their Foobar type with an inout/const/immutable toString function? Almost none, and so Nullable!Foobar.opEquals cannot be inout. I first encountered this problem trying to get Nullable.toString to work with inout, and couldn't. That's my main gripe with inout.
Re: Persistent list
On Tuesday, 17 November 2015 at 01:49:05 UTC, Steven Schveighoffer wrote: [...] I think inout is worth saving, it needs a few tweaks and a good explanation. -Steve Sounds interesting. Might your ideas help to fix the difficulties inout has with composability? That would be excellent. Joseph
Re: Persistent list
On 11/16/15 8:21 PM, deadalnix wrote: On Tuesday, 17 November 2015 at 00:30:39 UTC, Steven Schveighoffer wrote: On 11/16/15 6:56 PM, deadalnix wrote: On Monday, 16 November 2015 at 22:30:55 UTC, Andrei Alexandrescu wrote: On 11/16/2015 05:02 PM, Jonathan M Davis wrote: It's just that you use inout instead of const. How is that worse? The short answer is my perception is inout is too complicated for what it does. -- Andrei I'm happy to read this. inout has the wrong cost/complexity ratio. It doesn't solve the problem generally (one want to return type depending on argument qualifier in general, not only for type qualifiers) while having a high complexity. The problem it solves is to provide a mechanism that allows one to safely apply the same qualifiers to the return type, but have the inputs be constant *throughout the function*. A templated function doesn't do this, you can have conditional code, or unchecked method calls that can modify the data when possible. Of course, if this isn't important, then the template solution is usable. My take is that whenever you use inout is when you would normally use const, but const doesn't allow what you need. If your function doesn't need const inside the function, then you shouldn't use inout. To me, it feels like inout is simple, but the implementation has warts that make it seem inconsistent. There is also the issue that nested inout is super-confusing, because now you have layers of inout, each layer meaning possibly something different. If we could somehow fix the nested part (and allow types with inout members inside there), I think inout would be less intimidating. Here is, IMO, the point you are missing. There many qualifier you'd like to have depend on other qualifiers. For instance : void doSomeThingAndCallBack(maybe_pure void function() callback) pure_if_maybe_pure_argument_is_pure { callback(); } This already works with templates. If all you care about is writing a function that has the *ability* to take any kind of input, then templates are perfect for that. What inout solves above templates (and note, you can combine inout AND templates), is that during the function call, the parameter is not modified -- guaranteed by the compiler (as much as it can). Templates cannot offer that. To me the maybe_pure solution doesn't even come close to inout's utility (what does it guarantee beside being able to take different types of parameters?). For those who care about const or try to use const (and immutable) to provide API guarantees on parameters, it becomes unwieldy to both specify "yes! I can take any qualified type of parameter" and "no! I promise I won't modify them." Const fills this void, but has the the issue of blindly coloring everything const, locking up all your data for things like function chaining. Inout is supposed to fix this one problem, and should be a seamless replacement for const in those cases. It obviously is not. Thus, the power/complexity ratio is not good. inout is for one specific thing, I see it to be unrelated to templates. It's more of an extension of const. The complexity, IMO, is not necessarily huge (perhaps in the current implementation, I'm not sure), but the consistency is terrible. There are things you just should be able to do, and the compiler won't do them. Inevitably, the templates people write end up trying to do these things (because they are logically correct), and the compiler spits out cryptic "cannot call this function" errors. These can be difficult to figure out. Also, yes, the implementation is B0rken :) Still it has gotten much better over time (or I learned the hard way to stay into the patterns that works ?). It has definitely gotten better over time. It used to be that if you used any kind of template with an inout parameter, it wouldn't compile. -Steve
Re: Persistent list
On Sunday, 15 November 2015 at 12:56:27 UTC, Andrei Alexandrescu wrote: On 11/14/2015 05:49 PM, Timon Gehr wrote: List uses RC internally. I don't think the UB casts will stay for the final version, unless you are willing to completely dilute the meaning of const in ways that Walter has explicitly expressed will not be done in the past. As I mentioned, he's okay with changing the language to make the casts well defined. -- Andrei Ok Here is what I propose as a spec. This is rough brain dump, but that is something I think can be a good start. There are mutable data that are thread local and immutable data that are shared. const is a wildcard type qualifier that can refers to mutable or immutable data. immutable is supposed to be effectively immutable. This means that the compiler is allowed to store these data in ro segments and optimize redundant loads without having to prove that no aliasing write occur in between. One can cast away const or immutable. It is a @system operation and this cast needs to be explicit. If the underlying data is in ro segment, any write is effectively undefined behavior (most likely a fault). If the underlying data is allocated on the head (using the GC or malloc for instance) then writing to it will effectively update the underlying memory. Any read from a const or immutable reference after these write can is undefined. Granted the write was not UB : 1/ Any read from a mutable reference in another thread is undefined behavior unless the writing thread release after write and the reading one acquire (or any stronger memory barrier). 2/ Any read from a mutable reference in the same thread will see the updates in a sequentially consistent manner. Sounds good ? This definitively allow to do RC for const/immutable without throwing away optimization opportunities.
Re: Persistent list
On 11/16/15 8:11 PM, Meta wrote: On Tuesday, 17 November 2015 at 00:30:39 UTC, Steven Schveighoffer wrote: The problem it solves is to provide a mechanism that allows one to safely apply the same qualifiers to the return type, but have the inputs be constant *throughout the function*. A templated function doesn't do this, you can have conditional code, or unchecked method calls that can modify the data when possible. Of course, if this isn't important, then the template solution is usable. My take is that whenever you use inout is when you would normally use const, but const doesn't allow what you need. If your function doesn't need const inside the function, then you shouldn't use inout. To me, it feels like inout is simple, but the implementation has warts that make it seem inconsistent. There is also the issue that nested inout is super-confusing, because now you have layers of inout, each layer meaning possibly something different. If we could somehow fix the nested part (and allow types with inout members inside there), I think inout would be less intimidating. -Steve I don't mean to derail this thread, but I also am not really crazy about inout in its current form. Its transitive nature is one issue (though that can't be changed due to const and immutable also being transitive), but also the fact that inout is basically a fourth qualifier, which causes a lot of pain when you're wrapping other types. For example, calling opEquals on a wrapped struct inside the opEquals of the wrapper struct (which is marked as inout) when the wrapped struct does not also define an inout opEquals, will not call the mutable opEquals of the wrapped struct. It *will not* compile unless the wrapped struct also defines an inout opEquals, no matter the constness of the wrapper or the wrappee. Basically, wrapper types cannot with inout. http://stackoverflow.com/questions/31516713/escaping-from-inout-hell I think it's quite clear that inout in its current form is a point of huge confusion. I want to work to fix this perception (and fix the broken corners of the implementation). What I would ask is for those who at the moment dislike it keep an open mind, and hold back on your pitchforks. I need to prepare a suitable defense, and it's difficult to shake off the "confusing and complex" albatross without having sufficient time to create something that is easy to understand/explain for something that is conceptually simple, but requires a complex proof. What I am afraid of is that someone makes a decision that something is bad, and by the time a good defense, or workable proposal is mounted, the answer is "we already discussed that, it's bad. Let's move on." At least with this, we have a feature that is part of the language, so is unlikely to go away. But I'd hate to see a mob of PR requests that remove inout from all of phobos/druntime before I can counter this. I think inout is worth saving, it needs a few tweaks and a good explanation. -Steve
Re: Persistent list
On Tuesday, 17 November 2015 at 00:30:39 UTC, Steven Schveighoffer wrote: On 11/16/15 6:56 PM, deadalnix wrote: On Monday, 16 November 2015 at 22:30:55 UTC, Andrei Alexandrescu wrote: On 11/16/2015 05:02 PM, Jonathan M Davis wrote: It's just that you use inout instead of const. How is that worse? The short answer is my perception is inout is too complicated for what it does. -- Andrei I'm happy to read this. inout has the wrong cost/complexity ratio. It doesn't solve the problem generally (one want to return type depending on argument qualifier in general, not only for type qualifiers) while having a high complexity. The problem it solves is to provide a mechanism that allows one to safely apply the same qualifiers to the return type, but have the inputs be constant *throughout the function*. A templated function doesn't do this, you can have conditional code, or unchecked method calls that can modify the data when possible. Of course, if this isn't important, then the template solution is usable. My take is that whenever you use inout is when you would normally use const, but const doesn't allow what you need. If your function doesn't need const inside the function, then you shouldn't use inout. To me, it feels like inout is simple, but the implementation has warts that make it seem inconsistent. There is also the issue that nested inout is super-confusing, because now you have layers of inout, each layer meaning possibly something different. If we could somehow fix the nested part (and allow types with inout members inside there), I think inout would be less intimidating. -Steve Here is, IMO, the point you are missing. There many qualifier you'd like to have depend on other qualifiers. For instance : void doSomeThingAndCallBack(maybe_pure void function() callback) pure_if_maybe_pure_argument_is_pure { callback(); } You'll note that this is the same problem as inout solves. Thing is inout is complex, but only solve a small subset of the problem. Thus, the power/complexity ratio is not good. Also, yes, the implementation is B0rken :) Still it has gotten much better over time (or I learned the hard way to stay into the patterns that works ?).
Re: Persistent list
On Tuesday, 17 November 2015 at 00:30:39 UTC, Steven Schveighoffer wrote: The problem it solves is to provide a mechanism that allows one to safely apply the same qualifiers to the return type, but have the inputs be constant *throughout the function*. A templated function doesn't do this, you can have conditional code, or unchecked method calls that can modify the data when possible. Of course, if this isn't important, then the template solution is usable. My take is that whenever you use inout is when you would normally use const, but const doesn't allow what you need. If your function doesn't need const inside the function, then you shouldn't use inout. To me, it feels like inout is simple, but the implementation has warts that make it seem inconsistent. There is also the issue that nested inout is super-confusing, because now you have layers of inout, each layer meaning possibly something different. If we could somehow fix the nested part (and allow types with inout members inside there), I think inout would be less intimidating. -Steve I don't mean to derail this thread, but I also am not really crazy about inout in its current form. Its transitive nature is one issue (though that can't be changed due to const and immutable also being transitive), but also the fact that inout is basically a fourth qualifier, which causes a lot of pain when you're wrapping other types. For example, calling opEquals on a wrapped struct inside the opEquals of the wrapper struct (which is marked as inout) when the wrapped struct does not also define an inout opEquals, will not call the mutable opEquals of the wrapped struct. It *will not* compile unless the wrapped struct also defines an inout opEquals, no matter the constness of the wrapper or the wrappee. Basically, wrapper types cannot with inout. http://stackoverflow.com/questions/31516713/escaping-from-inout-hell
Re: Persistent list
On 11/16/15 6:56 PM, deadalnix wrote: On Monday, 16 November 2015 at 22:30:55 UTC, Andrei Alexandrescu wrote: On 11/16/2015 05:02 PM, Jonathan M Davis wrote: It's just that you use inout instead of const. How is that worse? The short answer is my perception is inout is too complicated for what it does. -- Andrei I'm happy to read this. inout has the wrong cost/complexity ratio. It doesn't solve the problem generally (one want to return type depending on argument qualifier in general, not only for type qualifiers) while having a high complexity. The problem it solves is to provide a mechanism that allows one to safely apply the same qualifiers to the return type, but have the inputs be constant *throughout the function*. A templated function doesn't do this, you can have conditional code, or unchecked method calls that can modify the data when possible. Of course, if this isn't important, then the template solution is usable. My take is that whenever you use inout is when you would normally use const, but const doesn't allow what you need. If your function doesn't need const inside the function, then you shouldn't use inout. To me, it feels like inout is simple, but the implementation has warts that make it seem inconsistent. There is also the issue that nested inout is super-confusing, because now you have layers of inout, each layer meaning possibly something different. If we could somehow fix the nested part (and allow types with inout members inside there), I think inout would be less intimidating. -Steve
Re: Formal Review of std.range.ndslice
On Monday, 16 November 2015 at 22:45:35 UTC, Jack Stouffer wrote: This is the start of the two week formal review for the proposed std.range.ndslice. This new addition to the standard library would add the ability to create and manipulate multi-dimensional random access ranges in a way that will be very familiar to those of you who use numpy. This has the potential to give D a huge boost in popularity in numerical and scientific applications. One thing that stands out is the number of symbols in the Slice struct that have simple "///" doc comments. That is, they show up in the generated documentation without any explanation.
Re: Persistent list
On Monday, 16 November 2015 at 22:30:55 UTC, Andrei Alexandrescu wrote: On 11/16/2015 05:02 PM, Jonathan M Davis wrote: It's just that you use inout instead of const. How is that worse? The short answer is my perception is inout is too complicated for what it does. -- Andrei I'm happy to read this. inout has the wrong cost/complexity ratio. It doesn't solve the problem generally (one want to return type depending on argument qualifier in general, not only for type qualifiers) while having a high complexity.
Re: Implement the "unum" representation in D ?
On Sunday, 15 November 2015 at 04:19:21 UTC, Lionello Lunesu wrote: On 09/11/15 04:38, Richard Davies wrote: Yeah, I got curious too. I spend some time on it yesterday and had a stab at writing it in D. Hi. I send a email to John Gustafson yesterday, re this thread. He replied as follows: "There are efforts underway worldwide to support unums in C, Python, Julia, Java, and now D. And the book has only been out for nine months!" Nick
Re: Persistent list
On Sunday, 15 November 2015 at 20:11:02 UTC, Dicebot wrote: On Sunday, 15 November 2015 at 19:51:09 UTC, Andrei Alexandrescu wrote: Just to clarify - is that referring to the part "We need to change that if we want things like composable containers that work with const." or to the "I think it's a good thing to want" part? -- Andrei Second part. I don't see a case for const containers at all. Fully immutable functional style ones - sure, I have actually experimented implementing cache this way in https://github.com/Dicebot/mood/blob/master/source/mood/storage/generic_cache.d (thing that powers blog.dicebot.lv). But what would you use const containers for? Mixing mutable and immutable elements in one container? That sounds like a source of much trouble. For the variance. If you wan't write in the container, you make make it so that ConstContainer implicitly convert to ConstContainer if B inherit from A. You can have code that accept mutable and const container as well, which is useful, because you can cram immutable container in the ro section.
Re: Persistent list
On 11/16/15 5:35 PM, Andrei Alexandrescu wrote: On 11/16/2015 05:30 PM, Steven Schveighoffer wrote: I'll reiterate what I said elsewhere: inout is better, safer, and easier to maintain than the template solution. Do you have a working solution in dpaste? No change to the return types please. -- Andrei Ah, where it breaks down is emplace uses an internal struct with a T, which is inout(const(Node)*). So you *are* hitting one of the limitations of inout, one that Dmitry brought up. I stand corrected. I think it can be fixed, we need to make structs that contain inout member variables legal as long as they only exist on inout function stacks. It may be possible to fix emplace for inout by changing the ctor of the internal struct to inout instead of typing T as inout, but I'm not sure. In this case, in order to work around, you have to cast when you use emplace, somewhat defeating the safety of emplace :( http://dpaste.dzfl.pl/182e2ac5da2d The only other weird part is where you see inout(const(Node)*) in the fixed ctor. This is because it's a different type than inout(Node*), it's like const(immutable(Node)*), the pointer itself is const, but the data it points at is still immutable. -Steve
Re: Persistent list
On 11/16/15 4:49 PM, Andrei Alexandrescu wrote: On 11/16/2015 04:36 PM, Steven Schveighoffer wrote: We can and should fix this. I'll file an issue if none has been filed. That's great! -- Andrei https://issues.dlang.org/show_bug.cgi?id=15347 Note that the trigger is the ctor and dtor of the struct. Each adds worse layers of error message horror :) -Steve
Formal Review of std.range.ndslice
This is the start of the two week formal review for the proposed std.range.ndslice. This new addition to the standard library would add the ability to create and manipulate multi-dimensional random access ranges in a way that will be very familiar to those of you who use numpy. This has the potential to give D a huge boost in popularity in numerical and scientific applications. A quick run down for those that are not familiar with the process. After two weeks, the PR author (Ilya Yaroshenko) will have time to make proposed changes. Then, when the author feels it's ready, the PR will go to a vote. In the vote, everyone in the community has a say, but if one of the main contributors or maintainers has a very negative opinion (for example) that will carry more weight. Github: https://github.com/D-Programming-Language/phobos/pull/3397 dub: http://code.dlang.org/packages/dip80-ndslice docs: http://dtest.thecybershadow.net/results/bac6211c1d73b2cf62bc18c9844c8c82c92c21e1/5c6071ca953cf113febd8786b4b68916cbb2cdaf/ previous discussion: http://forum.dlang.org/thread/rilfmeaqkailgpxoz...@forum.dlang.org
Re: Persistent list
On 11/16/2015 05:30 PM, Steven Schveighoffer wrote: I'll reiterate what I said elsewhere: inout is better, safer, and easier to maintain than the template solution. Do you have a working solution in dpaste? No change to the return types please. -- Andrei
Re: Persistent list
On 11/16/2015 05:02 PM, Jonathan M Davis wrote: It's just that you use inout instead of const. How is that worse? The short answer is my perception is inout is too complicated for what it does. -- Andrei
Re: Persistent list
On Monday, 16 November 2015 at 16:58:24 UTC, Lionello Lunesu wrote: If it's RC we want, then @mutable is an axe when what we need is a scalpel. The non-observability comes from the fact the refcount is changed when the caller has lost its (const) reference and constness is a moot point. Changing refcount is fine now, provided the object is not immutable. As far as other outstanding const references go, these already expect changes to happen. This is what makes refcount special and provably safe to mutate. As long as we can ensure the object is not immutable, the object is allowed to change its own refcount. But refcount needs to be special cased, somehow, or else we'll end up with some C++ like `mutable`. I'm not a compiler or language-design guy, but something strikes me as odd about this whole discussion. It seems to me that a lot of it depends on a presumption that one wants the refcount field to be user-visible, and that therefore it must also have some user-visible type and perhaps some attributes. But at bottom, doesn't a refcount field behave more like a vptr for a class instance, which is there in the underlying storage model but is not directly user-visible? Or similar to whatever metadata is used for the start/end pointers of a dynamic array? As such, is there any reason for a refcount to be user-visible in the first place, other than to the compiler-internals implementor? I have to wonder whether a refcount field could be appended to the data payload via some sort of @rc attribute instead of as an explicit class/struct member, and perhaps referenced via some implicit pseudo member when the field needs to be manipulated. Then there perhaps wouldn't need to be any requirement to define any new kinds of storage categories for this field, in the same way that there isn't an explicit storage category for a vptr field. I could be all wet here with such ideas, but I'm just wondering ...
Re: Persistent list
On 11/16/15 5:02 PM, Jonathan M Davis wrote: On Monday, 16 November 2015 at 21:47:07 UTC, Andrei Alexandrescu wrote: On 11/16/2015 04:18 PM, Jonathan M Davis wrote: When you can templatize the function on the type that would otherwise be inout, then there really isn't any reason to use inout. But what do you do when you're dealing with a member function - especially on a class? I don't know of any way to templatize a member function on the type of the this pointer/reference, but maybe there's a template feature with which I'm not familiar enough. But even if there _is_ such a feature, it won't work for virtual functions. It does. Write one-liners that forward to the template function, as shown in http://dpaste.dzfl.pl/52a3013efe34 (search the page for QList). -- Andrei Well, that does reduce the code duplication, but you're still forced to have up to three separate functions to get each of the different return types (even if they are then simply wrapper functions). And compare that with simply declaring the same function once with its implementation internal to itself. It's just that you use inout instead of const. How is that worse? I'll reiterate what I said elsewhere: inout is better, safer, and easier to maintain than the template solution. Example: static QList cons(QList)(T head, auto ref QList lst) if (is(Unqual!QList == List)) Tell me how cons guarantees not to modify lst? Is it convention or compiler guarantees? find the bug: static QList cons(QList)(T head, auto ref QList lst) if (is(Unqual!QList == List)) { List result; result._allocator = either(lst.allocator, theAllocator); import std.conv : emplace; void[] buf = result.allocator.allocate(Node.sizeof); auto n = emplace!(const Node)(buf, head, lst.root, 1); incRef(lst.root); result.root = n; static if(!is(QList == const)) lst.root = lst.root.next; return result; } The point of const is to provide a mechanism to those reading the signature to say "this function will NOT change the parameter, and the compiler guarantees it." The point of inout is the same, but allows returning a portion of the parameters without resorting to casts or wrappers. -Steve
Re: Persistent list
On Monday, 16 November 2015 at 21:36:41 UTC, Steven Schveighoffer wrote: I just did the naive thing and slapped inout on your functions. This is what I got: persistent_list2.d(146): Error: cannot implicitly convert expression (( List!(immutable(int)) __slList1681 = List(null, null); , __slList1681).this(n, this.allocator())) of type List!(immutable(int)) to inout(List!(immutable(int))) WTF! Wow is that hideous. I don't recall ever seeing error messages that obtuse. We can and should fix this. I'll file an issue if none has been filed. Please do. - Jonathan M Davis
Re: Persistent list
On Monday, 16 November 2015 at 21:47:07 UTC, Andrei Alexandrescu wrote: On 11/16/2015 04:18 PM, Jonathan M Davis wrote: When you can templatize the function on the type that would otherwise be inout, then there really isn't any reason to use inout. But what do you do when you're dealing with a member function - especially on a class? I don't know of any way to templatize a member function on the type of the this pointer/reference, but maybe there's a template feature with which I'm not familiar enough. But even if there _is_ such a feature, it won't work for virtual functions. It does. Write one-liners that forward to the template function, as shown in http://dpaste.dzfl.pl/52a3013efe34 (search the page for QList). -- Andrei Well, that does reduce the code duplication, but you're still forced to have up to three separate functions to get each of the different return types (even if they are then simply wrapper functions). And compare that with simply declaring the same function once with its implementation internal to itself. It's just that you use inout instead of const. How is that worse? There are cases where inout doesn't work as well as const does due to limitations with inout, but in many (most?) cases, the only difference between using const and inout is that you're typing const instead of inout. So, if anything, that makes it sound like fixing inout so that it works in those other cases would be better than avoiding it in favor of splitting out the implementation into a separate function and having multiple wrapper functions in the API. - Jonathan M Davis
Re: Persistent list
On Monday, 16 November 2015 at 21:25:52 UTC, Timon Gehr wrote: On 11/16/2015 10:18 PM, Jonathan M Davis wrote: I don't know of any way to templatize a member function on the type of the this pointer/reference, but maybe there's a template feature with which I'm not familiar enough. Indeed there is. class C{ void foo(this T)(){ pragma(msg, T); } } class D: C{} void main(){ auto c=new const(C)(); c.foo(); auto d=new immutable(D)(); d.foo(); } Cool. That's good to know about. Thanks. - Jonathan M Davis
Re: Persistent list
On 11/16/2015 04:36 PM, Steven Schveighoffer wrote: We can and should fix this. I'll file an issue if none has been filed. That's great! -- Andrei
Re: Persistent list
On 11/16/2015 04:18 PM, Jonathan M Davis wrote: When you can templatize the function on the type that would otherwise be inout, then there really isn't any reason to use inout. But what do you do when you're dealing with a member function - especially on a class? I don't know of any way to templatize a member function on the type of the this pointer/reference, but maybe there's a template feature with which I'm not familiar enough. But even if there _is_ such a feature, it won't work for virtual functions. It does. Write one-liners that forward to the template function, as shown in http://dpaste.dzfl.pl/52a3013efe34 (search the page for QList). -- Andrei
Re: Persistent list
On 11/16/15 3:48 PM, Andrei Alexandrescu wrote: I think the main problem is the difficulty of getting from "I want to make this method work with mutable and nonconst data" to "I have a working solution using inout". Again, it's not that hard. I have had little trouble with using it instead of const where it is appropriate. There are a couple rough edges, but you haven't hit them yet. The semantics is complex and difficult. Error messages are horrifying. Even explaining code that works is hard. Once a solution works, trying to change it in meaningful ways again makes the code not work, and again with uninformative error messages. So there's resistance to changing working code. I just did the naive thing and slapped inout on your functions. This is what I got: persistent_list2.d(146): Error: cannot implicitly convert expression (( List!(immutable(int)) __slList1681 = List(null, null); , __slList1681).this(n, this.allocator())) of type List!(immutable(int)) to inout(List!(immutable(int))) WTF! This is not how it used to be. What the hell is __slList1681? And what is List(null, null)? This has to be some sort of lowering that was added to the compiler, I have never seen such horrible messages for inout. How it should look: Error: cannot implicitly convert expression List(n, allocator) of type List!(immutable(int)) to inout(List!(immutable(int))) Note, this is not an inout problem. If I put immutable(List) as the return type, I get: persistent_list2.d(146): Error: cannot implicitly convert expression (( List!(immutable(int)) __slList1681 = List(null, null); , __slList1681).this(n, this.allocator())) of type List!(immutable(int)) to immutable(List!(immutable(int))) We can and should fix this. I'll file an issue if none has been filed. At the same time, we have a wonderful language ready to help with features that didn't exist when we introduced inout. Search http://dpaste.dzfl.pl/52a3013efe34 for QList - it's restricted properly, works very well, and is easy to explain. Actually, it's not easier to explain or maintain, and the solution existed before inout was introduced (in fact one of the reasons *to* use inout was to avoid QList-like solutions). Example: static QList cons(QList)(T head, auto ref QList lst) if (is(Unqual!QList == List)) Tell me how cons guarantees not to modify lst? Is it convention or compiler guarantees? find the bug: static QList cons(QList)(T head, auto ref QList lst) if (is(Unqual!QList == List)) { List result; result._allocator = either(lst.allocator, theAllocator); import std.conv : emplace; void[] buf = result.allocator.allocate(Node.sizeof); auto n = emplace!(const Node)(buf, head, lst.root, 1); incRef(lst.root); result.root = n; static if(!is(QList == const)) lst.root = lst.root.next; return result; } The point of const is to provide a mechanism to those reading the signature to say "this function will NOT change the parameter, and the compiler guarantees it." I remember reading originally why Walter put const into the language -- because C++ developers who used const extensively to provide guarantees simply wouldn't use D if it didn't provide a mechanism to do this. I don't recall the exact wording, but I'm sure it's somewhere in the ng. The point of inout was to provide what const does, but allow you to hook the output const flavor to the input const flavor. That's all. Walter and I think inout didn't turn out well. It became a little monster mastering a swamp. Template solutions can drain that swamp, make the monster disappear, and build nice things on that field. I disagree, and appeals to authority is not very convincing, no matter how colorful. I think inout works great for what it's good at. It has some finishing to do, but the concept is sound and works fine. It's a perfect fit for containers in general. In this particular case it's not necessary. We absolutely should fix the error messages, they are not very helpful. I think we should slowly marginalize inout - discourage it from new code, document and publicize better alternatives, the works. Because we have a poor error message? I can assure you this is not endemic to inout. In this case, it appears to work only because of your cast of _allocator to mutable whenever you access it via allocator. Other than that, the only other member is the node pointer, which is const. Effectively, A list's data is always const, so there is no reason to make the struct itself const. Plenty of reason. The list may be member in an object. Also, if you don't have const List you can't compose List with itself. Huh? Mutable List casts to const List just fine. If I always return a mutable List from a composing operation, then it works for const List as well (both as the receiver of the return value and as the parameter). What I meant to say is that a const(List) isn't particularly needed to guard the List's data. That is already const. -Steve
Re: Wanted: Review manager for std.experimental.range.ndslice
On Monday, 16 November 2015 at 21:01:03 UTC, Jack Stouffer wrote: On Monday, 16 November 2015 at 20:12:37 UTC, Ilya wrote: It is very close draft: http://wiki.dlang.org/Review/Process I volunteer then, if you'll have me. Great! Thank you :)
Re: And in the (quasi-)comedy section…
On Monday, 16 November 2015 at 17:05:14 UTC, Marc Schütz wrote: On Monday, 16 November 2015 at 14:33:26 UTC, Russel Winder wrote: A quote from @SarcasticRover: New studies show that Mars' moon Phobos is slowly breaking up under pressure… but really, who isn't? Life is hard. You know, I saw this piece of news, but refrained from making a comment here. Though it was tempting :-P heh... +1
Re: Persistent list
On 11/16/2015 10:18 PM, Jonathan M Davis wrote: I don't know of any way to templatize a member function on the type of the this pointer/reference, but maybe there's a template feature with which I'm not familiar enough. Indeed there is. class C{ void foo(this T)(){ pragma(msg, T); } } class D: C{} void main(){ auto c=new const(C)(); c.foo(); auto d=new immutable(D)(); d.foo(); } But even if there _is_ such a feature, it won't work for virtual functions. Yup.
Re: Our template emission strategy is broken
On Monday, 16 November 2015 at 09:05:16 UTC, Marco Leise wrote: Am Wed, 11 Nov 2015 14:23:15 + schrieb Martin Nowak : Think of that for a moment, no package manager allows you to have cycles in your dependencies. There are package managers that allow packages to mutually depend on each other. Order is established by qualifying the dependency similar to how you declare an owning and a weak reference in a parent/child pointer relation. LOL. Yeah. I expect that 99+% of Linux boxes contain mutually dependent packages. Circular dependencies make setting up Gentoo that much more entertaining (e.g. IIRC, OpenSSL and Cyrus SASL depend on each other normally). At least some dependencies can be eliminated with binary packages, because they're only build dependencies, but not all of them are that way, unfortunately. - Jonathan M Davis
Re: Persistent list
On Monday, 16 November 2015 at 20:48:49 UTC, Andrei Alexandrescu wrote: I think we should slowly marginalize inout - discourage it from new code, document and publicize better alternatives, the works. When you can templatize the function on the type that would otherwise be inout, then there really isn't any reason to use inout. But what do you do when you're dealing with a member function - especially on a class? I don't know of any way to templatize a member function on the type of the this pointer/reference, but maybe there's a template feature with which I'm not familiar enough. But even if there _is_ such a feature, it won't work for virtual functions. So, while I completely agree that it's cleaner to avoid inout when it's not needed, from what I can see, there are cases where you really don't have an alternative aside from duplicating the entire function. So, it does seem like on some level, we're stuck using inout, even if we can avoid it in many cases. - Jonathan M Davis
Re: Wanted: Review manager for std.experimental.range.ndslice
On Monday, 16 November 2015 at 20:12:37 UTC, Ilya wrote: It is very close draft: http://wiki.dlang.org/Review/Process I volunteer then, if you'll have me.
Re: Persistent list
On Monday, 16 November 2015 at 18:37:18 UTC, Andrei Alexandrescu wrote: On 11/16/2015 12:51 PM, Steven Schveighoffer wrote: List tail() const I'd like tail to be qualifier-idempotent, i.e. return const for const and non-const for non-const. -- Andrei I don't have a compiler at hand right now, but doesn't this work? auto tail(this U)() const { assert(root); auto n = root.next; incRef(n); return U(n, allocator); }
Re: Persistent list
On 11/16/2015 03:38 PM, Steven Schveighoffer wrote: On 11/16/15 2:37 PM, Andrei Alexandrescu wrote: On 11/16/2015 01:55 PM, Steven Schveighoffer wrote: On 11/16/15 1:37 PM, Andrei Alexandrescu wrote: On 11/16/2015 12:51 PM, Steven Schveighoffer wrote: List tail() const I'd like tail to be qualifier-idempotent, i.e. return const for const and non-const for non-const. -- Andrei Why? const(int)[] isn't const, why should List!(const(int)) be? I'm keeping an eye toward other containers and also more general use. It's a common need. -- Andrei Anywhere const can work, inout should work as well. The one exception as I've described is when you create and build a (im)mutable result, then converting it to const. In this case, you have to build it at once. Otherwise, the compiler can't tell whether this mutable thing you are constructing is safe to cast to inout (and whatever flavor it needs to cast to upon exit). I think the main problem is the difficulty of getting from "I want to make this method work with mutable and nonconst data" to "I have a working solution using inout". The semantics is complex and difficult. Error messages are horrifying. Even explaining code that works is hard. Once a solution works, trying to change it in meaningful ways again makes the code not work, and again with uninformative error messages. So there's resistance to changing working code. At the same time, we have a wonderful language ready to help with features that didn't exist when we introduced inout. Search http://dpaste.dzfl.pl/52a3013efe34 for QList - it's restricted properly, works very well, and is easy to explain. Walter and I think inout didn't turn out well. It became a little monster mastering a swamp. Template solutions can drain that swamp, make the monster disappear, and build nice things on that field. I think we should slowly marginalize inout - discourage it from new code, document and publicize better alternatives, the works. In this case, it appears to work only because of your cast of _allocator to mutable whenever you access it via allocator. Other than that, the only other member is the node pointer, which is const. Effectively, A list's data is always const, so there is no reason to make the struct itself const. Plenty of reason. The list may be member in an object. Also, if you don't have const List you can't compose List with itself. Andrei
Re: Persistent list
On 11/16/15 2:37 PM, Andrei Alexandrescu wrote: On 11/16/2015 01:55 PM, Steven Schveighoffer wrote: On 11/16/15 1:37 PM, Andrei Alexandrescu wrote: On 11/16/2015 12:51 PM, Steven Schveighoffer wrote: List tail() const I'd like tail to be qualifier-idempotent, i.e. return const for const and non-const for non-const. -- Andrei Why? const(int)[] isn't const, why should List!(const(int)) be? I'm keeping an eye toward other containers and also more general use. It's a common need. -- Andrei Anywhere const can work, inout should work as well. The one exception as I've described is when you create and build a (im)mutable result, then converting it to const. In this case, you have to build it at once. Otherwise, the compiler can't tell whether this mutable thing you are constructing is safe to cast to inout (and whatever flavor it needs to cast to upon exit). In this case, it appears to work only because of your cast of _allocator to mutable whenever you access it via allocator. Other than that, the only other member is the node pointer, which is const. Effectively, A list's data is always const, so there is no reason to make the struct itself const. -Steve
Re: Wanted: Review manager for std.experimental.range.ndslice
On Monday, 16 November 2015 at 19:56:01 UTC, Jack Stouffer wrote: On Monday, 16 November 2015 at 03:05:03 UTC, Ilya Yaroshenko wrote: Hello, Review manager for N-dimensional ranges is wanted What does the job entail? It is very close draft: http://wiki.dlang.org/Review/Process
Re: Wanted: Review manager for std.experimental.range.ndslice
On Monday, 16 November 2015 at 03:05:03 UTC, Ilya Yaroshenko wrote: Hello, Review manager for N-dimensional ranges is wanted What does the job entail?
Re: Persistent list
On 11/16/2015 02:07 PM, Timon Gehr wrote: On 11/16/2015 07:37 PM, Andrei Alexandrescu wrote: On 11/16/2015 12:51 PM, Steven Schveighoffer wrote: List tail() const I'd like tail to be qualifier-idempotent, i.e. return const for const and non-const for non-const. -- Andrei "Qualifier-idempotent" would rather mean that taking the tail once results in the same qualifier as taking it twice. https://en.wikipedia.org/wiki/Idempotence Jesus. Fine. -- Andrei
Re: Persistent list
On 11/16/2015 01:55 PM, Steven Schveighoffer wrote: On 11/16/15 1:37 PM, Andrei Alexandrescu wrote: On 11/16/2015 12:51 PM, Steven Schveighoffer wrote: List tail() const I'd like tail to be qualifier-idempotent, i.e. return const for const and non-const for non-const. -- Andrei Why? const(int)[] isn't const, why should List!(const(int)) be? I'm keeping an eye toward other containers and also more general use. It's a common need. -- Andrei
Re: Wanted: Review manager for std.experimental.range.ndslice
On Monday, 16 November 2015 at 09:56:57 UTC, Andrea Fontana wrote: On Monday, 16 November 2015 at 03:05:03 UTC, Ilya Yaroshenko wrote: Hello, Review manager for N-dimensional ranges is wanted Docs (see PR for latest version): http://dtest.thecybershadow.net/artifact/website-7a646fdea76569e009844cdee5c93edab10980ca-cdcb694c40ec47acf88b0aa878e1623e/web/phobos-prerelease/std_experimental_range_ndslice.html PR: https://github.com/D-Programming-Language/phobos/pull/3397 DUB: http://code.dlang.org/packages/dip80-ndslice Best Regards, Ilya Nice work! If I have a matrix like 1 2 3 4 iota(4).sliced(2,2); Is there a way to transform it to: 1 1 1 2 2 2 1 1 1 2 2 2 1 1 1 2 2 2 3 3 3 4 4 4 3 3 3 4 4 4 3 3 3 4 4 4 or 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 4 0 0 0 0 0 0 0 ? Of course the inverse operation seems quite easier to do using slices. ``` import std.algorithm, std.range, std.stdio; auto m = iota(1, 5).sliced(2, 2); "%(%(%s %)\n%)\n".writefln(m); auto w = createSlice!int(6, 6); w[1..$, 1..$].strided!0(3).strided!1(3)[] = m; "%(%(%s %)\n%)\n".writefln(w); foreach(i; 0..3) foreach(j; 0..3) w[i..$, j..$].strided!0(3).strided!1(3)[] = m; "%(%(%s %)\n%)\n".writefln(w); ``` Prints: 1 2 3 4 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 4 0 0 0 0 0 0 0 1 1 1 2 2 2 1 1 1 2 2 2 1 1 1 2 2 2 3 3 3 4 4 4 3 3 3 4 4 4 3 3 3 4 4 4 --Ilya
Re: Persistent list
On 11/16/2015 07:37 PM, Andrei Alexandrescu wrote: On 11/16/2015 12:51 PM, Steven Schveighoffer wrote: List tail() const I'd like tail to be qualifier-idempotent, i.e. return const for const and non-const for non-const. -- Andrei "Qualifier-idempotent" would rather mean that taking the tail once results in the same qualifier as taking it twice. https://en.wikipedia.org/wiki/Idempotence
Re: Persistent list
On 11/16/15 1:37 PM, Andrei Alexandrescu wrote: On 11/16/2015 12:51 PM, Steven Schveighoffer wrote: List tail() const I'd like tail to be qualifier-idempotent, i.e. return const for const and non-const for non-const. -- Andrei Why? const(int)[] isn't const, why should List!(const(int)) be? -Steve
Re: Persistent list
On 11/16/2015 12:51 PM, Steven Schveighoffer wrote: List tail() const I'd like tail to be qualifier-idempotent, i.e. return const for const and non-const for non-const. -- Andrei
Re: Persistent list
On 11/16/15 1:15 PM, Dmitry Olshansky wrote: On 16-Nov-2015 19:44, Steven Schveighoffer wrote: On 11/14/15 3:42 AM, Dmitry Olshansky wrote: On 14-Nov-2015 02:10, Andrei Alexandrescu wrote: * Lines 141-152: I couldn't make tail() work with inout. Generally I'm very unhappy about inout. I don't know how to use it. Everything I read about it is extremely complicated compared to its power. I wish we removed it from the language and replaced it with an understandable idiom. I can't agree more. Every time dealing with inout when I finally think I grok how it works the next instant I see that it doesn't do what I expect. For me inout inevitably stops at the boundary of being unnable to have List!(inout(T)) and the like. One thing we could allow is types that contain inout member variables, but ONLY in the context of inout functions. In other words, you can create a type for it, but can only use it in the context of an inout function. inout should be indistinguishable of const but the moment you pass inout(T) to a template it becomes murky. Appender!(inout(int)) - which qualifier to instantiate? The idea is, you would instantiate Appender!(inout(int)) :) Should be fine to use inside an inout function. The problem is, you couldn't use it outside inout, so you couldn't use this as the return type. But inside the function, you could use it. Right now, you can effectively do this with arrays, since inout(T)[] works fine, and this can essentially map to some fictional template instantiation ArrayStruct!(inout(T)) (or some other way to instantiate ArrayStruct!T and wrap this in an attribute that means tail). But arrays enjoy both auto casting that tail member to other flavors, and also the compiler allows you to create inout arrays inside an inout function. We can at least solve the latter pretty easily. The closer we can move to have an actual ArrayStruct template that works just like a real array, the closer we are to having a complete solution. A List!(inout(T)) outside an inout function has no meaning. This is why we disallowed it. However, my belief is that it's the lack of a mechanism to apply an attribute to the tail of some struct that prevents the most utility here. If you returned a List!(inout(T)) there is no way to magically convert it to a List!(const(T)) or List!(immutable(T)). Consider that Node in this code has a "const(Node)* next" as its tail. Note, I think I was wrong with this. The Node has a Node *next, but root is labelled as const. In the end, this code is a bad example of what is wrong with inout, because inout shouldn't be used on it anyway. Looks a lot like tail-const problem. That is immutable T!E has no way to convert to T!(immutable E) and similarly to T!(const E). It all depends on how E is used in T. Tail-const is a specific problem that *could* be solved if we could provide a mechanism to do this, but providing the mechanism isn't *required*. -Steve
Re: Style guide is very inconsistent
On Monday, 16 November 2015 at 17:47:10 UTC, Jonathan M Davis wrote: [...] Thanks for going into so much detail.
Re: Persistent list
On 16-Nov-2015 19:44, Steven Schveighoffer wrote: On 11/14/15 3:42 AM, Dmitry Olshansky wrote: On 14-Nov-2015 02:10, Andrei Alexandrescu wrote: * Lines 141-152: I couldn't make tail() work with inout. Generally I'm very unhappy about inout. I don't know how to use it. Everything I read about it is extremely complicated compared to its power. I wish we removed it from the language and replaced it with an understandable idiom. I can't agree more. Every time dealing with inout when I finally think I grok how it works the next instant I see that it doesn't do what I expect. For me inout inevitably stops at the boundary of being unnable to have List!(inout(T)) and the like. One thing we could allow is types that contain inout member variables, but ONLY in the context of inout functions. In other words, you can create a type for it, but can only use it in the context of an inout function. inout should be indistinguishable of const but the moment you pass inout(T) to a template it becomes murky. Appender!(inout(int)) - which qualifier to instantiate? A List!(inout(T)) outside an inout function has no meaning. This is why we disallowed it. However, my belief is that it's the lack of a mechanism to apply an attribute to the tail of some struct that prevents the most utility here. If you returned a List!(inout(T)) there is no way to magically convert it to a List!(const(T)) or List!(immutable(T)). Consider that Node in this code has a "const(Node)* next" as its tail. I believe we should be able to achieve both. Looks a lot like tail-const problem. That is immutable T!E has no way to convert to T!(immutable E) and similarly to T!(const E). Overall I see const/immutable a fine thing at low-level scope but not applicable at all to high-level constructs. If something is conceptually const - its the task of implementation which may rely on physical const qualifier somewhere deep inside. -Steve -- Dmitry Olshansky
Re: Bitfield bug
On Monday, 16 November 2015 at 11:20:48 UTC, Lionello Lunesu wrote: On 16/11/15 18:05, deadalnix wrote: https://issues.dlang.org/show_bug.cgi?id=15305 Any taker ? I don't think this is that hard to fix, and this is really bad. https://github.com/D-Programming-Language/phobos/pull/3815 <3 <3 <3 <3
Re: All functions COMDAT on OSX
On Monday, 16 November 2015 at 17:09:05 UTC, Marc Schütz wrote: On Monday, 16 November 2015 at 14:37:33 UTC, bitwise wrote: On Monday, 16 November 2015 at 08:15:39 UTC, Walter Bright wrote: On 11/15/2015 8:44 PM, bitwise wrote: https://issues.dlang.org/show_bug.cgi?id=15342 DMD emits all functions as COMDAT on OSX. I'm guessing this was originally a workaround of some kind...does anybody know the story? Thanks, Bit It enables: 1. the linker to remove duplicates (happens with templates and other things) 2. the linker to remove unreferenced COMDATs I understand what it's for, but it's incorrect behaviour to have _all_ functions being emitted as comdat. Non-template functions shouldn't be coalesced in this way. If you compile the code example in the bug report with *any* compiler other than DMD/OSX, the example will fail as described, with a linker error. The example compares dmd/osx with gcc/osx, but the code will also fail with ldc/osx. And although I don't have time to check, I'm pretty sure it will fail with dmd/win as well. If you look at the code I cited, this is obviously a hack: [...] #if TARGET_OSX s->Sclass = SCcomdat; #else s->Sclass = SCglobal; #endif for (Dsymbol *p = fd->parent; p; p = p->parent) { if (p->isTemplateInstance()) { s->Sclass = SCcomdat; break; } } [...] FWIW, that's been in the source since somewhen between 2.025 and 2.026: https://github.com/D-Programming-Language/dmd/commit/00337ef8d8c4c1c08da68f95963e2fe1658a49ec Unfortunately there are no intermediate commits in the repo, because only released versions have been imported during the switch to Git. Yeah... I'm wondering how much chaos it would cause to fix this, because it's a blocking issue for fixing shared libs on OSX. To support shared libraries, I'de have to add a unique linux style global ctor/dtor to each module. LDC already does this. There is no alternative solution. I could special case the ctor/dtors in DMD not to be COMDAT, but the effect would be the same as fixing the bug anyways, which would be that people would get linker errors if they linked(or are currently linking) the same module multiple times in their binary. This breakage is necessary to implement shared libraries, and facilitate proper linking behaviour. Bit
Re: Persistent list
On 11/16/15 12:42 PM, Steven Schveighoffer wrote: On 11/16/15 12:35 PM, Steven Schveighoffer wrote: I'm afraid without a working example, I can't figure out what's *supposed* to work with inout/const. Update, saw your other note. Working now, trying to figure out how to do this correctly without any duplication (or wrapping). -Steve OK, I have figured it out. inout isn't necessary here at all because everything is const internally. For example, you had this: List tail() { assert(root); auto n = root.next; incRef(n); return List(n, allocator); } /// ditto const(List) tail() const { assert(root); auto n = root.next; incRef(n); return const(List)(n, allocator); } Which I was able to replace with this: List tail() const { assert(root); auto n = root.next; incRef(n); return List(n, allocator); } In any case, I think the choice between const and inout is confusing, and warrants a more in-depth explanation (when should I choose const or inout?) -Steve
Re: Style guide is very inconsistent
On Monday, 16 November 2015 at 16:42:57 UTC, maik klein wrote: On Monday, 16 November 2015 at 14:26:41 UTC, Jonathan M Davis wrote: On Monday, 16 November 2015 at 14:09:45 UTC, maik klein wrote: [...] Per the style guide, = Eponymous Templates [...] Okay thanks, but I am still not sure about my example. I am pretty sure that at least "any" should be camel case because it's a value, but what about "Contains"? It's neither a type nor a eponymous template. My guess is that it should also be camel case? So it would be contains!C.any!T ? Okay. Your Any template should clearly be camelCased, because its result is a bool. The same goes for ContainsImpl. Contains is a weird one though. It's pretty abnormal to use a template that's not a type, a function, an eponymous template, or a mixin template. Contains doesn't actually evaluate to anything on its own. It seems like it's just there so that you can have two sets of variadic arguments, which would tend to imply that it should be camelCased as part of any. However, the style guide says that non-eponymous templates should be PascalCased (though that _usually_ only applies to mixin templates), so a strict reading of the style guide would indicate that Contains should be PascalCased. Of course, using a verb like contains is also a bit weird when it's really just holding a list of types so that they can essentially be passed as the first argument to any. So, I'd probably be inclined to rename the templates to something that was closer to what they're actually doing. e.g. TypeList!(T, U, V).containsAny!(W, X, Y) But even that's not all that great, since TypeList is then specifically tied to containsAny even though it doesn't really look like it is at first glance, and the name TypeList is generic enough that it does seem like you might want to reuse it elsewhere when it really couldn't be. Maybe ContainsList!(T, U, V).containsAny(W, X, Y) would be better? I don't know. Coming up with a name for this is hard. What you really want is something like listsIntersect!((T, U, V), (W, X, Y)) or ListsIntersect!(AliasSeq!(T, U, V), AliasSeq!(W, X, Y)) but there's no way to express it that like that in D (the AliasSeqs auto-expand into a single AliasSeq). The requirement for two sets of variadic template arguments just makes this awkward. In any case, a strict reading of the style guide would seem to indicate that Contains should be PascalCased, because it's not an eponymous template, but given how rare what you're trying to do is, I doubt that much of anyone would complain if you used camelCase instead. I'd probably go with PascalCase though. - Jonathan M Davis
Re: Persistent list
On 11/16/15 12:35 PM, Steven Schveighoffer wrote: I'm afraid without a working example, I can't figure out what's *supposed* to work with inout/const. Update, saw your other note. Working now, trying to figure out how to do this correctly without any duplication (or wrapping). -Steve
Re: Persistent list
On 11/16/15 11:03 AM, Steven Schveighoffer wrote: On 11/14/15 10:44 AM, Andrei Alexandrescu wrote: That doesn't work for me with my unittests, I get: I'm such an idiot, I depended on dpaste to run the unit test, but forgot to check the unit test button. So technically, my updated version *parses* correctly :) Looking in more depth... I can't get your original code to work, so it's hard for me to figure out what is wrong. Using 2.069.1, I have the following error (after factoring out `either`, which I'm assuming is a new function): Stevens-MacBook-Pro:testd steves$ dmd -unittest persistent_list.d /Users/steves/.dvm/compilers/dmd-2.069.1/osx/bin/../../src/phobos/std/conv.d(4161): Error: template std.conv.emplaceImpl!(const(Node)).emplaceImpl cannot deduce function from argument types !()(const(Node), immutable(int), const(Node)*, int), candidates are: /Users/steves/.dvm/compilers/dmd-2.069.1/osx/bin/../../src/phobos/std/conv.d(3932): std.conv.emplaceImpl!(const(Node)).emplaceImpl()(ref UT chunk) /Users/steves/.dvm/compilers/dmd-2.069.1/osx/bin/../../src/phobos/std/conv.d(4037): std.conv.emplaceImpl!(const(Node)).emplaceImpl(Args...)(ref UT chunk, auto ref Args args) /Users/steves/.dvm/compilers/dmd-2.069.1/osx/bin/../../src/phobos/std/conv.d(5087): Error: template instance std.conv.emplace!(const(Node), immutable(int), const(Node)*, int) error instantiating persistent_list.d(169):instantiated from here: emplace!(const(Node), immutable(int), const(Node)*, int) persistent_list.d(195):instantiated from here: opBinaryRight!"~" persistent_list.d(266):instantiated from here: List!(immutable(int)) However, examining the code, I think you don't even need inout here, just a const function will do fine, since nothing on the original is changing, and all your nodes are flavored as pointing to const nodes. I see you have updated the code, and that doesn't work for me either. I'm afraid without a working example, I can't figure out what's *supposed* to work with inout/const. -Steve
Re: Persistent list
On 11/16/2015 11:58 AM, Steven Schveighoffer wrote: On 11/15/15 2:09 PM, Andrei Alexandrescu wrote: On 11/13/2015 06:10 PM, Andrei Alexandrescu wrote: [snip] Thanks all for the feedback. I've uploaded an updated version to http://dpaste.dzfl.pl/52a3013efe34. It doesn't use "inout", but doesn't duplicate code either; instead, it relies on private internal functions to do the deed. This still doesn't compile for me. You need my emplace bugfixes, so get the latest toolchain. -- Andrei
Re: Persistent list
On 11/16/2015 11:58 AM, Lionello Lunesu wrote: On 16/11/15 22:45, Andrei Alexandrescu wrote: On 11/16/2015 08:51 AM, Marc Schütz wrote: On Monday, 16 November 2015 at 02:26:29 UTC, Andrei Alexandrescu wrote: Yah, I agree with that argument. Probably @mutable is a more principled way to go about things. Glad to here that. I think the current transitive const system is really good and shouldn't be watered down beyond necessity. And a @mutable keyword, too, shouldn't just mean "immutability or const-ness end here", thus allowing any kind of mutation. What we actually need for immutable/const refcounting etc. is _non-observable mutation_, i.e. physical mutability, but without observable effects outside of the type's implementation (better yet, restricted to very short parts of it, just like @trusted). The challenge is proving that a mutation is not observable. Got an attack on that? -- Andrei Forgive me, I haven't followed the RC discussions closely, so I miss a lot of context. Feel free to point me to existing threads/articles. The best place to start for absorbing context is look at the casts in http://dpaste.dzfl.pl/52a3013efe34, understand the necessity of each, and figure out how they can be either made legal or (preferably) eliminated. If it's RC we want, then @mutable is an axe when what we need is a scalpel. There's more than RC in there. Andrei
Re: Persistent list
On 11/16/2015 11:03 AM, Steven Schveighoffer wrote: On 11/14/15 10:44 AM, Andrei Alexandrescu wrote: That doesn't work for me with my unittests, I get: I'm such an idiot, I depended on dpaste to run the unit test, but forgot to check the unit test button. So technically, my updated version *parses* correctly :) Looking in more depth... Thanks for letting us know. -- Andrei
Re: Persistent list
On 11/15/15 9:54 AM, Andrei Alexandrescu wrote: On 11/15/2015 09:34 AM, Dicebot wrote: On Sunday, 15 November 2015 at 14:23:05 UTC, Jonathan M Davis wrote: As I mentioned, he's okay with changing the language to make the casts well defined. -- Andrei Well, that's a big change, since it pretty much means that D's const isn't physical const anymore, and Walter has been _very_ insistent about that in the past - to the point that he's argued that C++'s const is outright useless because it isn't physical const. If casting away const and mutating is well-defined behavior, then we basically have C++'s const except that it's transitive ... Casting away _const_ is already legal if programmer can himself guarantee underlying object has mutable origin (i.e. not available via immutable reference), by the very definition of const. It is casting away immutable and mutating that is strictly UB. Correct. I'm not sure whether that's clarified in the language documentation yet. -- Andrei I argued this way, and eventually lost. I don't think it's feasible to have a const that can be cast away, and have optimizations based on const or pure. See this discussion: forum.dlang.org/post/riiehqozpkyluhhif...@forum.dlang.org One thing, however, is that if you can mark an island of space within an object as ALWAYS mutable, the compiler can know this and avoid optimizing away access to those pieces. It would have to be clearly marked as such, so the optimizations on non-marked data could still happen. I think it could be done, because logical const is possible via a global lookup table. Any time you go through a cast, however, this could easily break down. I hate to say it, but you would likely need another modifier like "tainted const" or something in order for that to work. -Steve
Re: All functions COMDAT on OSX
On Monday, 16 November 2015 at 14:37:33 UTC, bitwise wrote: On Monday, 16 November 2015 at 08:15:39 UTC, Walter Bright wrote: On 11/15/2015 8:44 PM, bitwise wrote: https://issues.dlang.org/show_bug.cgi?id=15342 DMD emits all functions as COMDAT on OSX. I'm guessing this was originally a workaround of some kind...does anybody know the story? Thanks, Bit It enables: 1. the linker to remove duplicates (happens with templates and other things) 2. the linker to remove unreferenced COMDATs I understand what it's for, but it's incorrect behaviour to have _all_ functions being emitted as comdat. Non-template functions shouldn't be coalesced in this way. If you compile the code example in the bug report with *any* compiler other than DMD/OSX, the example will fail as described, with a linker error. The example compares dmd/osx with gcc/osx, but the code will also fail with ldc/osx. And although I don't have time to check, I'm pretty sure it will fail with dmd/win as well. If you look at the code I cited, this is obviously a hack: [...] #if TARGET_OSX s->Sclass = SCcomdat; #else s->Sclass = SCglobal; #endif for (Dsymbol *p = fd->parent; p; p = p->parent) { if (p->isTemplateInstance()) { s->Sclass = SCcomdat; break; } } [...] FWIW, that's been in the source since somewhen between 2.025 and 2.026: https://github.com/D-Programming-Language/dmd/commit/00337ef8d8c4c1c08da68f95963e2fe1658a49ec Unfortunately there are no intermediate commits in the repo, because only released versions have been imported during the switch to Git.
Re: And in the (quasi-)comedy section…
On Monday, 16 November 2015 at 14:33:26 UTC, Russel Winder wrote: A quote from @SarcasticRover: New studies show that Mars' moon Phobos is slowly breaking up under pressure… but really, who isn't? Life is hard. You know, I saw this piece of news, but refrained from making a comment here. Though it was tempting :-P
Re: Persistent list
On 16/11/15 22:45, Andrei Alexandrescu wrote: On 11/16/2015 08:51 AM, Marc Schütz wrote: On Monday, 16 November 2015 at 02:26:29 UTC, Andrei Alexandrescu wrote: Yah, I agree with that argument. Probably @mutable is a more principled way to go about things. Glad to here that. I think the current transitive const system is really good and shouldn't be watered down beyond necessity. And a @mutable keyword, too, shouldn't just mean "immutability or const-ness end here", thus allowing any kind of mutation. What we actually need for immutable/const refcounting etc. is _non-observable mutation_, i.e. physical mutability, but without observable effects outside of the type's implementation (better yet, restricted to very short parts of it, just like @trusted). The challenge is proving that a mutation is not observable. Got an attack on that? -- Andrei Forgive me, I haven't followed the RC discussions closely, so I miss a lot of context. Feel free to point me to existing threads/articles. If it's RC we want, then @mutable is an axe when what we need is a scalpel. The non-observability comes from the fact the refcount is changed when the caller has lost its (const) reference and constness is a moot point. Changing refcount is fine now, provided the object is not immutable. As far as other outstanding const references go, these already expect changes to happen. This is what makes refcount special and provably safe to mutate. As long as we can ensure the object is not immutable, the object is allowed to change its own refcount. But refcount needs to be special cased, somehow, or else we'll end up with some C++ like `mutable`. Perhaps const-but-not-pure is the solution here. The object must be able to store (and have stored) a mutable reference, so it can use that reference to change the refcount. (This could be optimized to be a flag, since the mutable and const reference would refer to the same instance.) It means keeping track of const-but-mutable vs const-and-immutable references, and somehow telling the compiler that refcount is special. L.
Re: Persistent list
On 11/15/15 2:09 PM, Andrei Alexandrescu wrote: On 11/13/2015 06:10 PM, Andrei Alexandrescu wrote: [snip] Thanks all for the feedback. I've uploaded an updated version to http://dpaste.dzfl.pl/52a3013efe34. It doesn't use "inout", but doesn't duplicate code either; instead, it relies on private internal functions to do the deed. This still doesn't compile for me. While revising feedback I realized I'd missed Steve's version that works with inout: http://dpaste.dzfl.pl/3fbc786a50c1. It works and the inout-related parts don't look difficult; the only thing is making sure the right incantations are in place, and that's the difficult part. I would say the difficult part is figuring out the incantations from the given error messages. When you are depending on something to compile because it can call a template function, it's often difficult to figure out where it went wrong. The error messages are frequently unhelpful. inout is actually pretty simple to use. It has a couple of severe limitations that make it difficult to work with in certain situations -- one of them being composition (you can't compose a type with inout members). We can work on fixing these problems. So one important question is what style we use for Phobos and endorse as idiomatic. My sense after working on this for a while is - forget inout. Qualifiers are rather complex, and of them inout is the most. So I'd rather marginalize it. Please chime in with any thoughts. I disagree. inout is no more complex than const in most cases. In my experience changing to inout is simply changing the term "const" to "inout", and everything pretty much works. This was my experience when updating dcollections after inout was finally made to work. I'm going to work on writing an article about inout. It frequently confuses the shit out of everyone who uses it, and I don't think it should. -Steve
Re: Persistent list
On 11/14/15 3:42 AM, Dmitry Olshansky wrote: On 14-Nov-2015 02:10, Andrei Alexandrescu wrote: * Lines 141-152: I couldn't make tail() work with inout. Generally I'm very unhappy about inout. I don't know how to use it. Everything I read about it is extremely complicated compared to its power. I wish we removed it from the language and replaced it with an understandable idiom. I can't agree more. Every time dealing with inout when I finally think I grok how it works the next instant I see that it doesn't do what I expect. For me inout inevitably stops at the boundary of being unnable to have List!(inout(T)) and the like. One thing we could allow is types that contain inout member variables, but ONLY in the context of inout functions. In other words, you can create a type for it, but can only use it in the context of an inout function. A List!(inout(T)) outside an inout function has no meaning. This is why we disallowed it. However, my belief is that it's the lack of a mechanism to apply an attribute to the tail of some struct that prevents the most utility here. If you returned a List!(inout(T)) there is no way to magically convert it to a List!(const(T)) or List!(immutable(T)). Consider that Node in this code has a "const(Node)* next" as its tail. I believe we should be able to achieve both. -Steve
Re: Style guide is very inconsistent
On Monday, 16 November 2015 at 14:26:41 UTC, Jonathan M Davis wrote: On Monday, 16 November 2015 at 14:09:45 UTC, maik klein wrote: [...] Per the style guide, = Eponymous Templates [...] Okay thanks, but I am still not sure about my example. I am pretty sure that at least "any" should be camel case because it's a value, but what about "Contains"? It's neither a type nor a eponymous template. My guess is that it should also be camel case? So it would be contains!C.any!T ?
Re: Persistent list
On 11/14/15 10:44 AM, Andrei Alexandrescu wrote: That doesn't work for me with my unittests, I get: I'm such an idiot, I depended on dpaste to run the unit test, but forgot to check the unit test button. So technically, my updated version *parses* correctly :) Looking in more depth... -Steve
Re: opDispatch and compile time parameters
On 11/14/15 12:18 AM, Jakob Ovrum wrote: On Saturday, 14 November 2015 at 04:10:59 UTC, Steven Schveighoffer wrote: Is it me, or is this a bug? struct Foo { template opDispatch(string s) { // if you uncomment this, it compiles //void opDispatch() {} void opDispatch(T...)() {} } } void main() { Foo f; f.blue!char(); // Error: no property 'blue' for type 'Foo' } Usually you should explicitly instantiate opDispatch to see the real error message(s) that prevented opDispatch from being used, but in this case I can't find a way to do that. `f.opDispatch!("blue")!char()` is syntactically invalid, and aliasing doesn't work either: `alias t = f.opDispatch!"blue"; t!char(); // Error: need `this` for opDispatch`. I wonder what the real error is. It appears that you can't directly access the eponymous member, this doesn't work: f.opDispatch!("blue").opDispatch!(char)(); Error: no property 'opDispatch' for type 'void' Perhaps that fact that it *works* when you have the non-template version as the first member is the bug ;) In any case, I have used Jack Applegame's improved version, and it works beautifully! -Steve
Re: Persistent list
On Monday, 16 November 2015 at 08:18:55 UTC, Jonathan M Davis wrote: And actually, this gives me an interesting thought. Does making casting away const and mutating defined behavior give us a way to fix our postblit problem? I could see an argument that postblits should be completely unnecessary for immutable values (because you shouldn't need to avoid stuff like sharing references when it's immutable), which could mean that we could change it so that immutable structs values didn't trigger a postblit and thus worked fine as-is, and that would fix the problem with postblits and immutable. And if casting away const and mutating is legit, then it should be possible to treat the struct itself as mutable (or at least tail-const) within the postblit constructor, in which case it's then actually possible to have postblit constructor that works with const, whereas right now, we can't have it, because it would violate const to mutate the newly blitted, const struct. So, if this really fixes our postblit problem, it might be worth it just for that. As it stands, postblit constuctors tend to have to be avoided in many cases because of how badly they interact with const and immutable. Actually, with regards to immutable, it looks like you can already copy immutable objects with postblit constructors. You just can't copy it and get a mutable value out of it. But copying and creating another immutable value or a const value both work just fine. So, it looks like the only thing we're missing with regards to immutable and postblits is the ability to get a mutable copy, but that's not really much of a loss as far as I can think of at the moment. So, really it's just the issue with const and postblit that really needs fixing, and allowing the mutation of const to be defined behavior when the underlying object isn't immutable could give us the out we need to fix that problem. - Jonathan M Davis
Re: Persistent list
On Monday, 16 November 2015 at 14:08:23 UTC, Atila Neves wrote: You described immutable, not const. If one thread has a const reference, it's entirely possible another thread has a mutable reference. Are you sure that this is a well defined situation? What is the point of having "const" if "shared const" is the exact same thing? Immutable should never ever change for any reason, because the compiler should be able to cache derived values.
Re: Persistent list
On Monday, 16 November 2015 at 14:45:35 UTC, Andrei Alexandrescu wrote: On 11/16/2015 08:51 AM, Marc Schütz wrote: On Monday, 16 November 2015 at 02:26:29 UTC, Andrei Alexandrescu wrote: Yah, I agree with that argument. Probably @mutable is a more principled way to go about things. Glad to here that. I think the current transitive const system is really good and shouldn't be watered down beyond necessity. And a @mutable keyword, too, shouldn't just mean "immutability or const-ness end here", thus allowing any kind of mutation. What we actually need for immutable/const refcounting etc. is _non-observable mutation_, i.e. physical mutability, but without observable effects outside of the type's implementation (better yet, restricted to very short parts of it, just like @trusted). The challenge is proving that a mutation is not observable. Got an attack on that? -- Andrei That would be a neat trick. As I recall, previous discussions on logical const concluded that there was no way to implement it in a way that guaranteed that it was actually logical const as opposed to just being mutated in spite of being const. But it would be _very_ cool if someone figured out how to do it. Still, even without that guarantee, using something like @mutable rather than casting would be far safer - especially if the type system can guarantee that such an object can't be immutable. - Jonathan M Davis
Re: Persistent list
On Monday, 16 November 2015 at 14:08:23 UTC, Atila Neves wrote: You described immutable, not const. If one thread has a const reference, it's entirely possible another thread has a mutable reference. Only if it's shared, or you've screwed up with casting and ended up with an object which is actually shared being treated as TLS. A const, non-shared object can't possibly be mutated while you're doing stuff to it unless that same code somehow has access to a mutable reference to the same data. And in most cases (particularly if you're using pure heavily), it won't have access to any other references to the same data, so you can usually rely on a const object not being mutated while you operate on it. - Jonathan M Davis
Re: Persistent list
On 11/16/2015 08:51 AM, Marc Schütz wrote: On Monday, 16 November 2015 at 02:26:29 UTC, Andrei Alexandrescu wrote: Yah, I agree with that argument. Probably @mutable is a more principled way to go about things. Glad to here that. I think the current transitive const system is really good and shouldn't be watered down beyond necessity. And a @mutable keyword, too, shouldn't just mean "immutability or const-ness end here", thus allowing any kind of mutation. What we actually need for immutable/const refcounting etc. is _non-observable mutation_, i.e. physical mutability, but without observable effects outside of the type's implementation (better yet, restricted to very short parts of it, just like @trusted). The challenge is proving that a mutation is not observable. Got an attack on that? -- Andrei
Re: All functions COMDAT on OSX
On Monday, 16 November 2015 at 08:15:39 UTC, Walter Bright wrote: On 11/15/2015 8:44 PM, bitwise wrote: https://issues.dlang.org/show_bug.cgi?id=15342 DMD emits all functions as COMDAT on OSX. I'm guessing this was originally a workaround of some kind...does anybody know the story? Thanks, Bit It enables: 1. the linker to remove duplicates (happens with templates and other things) 2. the linker to remove unreferenced COMDATs I understand what it's for, but it's incorrect behaviour to have _all_ functions being emitted as comdat. Non-template functions shouldn't be coalesced in this way. If you compile the code example in the bug report with *any* compiler other than DMD/OSX, the example will fail as described, with a linker error. The example compares dmd/osx with gcc/osx, but the code will also fail with ldc/osx. And although I don't have time to check, I'm pretty sure it will fail with dmd/win as well. If you look at the code I cited, this is obviously a hack: [...] #if TARGET_OSX s->Sclass = SCcomdat; #else s->Sclass = SCglobal; #endif for (Dsymbol *p = fd->parent; p; p = p->parent) { if (p->isTemplateInstance()) { s->Sclass = SCcomdat; break; } } [...] Bit
And in the (quasi-)comedy section…
A quote from @SarcasticRover: New studies show that Mars' moon Phobos is slowly breaking up under pressure… but really, who isn't? Life is hard. -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: Style guide is very inconsistent
On Monday, 16 November 2015 at 14:09:45 UTC, maik klein wrote: Why are the variadics written in lower case? Per the style guide, = Eponymous Templates Templates which have the same name as a symbol within that template (and instantiations of that template are therefore replaced with that symbol) should be capitalized in the same way that that inner symbol would be capitalized if it weren't in a template - e.g. types should be PascalCased and values should be camelCased. = So, whether an eponymous template is camelCased or PascalCased depends entirely on what its result is. It's quite possible that there are older symbols in Phobos that don't follow those guidelines, but most do. However, there are some where it's not clear which it should be. e.g. std.meta.Filter is a funny one, because it works with any symbol - be it a type or a value - so it could have gone either way, but it was probably targeted primarily at types, so it ended up with its name being PascalCased. But in general, an eponymous template which results in a type is supposed to be PascalCased, whereas the others are supposed to be camelCased. Really, pretty much anything that isn't a type is camelCased, whereas types are PascalCased. It's just that there a few cases that are inherently ambiguous, and there may be some older symbols in Phobos which don't properly follow the current style guide. - Jonathan M Davis
Style guide is very inconsistent
I am a very new D user and I almost always try to mirror the "official" style guide if one is available. http://dlang.org/dstyle.html I have written the following function template Contains(C...){ template Any(T...){ import std.meta: anySatisfy; static if(T.length == 0){ enum Any = false; } else{ enum Any = ContainsImpl!T; } template ContainsImpl(T...){ enum bool isSameComponent(Comp) = is(Comp == T[0]); static if(T.length == 1){ enum ContainsImpl = anySatisfy!(isSameComponent,C); } else{ enum ContainsImpl = anySatisfy!(isSameComponent,C) && ContainsImpl!(T[1..$]); } } } } No idea how I should type it contains!c.any!T or contains!c.Any!T Which lead me to have a look at phobos For example template Filter(alias pred, TList...) vs template anySatisfy(alias F, T...) Are aliases now written in upper or lower camelCase? Should I use T... or TList... for variadics if I can't name them better? or private template GenericReplace(args...) Why are the variadics written in lower case?
Re: Persistent list
On Monday, 16 November 2015 at 09:42:43 UTC, Ola Fosheim Grøstad wrote: On Monday, 16 November 2015 at 09:04:33 UTC, Joseph Cassman wrote: [...] The D designers might want to look at Pony lang's capability system, which has been proven sound. It has 6 different aliasing capabilites that regulates among other things transition from mutable to immutable. D is a little bit better of (if it does not allow casting away const) than C++, because in C++ const is essentially "shared const", whereas in D in is "local const with potential aliasing". AFAIK the D sementics is that no other thread can hold a mutable reference to something you have as const. But it is still a relatively weak guarantee. In C you have "restricted" for notifying the compiler that the resource is aliasing free within the context. You described immutable, not const. If one thread has a const reference, it's entirely possible another thread has a mutable reference. Atila
Re: Persistent list
On Monday, 16 November 2015 at 02:26:29 UTC, Andrei Alexandrescu wrote: Yah, I agree with that argument. Probably @mutable is a more principled way to go about things. Glad to here that. I think the current transitive const system is really good and shouldn't be watered down beyond necessity. And a @mutable keyword, too, shouldn't just mean "immutability or const-ness end here", thus allowing any kind of mutation. What we actually need for immutable/const refcounting etc. is _non-observable mutation_, i.e. physical mutability, but without observable effects outside of the type's implementation (better yet, restricted to very short parts of it, just like @trusted).
Re: Persistent list
On Sunday, 15 November 2015 at 20:23:58 UTC, Dicebot wrote: On Friday, 13 November 2015 at 23:10:04 UTC, Andrei Alexandrescu wrote: I created a simple persistent list with reference counting and custom allocation at http://dpaste.dzfl.pl/0981640c2835. There is also another thing I wanted to mention on topic of persistent containers. Right now for me the most intriguing topic is trying to define immutable (and actually thread shared) cache data structure than can be efficiently and safely used without GC. There is whole class of tasks where you can get best performance by building new copy of cache in memory instead of modifying separate elements, trading increased memory concsumption for fast no lock parallel access. However in absence of GC task of deleting memory for older generations of cache becomes rather challenging. I have been thinking about approach with external two-level reference counting + dedicated allocator - quick thread-local RC comes first and once it goes to 0, shared RC in allocator gets decremented (being effetively user thread counter). Do you think it can work? If the elements are immutable, you can actually write a parallel non-stop-the-world GC for your cache. You just need to record the "age" of each element, and define a grace period that must have passed before they can be freed. As for your RC idea: You could either start by creating the objects as shared and add a `.unshare()` method to them, or start with thread-local objects and create the shared RC lazily (`.share()`).
Re: RFC in Comparison between Rust, D and Go
On 2015-11-14 07:31, Sergey Korshunoff via Digitalmars-d wrote: PS: you just say that C is not suitable for the system programming Well, he is the creator of D ;) -- /Jacob Carlborg
Re: Bitfield bug
On 16/11/15 18:05, deadalnix wrote: https://issues.dlang.org/show_bug.cgi?id=15305 Any taker ? I don't think this is that hard to fix, and this is really bad. https://github.com/D-Programming-Language/phobos/pull/3815
Re: Our template emission strategy is broken
On Saturday, 14 November 2015 at 03:43:38 UTC, Walter Bright wrote: On 11/13/2015 9:23 AM, Johannes Pfau wrote: Ellery filed a bug report and I've posted a reduced test case: https://issues.dlang.org/show_bug.cgi?id=15324 Thank you! https://issues.dlang.org/show_bug.cgi?id=15333 Also, thanks to whoever was able to reduce it more than I.
Bitfield bug
https://issues.dlang.org/show_bug.cgi?id=15305 Any taker ? I don't think this is that hard to fix, and this is really bad.
Re: Wanted: Review manager for std.experimental.range.ndslice
On Monday, 16 November 2015 at 03:05:03 UTC, Ilya Yaroshenko wrote: Hello, Review manager for N-dimensional ranges is wanted Docs (see PR for latest version): http://dtest.thecybershadow.net/artifact/website-7a646fdea76569e009844cdee5c93edab10980ca-cdcb694c40ec47acf88b0aa878e1623e/web/phobos-prerelease/std_experimental_range_ndslice.html PR: https://github.com/D-Programming-Language/phobos/pull/3397 DUB: http://code.dlang.org/packages/dip80-ndslice Best Regards, Ilya Nice work! If I have a matrix like 1 2 3 4 iota(4).sliced(2,2); Is there a way to transform it to: 1 1 1 2 2 2 1 1 1 2 2 2 1 1 1 2 2 2 3 3 3 4 4 4 3 3 3 4 4 4 3 3 3 4 4 4 or 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 4 0 0 0 0 0 0 0 ? Of course the inverse operation seems quite easier to do using slices.
Re: Our template emission strategy is broken
On Wednesday, 11 November 2015 at 13:08:08 UTC, David Nadlinger wrote: ... Sorry I haven't read this whole thread so maybe this has been mentioned before or not. I am not even sure if its really related to this topic, but it seemed related to me so I figured I would just post it here rather than make a new thread. ModuleInfo.localClasses doesn't list template class instances. I just ran into this(like 5 min ago) and thought it was odd. I expected it too list template instances as well so I thought it might be a bug, not really sure. Thankfully I don't really need it to list template instances of classes so it not affecting my project, but I could see it being a problem for others.
Re: Persistent list
On Monday, 16 November 2015 at 09:04:33 UTC, Joseph Cassman wrote: Just as a side thought, although it is probably a bit of a dasoku. But I have always wondered that if the purpose of _const_ is to allow some data to be changed by one reference but not changed by another, then why is it transitive. Doesn't that defeat its purpose? The D designers might want to look at Pony lang's capability system, which has been proven sound. It has 6 different aliasing capabilites that regulates among other things transition from mutable to immutable. D is a little bit better of (if it does not allow casting away const) than C++, because in C++ const is essentially "shared const", whereas in D in is "local const with potential aliasing". AFAIK the D sementics is that no other thread can hold a mutable reference to something you have as const. But it is still a relatively weak guarantee. In C you have "restricted" for notifying the compiler that the resource is aliasing free within the context. And then doesn't transitive const effectively have the same semantics and use-case as _immutable_? I mean, once you start to use transitive const in an interface, how are you supposed to get the mutable reference that is so promised? Perhaps this is the question that is essentially being asked here? The right thing to do is to: 1. map out all possible aliasing combinations and pick a set of capabilities that is sound 2. poke a clean well defined hole through the constness by allowing a "mutable" modifier that does not depend on type state. (or you should add type state and an effect system). 3. implement something that is compatible with conservative C++ (shared head const with mutable fields and no const_cast). D really should try to avoid repeating C++'s mistakes or add a different set of mistakes, in order to compensate for former mistakes.
Re: [Poll] On Linux, what should we commonly use as sub-directory name for D?
On 16 November 2015 at 09:30, Marco Leise via Digitalmars-d < digitalmars-d@puremagic.com> wrote: > Am Mon, 16 Nov 2015 08:49:57 +0100 > schrieb Iain Buclaw via Digitalmars-d > : > > > There should be ways to catch ABI changes in the build or test process. > > Maybe I'm misremembering something though. :-) > > > > There should be a degree of ABI compatibility between releases for plain > > static functions - assuming that we add no more properties to the > > language. That leaves what breaks the most in moving to a new version > are > > template instantiations, no? > > Frankly I have no idea what level of testing is in place. :D > To be practical for package maintainers, we would need some > higher level common D ABI versioning scheme that includes > Phobos. Then I could start grouping libraries by architecture > and this ABI version instead of by compiler/FE version. But > let's take baby steps here and first get DMD to use DWARF EH. > Once we can dynamically link DMD<->GDC, DMD<->LDC, we can > think about a stable Dlang ABI in terms of EH, function > mangling, Phobos etc. > A good litmus test would be to take the C++ ABI tests in the D2 testsuite, and convert the C++ sources to D. Build one with DMD and the other with GDC. If something segfaults or goes wrong at runtime, then raise a bug about how DMD doesn't pass parameters correctly. ;-) Besides, I'd worry more about how DMD keeps changing the names of runtime hooks to be able to do things GDC has done for years. With Dwarf EH thrown into the mix, there's now three functions that handle throwing objects (GDC still only has one). Not cool man!
Re: Our template emission strategy is broken
Am Wed, 11 Nov 2015 14:23:15 + schrieb Martin Nowak : > Think of that for a moment, no package manager allows you to > have cycles in your dependencies. There are package managers that allow packages to mutually depend on each other. Order is established by qualifying the dependency similar to how you declare an owning and a weak reference in a parent/child pointer relation. E.g. You must install DMD before druntime/Phobos, but DMD is only usable after druntime/Phobos has also been installed. -- Marco
Re: Persistent list
On Monday, 16 November 2015 at 06:24:05 UTC, Jonathan M Davis wrote: [...] Regardless, I think that it's quite clear that certain idioms simply do not work with physical const, and there's been complaining about that for years. The only real question here is whether those idioms are worth enough to lose out on physical const. The answer up until now has always been no (at least from Walter), but since Andrei is now hitting this himself rather than seeing others complain about it, he clearly views it as a problem in a way that he didn't before, so that may result in him changing Walter's mind. - Jonathan M Davis I appreciate this discussion. I feel better that I am not the only one having difficulty with the _const_ keyword. Honestly about the only time I use _const_ is to tell the D compiler that a struct member function does not modify its containing type. When I start to use _const_ I quickly get a headache trying to figure out how to fix my code when the compiler starts to complain about function overloading issues and starts to require explicit casts all over the place, _inout_ doesn't work, did I use _Unqual_ or maybe I shouldn't, should this be a template, etc. I end up with a headache and all I want is the thing to compile. I wonder many times why go through the trouble. Why not just use a unit test? After reading through this discussion I wonder if it has been considered to keep _immutable_ and _const_ as they are, but add a less restrictive do-not-change-me type qualifier to the language? A keyword like _readonly_, for example, could represent the idea of intransitive const (or perhaps even a different type of do-not-change-me-ness). I appreciate the need to be conservative in language additions, especially at this point in the life cycle of D2. Still, if people want and can show they need a type of do-not-change-me type qualifier in addition to _const_ and _immutable_ (not overlapping with unique et. al.) why not provide it for them? Just as a side thought, although it is probably a bit of a dasoku. But I have always wondered that if the purpose of _const_ is to allow some data to be changed by one reference but not changed by another, then why is it transitive. Doesn't that defeat its purpose? And then doesn't transitive const effectively have the same semantics and use-case as _immutable_? I mean, once you start to use transitive const in an interface, how are you supposed to get the mutable reference that is so promised? Perhaps this is the question that is essentially being asked here? Joseph
Re: [Poll] On Linux, what should we commonly use as sub-directory name for D?
Am Mon, 16 Nov 2015 08:49:57 +0100 schrieb Iain Buclaw via Digitalmars-d : > There should be ways to catch ABI changes in the build or test process. > Maybe I'm misremembering something though. :-) > > There should be a degree of ABI compatibility between releases for plain > static functions - assuming that we add no more properties to the > language. That leaves what breaks the most in moving to a new version are > template instantiations, no? Frankly I have no idea what level of testing is in place. :D To be practical for package maintainers, we would need some higher level common D ABI versioning scheme that includes Phobos. Then I could start grouping libraries by architecture and this ABI version instead of by compiler/FE version. But let's take baby steps here and first get DMD to use DWARF EH. Once we can dynamically link DMD<->GDC, DMD<->LDC, we can think about a stable Dlang ABI in terms of EH, function mangling, Phobos etc. I can easily see Phobos being split out of the DMD release cycle by then, with both loosely depending on each other. -- Marco
Re: All functions COMDAT on OSX
On 11/15/2015 8:44 PM, bitwise wrote: https://issues.dlang.org/show_bug.cgi?id=15342 DMD emits all functions as COMDAT on OSX. I'm guessing this was originally a workaround of some kind...does anybody know the story? Thanks, Bit It enables: 1. the linker to remove duplicates (happens with templates and other things) 2. the linker to remove unreferenced COMDATs
Re: Persistent list
On Monday, 16 November 2015 at 06:36:31 UTC, rsw0x wrote: On Monday, 16 November 2015 at 06:24:05 UTC, Jonathan M Davis wrote: On Sunday, 15 November 2015 at 21:45:08 UTC, Dicebot wrote: [...] Except that what if the container is passed to something that keeps it around? The ref-count would need to at least be incremented when passing it, and if the container were passed around enough, it could potentially need to be incremented a lot. Ranges are potentially another big issue. As I understand it, there have already been issues with const and ranges with std.container.Array, because some of the fancy stuff that it does internally really doesn't work with const (though maybe I misunderstood). this has a lot to do with const being virtually useless with structs I'd say that there are two things about const which apply to structs which don't apply to classes which make const with structs bad. Stuff like having const member functions or having const values isn't necessarily any more of a problem with structs than it is with classes. What _is_ problematic is 1. const member variables (because they essentially force the whole struct to be treated as const even though it isn't - e.g. assignment doesn't work) 2. postblits don't work with const or immutable (so if you need a postblit, your struct really doesn't work with const or immutable) Beyond that, const with structs is pretty much the same as it with classes. It's definitely restrictive, but not useless. And actually, this gives me an interesting thought. Does making casting away const and mutating defined behavior give us a way to fix our postblit problem? I could see an argument that postblits should be completely unnecessary for immutable values (because you shouldn't need to avoid stuff like sharing references when it's immutable), which could mean that we could change it so that immutable structs values didn't trigger a postblit and thus worked fine as-is, and that would fix the problem with postblits and immutable. And if casting away const and mutating is legit, then it should be possible to treat the struct itself as mutable (or at least tail-const) within the postblit constructor, in which case it's then actually possible to have postblit constructor that works with const, whereas right now, we can't have it, because it would violate const to mutate the newly blitted, const struct. So, if this really fixes our postblit problem, it might be worth it just for that. As it stands, postblit constuctors tend to have to be avoided in many cases because of how badly they interact with const and immutable. - Jonathan M Davis