Re: DIP 1009--Improve Contract Usability--Formal Review
On Wednesday, 30 August 2017 at 14:05:40 UTC, Mark wrote: I see that in the previous review rounds some people suggested various keywords for designating the return value of a function ("return", "result", ...) in an `out` contract. What about using a plain old underscore? For example: int abs(int x) out(_ >= 0) { return x>0 ? x : -x; } I think it's good to be consistent with existing out contracts which require declaring the variable first. The identifier `__result` currently works, but the thing is, it takes fewer characters to write `out(r; r >= 0)` than to write `out(;__result >= 0)` (or `out(__result >= 0)`). The possibility of using a single character as the return identifier makes it hard, in my opinion, to justify complaints about the syntax being "too verbose."
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 2 Begins
On Monday, 31 July 2017 at 09:55:22 UTC, Nick Treleaven wrote: This is subjective. If you put `do` on the end of the line, it is trivial: in(x > 4) out(works) out(r; r.test) out(flag) do { // body } The common case is for `out` contracts to test for the return variable. Something like 90% will therefore look like: int fun(int x) out(r; r > 0) { } So it's the uncommon case we're trying to solve for. Requiring `do` in precisely one case, which is the rare case in which the `out` test has only one identifier, and therefore can't be disambiguated from existing `out` contracts, is a solution to that problem. It's seems like a complicated one. To me, it's simpler to simply require the `;` because it's the uncommon case to begin with, and everyone will know what it means because they'll be used to seeing `out(r; r > 0)`. That said, `do` can solve the loophole with the alternative ambiguous syntax. For example: int fun(ref int x, ref int y, ref int z) out(x) // fine, followed by another contract out(y != 0) // fine, multiple tokens, unambiguous out(z) do // fine, followed by `do` { } If you forget to add the `do` there is an inevitable parsing error, so it's not that bad even in the worst case. The error can be fixed by changing `out(z)` to `out(z != 0)`, or to `out(z) do` as you suggest. `do` is only going to be valuable in that one case, though. I'd say it depends where the language designers want to pay the cost of solving the problem. Either pay it up front with the ugliness of the foreach syntax, or pay it in complexity with the different cases of the ambiguous syntax. Because it's a programming language and not a sports car, I'd probably choose the consistency of the foreach syntax over the attractiveness of the ambiguous syntax. But there's no clear winner, IMO.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 2 Begins
On Friday, 28 July 2017 at 11:04:23 UTC, Nick Treleaven wrote: One option to solve the out contract ambiguity and aid parsing by tools is to require 'do' after out contract expressions. It allows the syntax `out(expression) do {...}`, even when expression is a single identifier that should be interpreted as a boolean expression. One of the main goals of this DIP is to eliminate the need for `body/do` in the common case. It would significantly reduce this DIP's value if it couldn't do that, IMO.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 2 Begins
On Tuesday, 25 July 2017 at 07:48:39 UTC, Andrea Fontana wrote: I don't like it so much but also something like this could be considered: out!(x => x>0) or maybe: out!x(x > 0) that can't collide with current syntax Andrea It's another viable option, but it doesn't seem to stand out much from the crowd. Most people, including me, seem to think `out(x; x > 0)` and `out(; y > 0)` are the "least imperfect" option. I suspect they would win if put to a vote. Maybe the leadership can come up with something better. People will get used to whatever is selected. I just like the foreach version because it's simple and concise. I also don't think the ambiguous `out(x > 0)` syntax is that bad for non-return variables. But I can also see why that's suboptimal from a design point of view.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 2 Begins
On Wednesday, 26 July 2017 at 08:12:39 UTC, Olivier FAURE wrote: I... think you misunderstood me? I shouldn't have used the word 'proposals', I should have said 'suggestions'. What I meant was "I think it would be better for the current version of DIP 1009 to include a 'Rejected alternative syntaxes' that would include a summary of the previously discussed suggestions for improving contract readability." MysticZach argues that such a section would be pointless since the language authors read the previous version of DIP 1009, but I still think adding it would be a good idea (for posterity and to streamline discussions in this thread). I don't know. DIPs have both a forward-looking and a backward-looking aspect. The forward is to convince the language authors of the need/value of a specific language change. The backward is to record a history of discussions so that people can learn why things are the way they are. They are both valuable in their own way, but I think the forward-looking aspect is more valuable. I'd like some guidance from the leadership as to the important of the backward-looking aspect of DIPs. For example, DIP1003 was actually rewritten to excise the alternatives and keep only the one adopted. The motive given was that people looking for the history could examine prior versions of the DIP. I guess the motive is that too much history can end up cluttering the important information. That said, I think that making good decisions for the language far outweighs any concerns about DIPs themselves. So we should really be focusing on that.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 2 Begins
On Friday, 21 July 2017 at 19:36:08 UTC, H. S. Teoh wrote: However, I think the presentation of the DIP needs some work. For example, the rationales and lines of reasoning that eventually led to the currently proposed syntax, both from the original draft of this DIP and from the ensuing discussion in the previous review thread, ought to be included (of course, in summarized form -- no need to repeat the back-and-forth of the original discussions, but just the eventual line of thought). If possible, some of the discarded alternatives could be mentioned along with the reasons why they were eventually decided against. The first draft of the current proposal actually started with this approach: https://github.com/dlang/DIPs/commit/677c4e2bd5ff9b4bcbca35a28831560d5ce06f8c Hopefully this will help: https://github.com/dlang/DIPs/pull/88
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 2 Begins
On Friday, 21 July 2017 at 19:36:08 UTC, H. S. Teoh wrote: In short, I feel that a more substantial discussion of how we arrived at the current form of the proposal is important so that Walter & Andrei can have the adequate context to appreciate the proposed syntax changes, and not feel like this is just one possibility out of many others that haven't been adequately considered. I think we have to assume they've been reading the prior threads. If they have specific questions or concerns, then we have to hope they'll express them here, rather than just reject the proposal. I'll put you in the author line as a co-author if you want, as this _is_ essentially your proposal. And there should be at least one example of a body-less function declaration with contracts, just to see what it looks like in that case. Right now, such declarations are only legal in interfaces. That might change if the implementation changes. Here's how one would look with the new syntax: interface I { void fun(int a) in(a); }
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 2 Begins
On Saturday, 22 July 2017 at 03:05:55 UTC, aberba wrote: How about this in current syntax? (that's what I do) int func(int a) in { assert(a >= 0); } out(result) { assert(result >= 2); } body { return 2 * a; } an improvement could be: int func(int a) in assert(a >= 0); out(result) assert(result >= 2); body { return 2 * a; } just like an in-line if-else statement That was actually part of my original proposal [1]. People in that discussion [2] seemed more excited about the current proposal , and they won me over to it. If the syntax doesn't assume `assert`, probably 99% of contracts will use it explicitly, so it's really making it easier by just assuming it. And being allowed to omit the word `body` (now `do`) with the new syntax is an important feature. That said, I don't think your proposal is incompatible with the current one. It just might be made unnecessary by it. [1] https://github.com/dlang/DIPs/blob/d2dc77802c74378cf4545069eced21f85fbf893f/DIPs/DIP1009.md [2] http://forum.dlang.org/post/gjtsfysvtyxcfcmuu...@forum.dlang.org
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 2 Begins
On Friday, 21 July 2017 at 18:55:08 UTC, Moritz Maxeiner wrote: I really like how the syntax turned out. My only remaining peeve is the `ContractParameters` nomenclature in the grammar section, because it implies that asserts are contracts. Maybe I should have stuck with AssertParameters. That can easily be fixed.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 2 Begins
On Friday, 21 July 2017 at 15:13:09 UTC, Timon Gehr wrote: "in and out expressions must come at the end of the function declarator suffix, and before the regular contracts, if any" The implementation actually allows all possible notations for contracts to be mixed freely. Whether or not 'do' is required depends on what notation is used by the last contract. I decided that for grammar purposes it would be easier to require the contract expressions before the contract blocks. Contract blocks are currently conflated grammatically with FunctionBody [1]. An accurate grammar that describes the current implementation would be twice as complicated, because FunctionBody would have to be redefined. I want the feature to be as simple as possible to understand, so I didn't think it was worth it. There has also been mention of the possibility of improving the implementation of contracts to allow separate compilation, in which case the signature, plus contracts, could some day appear without the body. I wanted to define the new expressions to accommodate this possibility. [1] https://dlang.org/spec/grammar.html#FunctionBody
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 28 June 2017 at 14:33:52 UTC, Moritz Maxeiner wrote: The DIP is still at pre-preliminary review round 1 (since it hasn't finished yet). The current syntax proposal is effectively emergent through H. S. Teoh's general proposal [1], Solomon E's out enhancement [2], and Timon Gehr's implementation of the former two [3]. You can see in Timon's examples [4] how it looks (and contracts are part of a function's signature). Yes, this thread has been incredibly productive, and has resulted in a complete metamorphosis of my original proposal, into a proposal that I think is very strong. I have to rewrite the existing DIP to reflect that.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 28 June 2017 at 01:23:18 UTC, MysticZach wrote: On Tuesday, 27 June 2017 at 09:18:11 UTC, Olivier FAURE wrote: A bit late to the party, but I would recommend the following syntax: out (void; myTest) for argument-less tests. A casual reader would be less likely to see this in code and think it's some sort of typo; it would be easier to google; and it would make some semantic sense (functions that don't return anything return void). It's a creative suggestion, and not a bad one. But it's verbose, and I'd like to be able to omit the identifier altogether. Currently, only `for` loops allow this, as when people write: for( ; ; ) Theoretically, `foreach foreach( ; a) ... out( ; ...) Currently `foreach` does not allow omitting Sorry, clicked the `send` button too soon. Anyway, currently `foreach` does not allow omitting the initial identifier, but in theory it _could_ be enhanced to do so. If `out` expressions also allow this, then we get the desired symmetry between `for`,`foreach`, and `out` expressions, with minimal verbosity. That's the solution I promote. It's better than requiring something to be there when nothing really has to be. I don't know why `foreach` isn't already this way.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Tuesday, 27 June 2017 at 09:18:11 UTC, Olivier FAURE wrote: A bit late to the party, but I would recommend the following syntax: out (void; myTest) for argument-less tests. A casual reader would be less likely to see this in code and think it's some sort of typo; it would be easier to google; and it would make some semantic sense (functions that don't return anything return void). It's a creative suggestion, and not a bad one. But it's verbose, and I'd like to be able to omit the identifier altogether. Currently, only `for` loops allow this, as when people write: for( ; ; ) Theoretically, `foreach foreach( ; a) ... out( ; ...) Currently `foreach` does not allow omitting
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Monday, 26 June 2017 at 21:06:10 UTC, Timon Gehr wrote: The DIP is missing the corresponding syntax for invariants: class C{ private int x=1; invariant(x>0, "x must stay positive"); } Implementation: https://github.com/dlang/dmd/compare/master...tgehr:contract-syntax Well done. It seems to speak to the intuitive nature of the design that it's so easy to deduce how it would work in this context.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Sunday, 25 June 2017 at 12:10:02 UTC, Timon Gehr wrote: The path of least resistance is to use existing language constructs, i.e. out result => assert(result > 0) Andrei This would face quite some resistance, on the following grounds: out(result){ assert(result > 0); } // exists out result => assert(result > 0) // more of the same out(result; result > 0) // better I also imagine we'll end up seeing quite a lot of: out( ; __result > 0) ...even though `__result` is still undocumented, because it's DRY. That's actually an incentive, IMO, to go ahead and document it. It's just tighter.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Saturday, 24 June 2017 at 12:26:57 UTC, Moritz Maxeiner wrote: Should the need ever arise for (new) contract and assert grammar to diverge it can be dealt with then by whoever does the diverging. Yes, I'll keep the grammar the same for now, because there is a benefit to doing so, in that any improvements to the assert grammar will immediately apply to the contract grammar too.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Saturday, 24 June 2017 at 02:31:09 UTC, Solomon E wrote: I think my proposal to add another use of semicolon in parentheses, like `foreach` or `for` but not the same as either, was needlessly complicated. It's very popular, actually. :) in (a) out (result) (a) This resembles template function declarations. Both proposals resemble something else that they are not. Your proposal for `out` is attractive, actually, because the semantics of foreach are closer to what we're looking for than are the semantics of template declarations. as syntax sugar where each (a) lowers to {assert(a);} and in future can lower to something else, to renovate contract implementation The foreach syntax can be just as easily lowered: out(result; a) ...to: out(result) {assert(a);} That also includes the optional message. out(result; result < 1, "alert!") ...lowers to: out(result) { assert(result < 1, "alert!"); } That's so much easier, in every way. There's no intention of making it complicated!
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 21:36:07 UTC, Moritz Maxeiner wrote: Contracts within the DbC paradigm *are* abstractions that do not necessitate any particular implementation. In practice, though, what must any such implementation actually achieve? 1. allow the source code to express its intent to the reader 2. prevent programs in invalid states from continuing 3. provide information about those invalid states after the fact Goal 1 lies in the domain of the language grammar. Goals 2 and 3 reflect the behind-the-scenes implementation of that grammar. Most native languages simply (sensibly) choose to use asserts for that. Which could mean that they use the grammar of asserts, e.g. `assert(a, "message");`, or that they use a specific behind-the-scenes implementation of that grammar, i.e. the code that such a grammar compiles to. It would only couple the contracts with asserts if the DIP also specifies that asserts *must* be used for the lowering (which I would be against btw). I think this reveals the sticking point. I think that the way D compiles assert expressions can and should be improved by making it more flexible behind the scenes. But that doesn't necessarily mean that the grammar needs to change. The problem is that we need to put *some* grammar into the new `in` expression design. If we allow, for example, a random sequence of function arguments, e.g.`in(a, b < 0, "yay!", myDvar)` there is no go-to way to implement it. The surface code would then require a particular backend implementation that could handle the grammar, and would furthermore now be coupled with that implementation. I'd rather not deal with that problem. It's vastly easier to just put my faith into the `assert` grammar, and hope that any improvements that it needs and receives will apply equally to `assert`s as well.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 20:49:35 UTC, Moritz Maxeiner wrote: Normal usage of the new syntax? If asserts later on get a (possibly breaking) syntax overhaul that will affect (and forward breakage to) the contract syntax, as well, if it uses the same compiler infrastructure. I believe this fear is irrational. A breaking change to the assert syntax would be extremely stupid. Imagine how much code would break if there were a breaking change to `assert`! The only possible changes to it must be additive. My naive assumption is that any improvement in the in/out grammar would also apply to asserts, and vice versa. Why should it? Contracts are not asserts or vice versa. I 95% disagree. As far as I can tell, they are _very_ similar. The only difference I can see is that when you violate an `in` contract, the exit message should point to the caller instead of the callee as the source of the problem. Beyond that, they seem like little more than glorified `assert`s. I think their greatest benefit is in helping the programmer read and understand the logic of the program, rather than in anything the compiler can do with them. I'm not sure what you're getting at here. With the proposal Timon implemented we have the following: - the newer, decoupled contract syntax that separates contract specification and implementation from each other; Timon's implementation uses asserts as the internal contract implementation AFAIK Not exactly. It actually _couples_ `in` expressions with assert expressions. In essence it just lowers int fun(int a) in(a) { } ...to: int fun(int a) in { assert(a); } { } This is a sensible default. In the future, some logic could be added to provide a hook to a different implementation of the `in` function, so that it would lower instead to: int fun(int a) in { __userDefinedInContract(a); } { } But I suspect the vast majority will stick with the default.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 20:03:17 UTC, Moritz Maxeiner wrote: No. Asserts are the meat of in/out contracts, these are actually asserts. Anything you do to the assert grammar should be done here as well. I agree. I can understand wanting to pass in/out violations to a different handler behind the scenes. But I don't see why that should affect the grammar. Because coupling the new contract syntax and assert syntax in the grammar means that changing assert syntax will affect the new contract syntax (when it shouldn't, as they are semantically decoupled). By default, I assume they will not be semantically decoupled, that they will all just use regular asserts. I think the consistency the assert grammar will bring is worth a whole lot, as once it is understood in one place, it is understood everywhere. That's why it's so easy for Timon to implement, for example, because the assert logic is already available. So, for me to be convinced that the the grammar for in/out contracts should be different, I'd have to see a clear and compelling use case. What exactly did you have in mind? My naive assumption is that any improvement in the in/out grammar would also apply to asserts, and vice versa. I would go further and say that having consistency among all types of contracts is valuable enough to be worth sacrificing a considerable amount of flexibility in the grammar, even if a compelling use case were presented.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 18:42:55 UTC, Steven Schveighoffer wrote: On 6/23/17 2:24 PM, Moritz Maxeiner wrote: I'm all for this syntax, just one spec/implementation question: If the new contract syntax (formally) shares grammar rules with assert, won't that cause more work for people who want to update the assert syntax later (since they will have to take contracts into account)? No. Asserts are the meat of in/out contracts, these are actually asserts. Anything you do to the assert grammar should be done here as well. I agree. I can understand wanting to pass in/out violations to a different handler behind the scenes. But I don't see why that should affect the grammar.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 18:20:23 UTC, Moritz Maxeiner wrote: On Friday, 23 June 2017 at 18:03:26 UTC, Timon Gehr wrote: On 23.06.2017 18:21, H. S. Teoh via Digitalmars-d wrote: [...] Agreed. Implementation: https://github.com/dlang/dmd/compare/master...tgehr:contract-syntax (At most one contract of each type is supported. It is not very hard to implement multiple contracts, but this requires touching semantic analysis.) Holy ***. I set aside some time this weekend to try implementing this myself as an exercise, but oh well. Thanks! I know! I'd say it'll take me a good deal longer to rewrite the DIP than he's taking to implement it!
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 16:21:28 UTC, H. S. Teoh wrote: On Fri, Jun 23, 2017 at 09:06:59AM +, Solomon E via Digitalmars-d wrote: [...] T foo(T)(T x, T y) in (x > 0, y > 0) out (r; r > 0) { return x % y + 1; } Hmm, I like this syntax for out-contracts! It borrows from existing foreach syntax, so it has some precedence, whereas the previous proposal of `out(...)(...)` looks uglier and also looks deceptively like a template function declaration. `out (r; r > 0)` gets my vote. OTOH, I don't like the comma in the in-contract. Let's just keep it as either separate clauses: in (x > 0) in (y > 0) Yeah, my take is that the grammar for `assert`s applies to the new syntax as well. If the grammar for asserts is this: AssertExpression: assert ( AssertParameters ) ... then the grammar for the new syntax is: InExpression: in ( AssertParameters ) OutExpression: out ( ; AssertParameters ) out ( Identifier ; AssertParameters )
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 13:58:38 UTC, Moritz Maxeiner wrote: OT: Anyone interested in a DIP for more template constraint unfulfilled information in a consistent way to contracts (?) : --- int myFunc(Args...)(Args args) if (Args.length > 0, "Starving!") if (Args.length > 1, "Still hungry!") if (Args.length > 2, "Just a little bit more!") in (args[0] != 0, "Yikes!") in (args[1] > 1, "Why you do this?") out (result; result > 0, "Oops...") { ... } --- This would be a good question for a different thread.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 13:00:30 UTC, Steven Schveighoffer wrote: On 6/23/17 5:06 AM, Solomon E wrote: What I expected from my impression of existing D syntax was that something like this might be coming up: T foo(T)(T x, T y) in (x > 0, y > 0) out (r; r > 0) { return x % y + 1; } The out contract looks pretty good actually. The in contract, not as good. That looks like a comma expression. I'd rather see this be: in(x > 0) in(y > 0) or in(x > 0 && y > 0) I would assume the grammar for these expressions would be the same as for `assert`s. So you're right in pointing out the flaw above.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 09:06:59 UTC, Solomon E wrote: What I expected from my impression of existing D syntax was that something like this might be coming up: T foo(T)(T x, T y) in (x > 0, y > 0) out (r; r > 0) { return x % y + 1; } `out ()` has syntax similar to `foreach` and `for`, allowing mentioning something about the return type, or unpacking a return value, then testing it. (When there's no semicolon, an `out` block follows.) This is a good idea, and I didn't think of it. Points: * It would be great if you were allowed to omit the identifier before the semicolon in cases where you didn't need it. The existing foreach grammar does not allow this [1]. I'm not sure if that is intended to prevent bugs, or if it was just never thought to be useful. * The grammar for what's inside the parens should also mimic what's inside `assert`s, allowing an error message. So the new grammar would actually be a mix of the existing `foreach` and `assert` grammars, e.g. out(r; r >0, "contract violated!") Comparing with the double parens solution: out(result)(result > 0, "violation!") out()(otherData > 0, "prohibited!") vs. out(result; result > 0, "violation!") out(; otherData > 0, "prohibited!") It's a close call. Nice job! [1] https://dlang.org/spec/statement.html#foreach-statement
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 00:17:23 UTC, Steven Schveighoffer wrote: We can call that contextual "keyword" result. Doesn't have to be a keyword, just the implied return value symbol name. Another problem is that any given contextual reserved identifier you choose will run the risk of shadowing other variables. `result` could easily already be defined in an outer context. A solution to this is to use a variable starting with `__`, as those are the existing way of defining reserved identifiers. Maybe `__result`?
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Friday, 23 June 2017 at 00:17:23 UTC, Steven Schveighoffer wrote: int foo() out(result) { } what does this mean? Does it mean assert(result) on the out contract, or this is the old form of out? If we didn't have contract syntax already, and many existing code bases that use it, I'd say this would be the way to go. The current grammar is: OutStatement: out ( Identifier ) { Statement } out { Statement } So one way out is simply to demand that there be more than just an identifier when checking in the new way. So you'd have to require more tokens, e.g.`out(result !is null)` instead of just `out(result)` in order for the parser to easily distinguish between the two. It's a little messy. On the other hand, requiring two sets of parens is clean, but ugly. So it's a choice between ugly and messy, unless someone comes up with something more elegant.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Thursday, 22 June 2017 at 21:56:29 UTC, Timon Gehr wrote: On 22.06.2017 23:51, MysticZach wrote: On Thursday, 22 June 2017 at 21:41:55 UTC, MysticZach wrote: The whole double parentheses is a bit ugly to me. Is there any problem with out(return > 0) instead of out(r) (r > 0) I'm sorry, I didn't read closely. I think that's just asking for trouble, wanting to use `return` as an identifier. Timon found a specific reason why, but in general contextual keywords are frowned upon for precisely this type of ambiguity in the meaning of the code. (It's not a contextual keyword. A contextual keyword is an identifier that is reserved in some contexts but not others.) I would argue that the above suggestion promotes `return` precisely that way. It's now an identifier in precisely that one context, but is reserved as a keyword in all other contexts. Not sure what to call it. But we're a little off topic, as we both agree that the above solution to the double parens isn't viable, right?
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Thursday, 22 June 2017 at 21:41:55 UTC, MysticZach wrote: The whole double parentheses is a bit ugly to me. Is there any problem with out(return > 0) instead of out(r) (r > 0) I'm sorry, I didn't read closely. I think that's just asking for trouble, wanting to use `return` as an identifier. Timon found a specific reason why, but in general contextual keywords are frowned upon for precisely this type of ambiguity in the meaning of the code.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Thursday, 22 June 2017 at 20:02:17 UTC, jmh530 wrote: On Thursday, 22 June 2017 at 18:57:40 UTC, MysticZach wrote: [snip] I don't mind that so much, but you made a good point earlier on how out would work with it. The whole double parentheses is a bit ugly to me. Is there any problem with out(return > 0) instead of out(r) (r > 0) The current grammar for `out` is: OutStatement: out { Statement(s) } out ( Identifier ) { Statement(s) } If the out contract with the new syntax had only one assertion, and that assertion were a single identifier, there would be a parsing ambiguity: int fun(int a) { int nested(int b) out (b) // out with a single assert, or out with identifier and brackets? { assert(b); // function body, or `out` contract? } do { ... } // function body, or do-while loop? while (true); // only here do we finally figure it out } There's probably an easy way to tidy this up, but I couldn't think of one off hand, so I suggested `out ( ) ( IfCondition )` as an unambiguous alternative. It would in fact be the rare case, since most `out` contracts will just want to check the return value. Also, I can see the point of Critique 5 in the DIP for not including in/out anywhere and wanting to pin it to the top of the body. The suggestion in your post at least succeeds at that. I assume you mean H.S. Teoh's suggestion? If it's as good as the others seem to think, hopefully it will succeed more than that... but preventing enhancement 5 is as simple as having the compiler issue an error if the user violates the rule that contracts must occur first and be grouped together in the body.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Thursday, 22 June 2017 at 14:08:32 UTC, jmh530 wrote: My recollection is that the most significant reason to use contracts in D is because of contract inheritance. There's a lot of focus in this discussion on normal functions, when I would say that contracts really aren't even needed. So a more useful situation to consider then is: [...] I would say keep the current behavior for backwards compatibility (maybe with the body/do change), but also allow the following code: class Foo { int fun(int a) { in { assert(a > 0 && a < 10); } return a; } } class Bar : Foo { int fun(int a) { in {assert(a > 0);} return a; } } The existing proposal allows this, and goes further and allows removing the unnecessary brackets after `in`: class Foo { int fun(int a) { in assert(a > 0 && a < 10); return a; } } class Bar : Foo { // override override int fun(int a) { in assert(a > 0); return a; } } Some people don't like the cognitive dissonance of seeing `in` inside the function. It really doesn't look that bad to me, and I'm glad to have a little support for the idea. But there are a couple more considerations. First, classes in D are not as popular as they are in some other languages, because of how powerful regular structs have become. I'd want to get more feedback on the value of improving a syntax (assuming it is clearly an improvement, which several people so far disagree with) that is only really valuable in cases that aren't used that much. There are other questions too. The syntax is only one of three possible reasons contracts in D aren't that popular. The second reason is that the specific implementation, i.e. the "backend", currently has limited support as described by H.S. Teoh [1]. The third reason is more abstract and harder to pin down, which is that some things are just more attractive in theory than they are in practice. The question is, even with the best possible syntax, and the best possible implementation, how much total value can `in` and `out` contracts add to language? How much more total use would they see? If we knew in advance that the answer to the third question is, "People wouldn't use them that much," then we might spare ourselves the effort of improving them. We could more or less drop the issue as a lost cause. But I suppose the premise of this DIP is that it's worth it to try to find out. It also looks like there will be a separate DIP for reimplementing the backend, so this one will focus, as it already does, on the syntax. That said, H.S. Teoh's version of the above code would look like this: class Foo { int fun(int a) in(a > 0 && a < 10) { return a; } } class Bar : Foo { override int fun(int a) in(a > 0) { return a; } } I'm leaning towards pushing this one, as it simply hasn't gotten the pushback that mine has so far. I do have a problem with it, which is that the checking logic is mingled in with the grammar. This doesn't usually happen in D, which normally requires you to explicitly write `assert` in order to assert something. Here, `in` becomes grammatically equivalent to an `assert` expression, but one which is only allowed in the function signature. At minimum, I can say that the reception for this idea has been more positive than for mine. But I do appreciate the support :-} [1] http://forum.dlang.org/post/mailman.3554.1498074198.31550.digitalmar...@puremagic.com
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Thursday, 22 June 2017 at 13:11:12 UTC, MysticZach wrote: As long as one is doing this, maybe a proposal for user-defined `assert` should be provided too? It'd be interesting to have a dedicated file for user-defined assert and contract configuration. The core idea is to allow *everyone*, from large companies to individual hobbyists, to use `assert`, `in`, and `out`, and have it work the way they want. I would definitely need help writing that DIP. :-)
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Thursday, 22 June 2017 at 12:54:00 UTC, MysticZach wrote: On Thursday, 22 June 2017 at 10:59:18 UTC, Moritz Maxeiner wrote: Again, that's not what H.S. Teoh's proposal would do. All it does is install an *implementation agnostic*, *abtract* way to specify contracts into the grammar. Whether that is lowered to assert, or anything else is an implementation detail and it certainly isn't fixed to asserts. Okay. Then the proposal needs to be accompanied by an explicit description of how to hook into the new semantics. Which is what you provided, but I suppose it would need to be exactly specified. In particular, where exactly is the code for the (optional) user-defined hook to be found? In a separate file, maybe as indicated with a command line option, e.g. `-contractsConfig=myContracts.d`? As long as one is doing this, maybe a proposal for user-defined `assert` should be provided too? It'd be interesting to have a dedicated file for user-defined assert and contract configuration. The core idea is to allow *everyone*, from large companies to individual hobbyists, to use `assert`, `in`, and `out`, and have it work the way they want. I would definitely need help writing that DIP.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Thursday, 22 June 2017 at 10:59:18 UTC, Moritz Maxeiner wrote: Again, that's not what H.S. Teoh's proposal would do. All it does is install an *implementation agnostic*, *abtract* way to specify contracts into the grammar. Whether that is lowered to assert, or anything else is an implementation detail and it certainly isn't fixed to asserts. Okay. Then the proposal needs to be accompanied by an explicit description of how to hook into the new semantics. Which is what you provided, but I suppose it would need to be exactly specified. In particular, where exactly is the code for the (optional) user-defined hook to be found? In a separate file, maybe as indicated with a command line option, e.g. `-contractsConfig=myContracts.d`? DIP1003 did not introduce an entirely new system, it merely slightly changed an existing sytem. DIP1009 *does* introduce several new syntax forms, i.e. adding a whole new system, which means it *also* introduces the responsibility of maintaining backwards compatibility when someone tries to improve contracts again (and then we would have three systems to specify contracts). Okay, I'm a convert. Although still one big downside is that DbC in D is somewhat impaired, as H.S. Teoh pointed out [1]. [1] http://forum.dlang.org/post/mailman.3554.1498074198.31550.digitalmar...@puremagic.com
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Thursday, 22 June 2017 at 12:21:29 UTC, MysticZach wrote: I start to get the nagging feeling that your point about the limitation in D's DbC implementation is actually the fatal flaw here. It's currently _illegal_ (outside of interface declarations) to expose the signature separately from the body, which, as you point out, is more or less the whole point of DbC. The existing system is itself distinctly _worse_ than just writing out asserts manually... and as far as I can tell, none of the alternative syntaxes is a decisive improvement over it. Yours looks the best, but implying `assert` in the grammar seems to be going too far, especially for a DbC system that is only half functional. If the `assert` system were made more user-definable, it would make more sense. Do you agree with me on this? Plans to improve `assert` are already in the air. Maybe we should wait on them before promoting your suggestion? Conversely, as Moritz suggests, contracts could have their own separate logic, with optional user-defined hooks. Do you have a suggestion on how to implement this behind the scenes?
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Thursday, 22 June 2017 at 06:43:38 UTC, H. S. Teoh wrote: On Thu, Jun 22, 2017 at 05:46:06AM +, MysticZach via Digitalmars-d wrote: [...] As far as syntax subtrees not belonging to their parent, I can see where the cognitive dissonance comes from. But it just doesn't seem that bad to me, since contracts are always executed as if they are sequential statements anyway. [...] Then possibly you're missing the point behind DbC. The idea of "executing" a contract seems to indicate that you're taking the current D implementation of it as normative. I understand. Thus, a better DIP would suggest reimplementing D's DbC system altogether. Because as it is, they are little more than syntax dressing, which happens to be less convenient that just writing out the asserts in the first place. They're more like syntax _vinegar_ than sugar. Which explains why hardly anyone uses them. Why write this: int fun(int a) in { assert (a); } do { return a; } ...when you could just do this: int fun(int a) { assert(a); return a; } With your improvement, it's a little better, int fun(int a) in (a) { return a; } ...but the cost is that `assert` is implied, and no other system of checking is allowed, which seems like a sufficient flaw to make it not decisively better. To solve this, you'd have to decouple `assert` from the contract, requiring this: int fun(int a) in (assert(a)) { return a; } This also looks good. But now the grammar is weird because it's just an expression in there without a statement, which doesn't happen anywhere else in D. I start to get the nagging feeling that your point about the limitation in D's DbC implementation is actually the fatal flaw here. It's currently _illegal_ (outside of interface declarations) to expose the signature separately from the body, which, as you point out, is more or less the whole point of DbC. The existing system is itself distinctly _worse_ than just writing out asserts manually... and as far as I can tell, none of the alternative syntaxes is a decisive improvement over it. Yours looks the best, but implying `assert` in the grammar seems to be going too far, especially for a DbC system that is only half functional. If the `assert` system were made more user-definable, it would make more sense. Do you agree with me on this? Plans to improve `assert` are already in the air. Maybe we should wait on them before promoting your suggestion?
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 19:34:53 UTC, H. S. Teoh wrote: This is a sticky point about D's current DbC implementation that myself and several others feel is a design flaw. In particular, that in-contracts are executed as part of the *callee*, when the intent of DbC is really that it is the obligation of the *caller* to fulfill its stipulations, and therefore the contract verification should happen at *caller* site rather than at the beginning of the callee. This particular implementation detail causes problems with binary-only libraries: most library vendors would prefer to ship the library compiled with -release rather than not, but in -release, the asserts in any in-contracts would be elided, making them essentially non-existent by the user uses the library. So you either have to dispense with DbC altogether, or be forced to ship two versions of your library, one with contracts compiled in and one without, in order for your users to benefit from DbC *and* not have to suffer performance penalties in their own release builds. Had in-contracts been implemented on the caller's side instead, this would no longer be a problem: the contracts will still be part of the library API, so the user can benefit from them when not compiling with -release, but now the library itself can be shipped only with the binaries compiled with -release for best performance. This is probably something outside the scope of this DIP, however. It's related. A design flaw in D's DbC means that contracts on the whole are less important. Which means, unfortunately, that improving them is less important. Which could affect the final decision. But on the other side, binary-only libraries published in release mode are actually rare in D, right?
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Thursday, 22 June 2017 at 00:27:38 UTC, Timon Gehr wrote: On 21.06.2017 19:39, MysticZach wrote: My counterargument to that is that it's possible that the cognitive dissonance only occurs because of what people are used to, rather than what is inherent to the syntax. This is a purely philosophical distinction without empirical basis. Well I never experienced the dissonance myself, and was surprised to find that others did experience it. I just thought my proposal was a better syntax for `in` and `out` contracts. Well my impression was that Walter liked it too, although I could have misinterpreted his comment here: http://forum.dlang.org/post/ogvt66$1bcp$1...@digitalmars.com He is saying it is good that a DIP to improve contract syntax /exists/. I agree with that. It's really not clear what he meant. I guessed that the highest probability of what he meant was that he actually liked the DIP, as opposed to the mere fact that it _was_ a DIP. But as I already said, I could have misinterpreted his comment. In the face of lack of knowledge, it's a sign of wisdom to admit that one might be wrong, I think. If such an alternative checking system is utilized, there should be a way to hook into the checking logic. Improving the checking logic interface may solve at a higher level the problem I'm trying to solve at a very low one, with mere syntax changes, and it might be (is probably?) the best way forward. Your proposal does not solve this problem, and there is no need for this DIP to do that. The goal of this DIP, and the problem I'm trying to solve, is "Improve Contract Usability." And for this, H.S. Teoh's proposal is a very good one. But it still has a sticking point, which I want to resolve, namely that it elevates the existing `assert` functionality beyond the current requirement that one must explicitly write `assert`, going so far as to imply it in the grammar itself. But because of many complaints about the limitations of the assert mechanism as it currently exists, I would hesitate to install it into the grammar as the "One Chosen Way" to bail out of contracts with the new syntax. However, if the functioning of the `assert` mechanism were more customizable, then it would be easier to entrust it, in my opinion, with the "sacred responsibility" of being installed into the grammar. H.S. Teoh's proposal would then stand on a firmer foundation, and my initial proposed syntax would become the inferior optionl. At that point, this DIP could be rewritten to advocate his syntax instead. (I think it would be better to just retain the number and title "DIP1009: Improve Contract Usability" than to make a new one for the same issue. Other DIPs have followed this pattern, where it was the goal and title that remained the same, while the specifics changed.) We are looking for a significant improvement. Otherwise, what's the point? We need to justify the cost. The intent of my proposal was to make a small improvement. The cost (or so I thought, and may still believe) was also small. Small improvements are still improvements. DIP1003 is an example of this. https://github.com/dlang/DIPs/blob/master/DIPs/DIP1003.md The point of contracts is assigning blame by documenting assumptions and guarantees. If something within the function body crashes, it's ideally the fault of the function implementation. ... I like new as long as it is an improvement. This is not. Having syntax subtrees that do not actually logically belong to their parent in the grammar is awkward language design, especially if they affect the parent's signature. I'm still wondering what, in practice, the difference really is. With existing syntax: int fun(int a) in { assert(a); } // 1 do { assert(a); // 2 ... } What will the compiler or programmer actually learn from 1 if it violates that they won't learn from 2 if it violates? What is the practical incentive for `in` contracts at all? All my new syntax does is assume that there is in fact a difference between 1 and 2, and makes 1 easier to write, as: int fun(int a) { in assert(a); // 1 assert(a); // 2 ... } As far as syntax subtrees not belonging to their parent, I can see where the cognitive dissonance comes from. But it just doesn't seem that bad to me, since contracts are always executed as if they are sequential statements anyway. I would imagine that new programmers who only ever encountered the new proposed syntax would be surprised that the old syntax ever existed in the first place, as it's so unnecessarily awkward. But at this point, we might as well wait for more feedback from other people.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 18:04:07 UTC, Moritz Maxeiner wrote: On Wednesday, 21 June 2017 at 17:55:05 UTC, MysticZach wrote: Question: If `assert` itself allowed a user-defined hook, what would the remaining justification be for decoupling `in` and `out` contracts from the `assert` logic? Because then you won't have normal asserts and contracts be subject to different semantics? If I use a library, I may very well want to disable the library's internal assert checks (because I have enough experience that it's working properly), but keep it's contracts alive, because my code is still shiny new and riddled with bugs. Timon appears to think that the checking logic is more monolithic. From his reply above [1]: "If [an alternative checking system is utilized], there should be a way to hook into the checking logic. This has nothing at all to do with contract syntax. asserts and contracts are coupled already, as in-contracts form a disjunction on override by catching AssertErrors." So I'm hoping more people will weigh in on this issue. For example, how easy is it to separate a library's internal contracts from its external ones? Would you have to write internal contracts in a different way from the ones facing the user? How often is this distinction the one causing problems with productivity? The way I'm thinking about it would be that if there were a pragma to turn off contracts in a particularly hot code path, then the rest of the program could remain safe, while the fast part was allowed to go as fast as possible, addressing the performance issue. But regarding the information issue, what kind of error information is better delivered specifically through compiler knowledge of `in` and `out` contracts, versus what it would deliver in the same way via regular `assert`s? Or are all contracts basically just fancy sugar for asserts at the beginning and end of a function body? What can the compiler do with the extra information? What can it say to the user that the user wouldn't already be able to figure out if it were a regular assert? [1] http://forum.dlang.org/post/oie2nt$emf$1...@digitalmars.com
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 17:38:02 UTC, Moritz Maxeiner wrote: But another option is simply to upgrade `assert` to make sure it offers what everyone wants. That would be really cool, but I doubt it will be feasible here. I think that in this case it will more likely end up with everyone hating that universal solution equally. Well the universal solution could be, for example, the suggestions from my post in the other thread: 3. Allow an additional compiler flag for more informative, but heavier asserts, e.g. `-release=informativeAsserts`. 4. Allow a pragma in the code, e.g. `pragma(asserts, none/regular/informative)` for what kinds of asserts are to be used at a given moment. This would be added flexibility, rather than a one-size-fits-all solution. So the word "universal" is a little deceptive. The options could also include a user-defined hook for assert. Question: If `assert` itself allowed a user-defined hook, what would the remaining justification be for decoupling `in` and `out` contracts from the `assert` logic? That's what I mean by thinking the problem might be fixable by upgrading `assert`.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 15:18:21 UTC, Timon Gehr wrote: On 21.06.2017 02:51, MysticZach wrote: I think people could get used to the cognitive dissonance. That's really not what D is about. My counterargument to that is that it's possible that the cognitive dissonance only occurs because of what people are used to, rather than what is inherent to the syntax. I've already gotten used to it just by writing this DIP. I think it is likely that you are an outlier. Well my impression was that Walter liked it too, although I could have misinterpreted his comment here: http://forum.dlang.org/post/ogvt66$1bcp$1...@digitalmars.com If such an alternative checking system is utilized, If so, there should be a way to hook into the checking logic. This has nothing at all to do with contract syntax. asserts and contracts are coupled already, as in-contracts form a disjunction on override by catching AssertErrors. Improving the checking logic interface may solve at a higher level the problem I'm trying to solve at a very low one, with mere syntax changes, and it might be (is probably?) the best way forward. the syntax for writing contracts should be as easy for them as for those using `assert`. Maybe, but your DIP does not pull its own weight as long as the latter syntax is not a notable improvement over what we have now. Well, my view is that my DIP is actually a very lightweight syntax change, and an equally lightweight improvement in contract syntax, so it's a lost-cost, mild improvement . The cognitive dissonance argument is the main one against it, and I really don't know if that dissonance is based on fundamental flaws in the way I'm thinking about it, or just the "Shock of the New" [1]. If allowing contracts in the function body really is a fundamentally flawed concept, then I won't keep advocating for it. H. S. Teoh's counter-proposal is, and I think your DIP has a much higher chance of acceptance if you go with it. I'm not actually worried about whether the proposal is accepted or not, as long the best ideas and arguments come forward and are heard. I have more faith in the process than I do in any particular proposal. As far as Teoh's proposal, I would say that its quality is highly correlated to the percentage of projects that find built-in `assert` adequate to their needs, which is hard to assess precisely - the better `assert` is, or can be made to be, the better Teoh's proposal is, I'd say. Moritz [2] suggests solving the problem by decoupling `in` and `out` contract syntax from the checking logic. This seems like a good way to go too. But I'd like to see a little more justification for it. [1] Robert Hughes documentary, "The Shock of the New" https://www.youtube.com/watch?v=J3ne7Udaetg [2] http://forum.dlang.org/post/uzzwmgqoqxuxhusjv...@forum.dlang.org
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 14:49:09 UTC, Moritz Maxeiner wrote: On Wednesday, 21 June 2017 at 13:24:24 UTC, MysticZach wrote: So weird how this discussion is happening in parallel with this other discussion :-) : http://forum.dlang.org/post/rkdpuuggltowhqmcm...@forum.dlang.org It is, though as I have pointer out over there, I would really like to decouple assert semantics from the new contract semantics to achieve the maximum elegance we can within the design limits of the language. Well I'd be just as happy expanding the design limits of the language, i.e. `assert`, if that were a better option. The issue you raise is just how different are `in` and `out` contracts from regular `assert` contracts. They _are_ all listed in the same section of the documentation [1], for whatever that's worth. The practical question is whether one can assume that the same semantics used for `assert`, whatever they may be, will in all cases be desirable for `in` and `out` too. The flexibility of decoupling them is one solution, if they are clearly sufficiently different. But another option is simply to upgrade `assert` to make sure it offers what everyone wants. I don't know what to suggest, because I don't if `assert` can be made good enough to warrant direct inclusion into the grammar. If it could, then all contracts, including plain `assert` statements, would benefit from them. [1] https://dlang.org/spec/contracts.html
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 14:22:52 UTC, Moritz Maxeiner wrote: If you do accidentally forget the extra set of parens on the `out` contract, you would get "Error: `do` expected before function body after a bracketed `out` contract" at the end of the function. (If, however, it a happens to be a nested function, and the next statement in that function happens to be `do`, then the parser will think the `do` loop is the function body... Mmmm, is this worth worrying about??) Could you give a specific (short) example of what you think of? I don't see any potential for ambiguity in the following at a quick glance, so I'm not sure I got where you think the problem lies: --- void foo() { int bar(Args...)(Args args) if (Args.length > 2) in (args[0] != 0) in (args[1] > 1) out (result)(result > 0) { ... } do {} while (true); } --- The only problem is if a programmer forgets to add the additional parentheses, in which case the bracketed block is then mistaken for the `out` contract, which will lead to a confusing error message. For example: void foo() { int bar(Args...)(Args args) if (Args.length > 2) in (args[0] != 0) in (args[1] > 1) out /*whoops, forgot `( )`*/(result) { ... } do { ... } while (true); // Error: while statement cannot contain just `;` } Honestly this doesn't seem like a big deal, as I'd imagine it'd be hard not to notice that code like this wasn't working as expected. And also extremely rare. So I'm still in favor.
Re: dmd -betterC
On Wednesday, 21 June 2017 at 10:51:39 UTC, ketmar wrote: there, of course, *IS* The difference. besides the aesthetical one (seeing failed condition immediately "clicks" in your head, and generic "assertion failed" message is only frustrating), there may be the case when source code changed since binary was built. here, line number gives you zero information, and you have to checkout that exact version, and go check the line. but when failed condition dumped, most of the time it allows you to see what is wrong even without switching to the old codebase (yes, "most of the time" is from RL -- it is literally *most* of the time for me, for example). How would you solve this issue? By pure chance, we're debating this exact same issue right now in the DIP1009 thread [1]. Solutions: 1. Make more informative asserts the compiler default. This threatens performance, which argues against it. 2. Status quo. Make people use whatever asserts they want, e.g. fluent asserts [2]. This would mean that H.S Teoh's proposed syntax for DIP1009 [3] would carry less weight, and the existing proposal would carry more. Elegance is sacrificed for the sake of versatility. 3. Allow an additional compiler flag for more informative, but heavier asserts, e.g. `-release=informativeAsserts`. 4. Allow a pragma in the code, e.g. `pragma(asserts, none/regular/informative)` for what kinds of asserts are to be used at a given moment. 5. ??? [1] http://forum.dlang.org/post/mailman.3531.1498022870.31550.digitalmar...@puremagic.com [2] http://fluentasserts.szabobogdan.com/ [3] http://forum.dlang.org/post/mailman.3511.1497981037.31550.digitalmar...@puremagic.com
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 09:10:33 UTC, MysticZach wrote: On Wednesday, 21 June 2017 at 05:19:26 UTC, H. S. Teoh wrote: Umm... I think we're not quite on the same page here. What *else* are people supposed to use inside their contracts besides the built-in assert?? I believe `assert` would have to be extremely robust to merit being included directly into the syntax of the language. I'm not opposed to this in principle. But I'm no expert, and not willing to assume it's desirable. On the other hand, if `assert` were made so perfect as to ensure that no one would prefer a different method of bailing out of their programs, then you're right, and the problem of contract syntax could be solved at that level instead of the more "pedestrian" approach I'm taking. So weird how this discussion is happening in parallel with this other discussion :-) : http://forum.dlang.org/post/rkdpuuggltowhqmcm...@forum.dlang.org
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 12:05:55 UTC, Moritz Maxeiner wrote: On Wednesday, 21 June 2017 at 09:53:40 UTC, meppl wrote: On Wednesday, 21 June 2017 at 09:27:20 UTC, MysticZach wrote: On Wednesday, 21 June 2017 at 08:15:34 UTC, MysticZach wrote: On Wednesday, 21 June 2017 at 04:16:22 UTC, Moritz Maxeiner Adding `if (...)` should not be different from adding `in (...)` or `out (...)` in terms of syntax rules: it's inconsistent. If you want to have that `do` there, I would argue that it should also become required if only an `if (...)` is present, so --- int myFunc(Args...)(Args args) if (Args.length > 2) { ... } --- should then become illegal and must be rewritten as --- int myFunc(Args...)(Args args) if (Args.length > 2) do { ... } --- I doubt that's going to happen, though (too much code breakage), and I also don't like it. Simply drop the `do`. I tend to agree. I think the grammar for `out` contracts is still murky, though, because the normal existing case is: OutStatement: out ( Identifier ) { OutContractsBody } out { OutContractsBody } My fix would be to require two sets of parentheses for the new conditional, like so: OutStatement: ... // new version out ( Identifier ) ( IfCondition ) out ( ) ( IfCondition ) This makes the grammar unambiguous and clean. And because normally `out` contracts want to check the return value, the last case, `out ( ) ( ... )` will be the rare one. If you do accidentally forget the extra set of parens on the `out` contract, you would get "Error: `do` expected before function body after a bracketed `out` contract" at the end of the function. (If, however, it a happens to be a nested function, and the next statement in that function happens to be `do`, then the parser will think the `do` loop is the function body... Mmmm, is this worth worrying about??)
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 08:15:34 UTC, MysticZach wrote: On Wednesday, 21 June 2017 at 04:16:22 UTC, Moritz Maxeiner wrote: int myFunc(Args...)(Args args) if (Args.length > 2) in (args[0] != 0) in (args[1] > 1) out (result => result > 0) { ... } --- - in contracts take a parenthesis delimited bool expression - out contracts take a parenthesis delimited bool function literal. `out` contracts would also have to account for the case where they don't check the return value. This would confuse the grammar a little in the case of function literals as boolean expressions. A different possible grammar that wouldn't have this problem is: OutStatement: out ( IfCondition ) out ( Identifier ) ( IfCondition ) plus the existing ones: OutStatement: out BlockStatement out ( Identifier ) BlockStatement I may have spoke too soon. If the grammar were: OutStatement: out ( IfCondition ) out ( FunctionLiteral ) It might still work okay. A little hiccup in the semantics, figuring out that the first parameter to the function literal is meant to be the return identifier. Maybe it's not a big deal.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 05:19:26 UTC, H. S. Teoh wrote: On Wed, Jun 21, 2017 at 01:06:40AM +, MysticZach via Digitalmars-d wrote: On Tuesday, 20 June 2017 at 21:04:16 UTC, Steven Schveighoffer wrote: > This is much much better. The verbosity of contracts isn't > really the brace, it's the asserts. I think it's both, and I think the brace is the only thing that can be improved upon. How could you justify insisting that everyone use the built-in asserts for their contracts? [...] Umm... I think we're not quite on the same page here. What *else* are people supposed to use inside their contracts besides the built-in assert?? Many people have expressed discontent with existing asserts. In fact, they were just changed yesterday to address one of these concerns: https://github.com/dlang/dmd/pull/6901 I believe `assert` would have to be extremely robust to merit being included directly into the syntax of the language. I'm not opposed to this in principle. But I'm no expert, and not willing to assume it's desirable. On the other hand, if `assert` were made so perfect as to ensure that no one would prefer a different method of bailing out of their programs, then you're right, and the problem of contract syntax could be solved at that level instead of the more "pedestrian" approach I'm taking. While D currently gives you the flexibility of arbitrary code inside a contract, a contract is not supposed to do anything other than to verify that the caller has passed in arguments that are valid.[1] To me, it's still a question of whether `assert` is the only valid way to bail out of a program. I agree that arbitrary other code inside contracts is bad practice, and that wanting to prohibit it makes sense. Furthermore, contracts specify what constitutes valid input to the function -- this serves both as documentation to would-be callers, and also as specification to the compiler as to what are acceptable arguments. The built-in assert mechanism serves both purposes -- especially the second purpose because the compiler understands it directly, as opposed to some other user-defined mechanism that the compiler wouldn't understand. This wouldn't change just with a syntax rewrite. If the compiler wanted to use `assert` for optimization purposes, it could do that just as well with any of the proposed syntaxes. People who didn't want to use `assert` would be at a disadvantage in this regard. But at least they would have that option. Besides, this is a matter of semantics, whereas this DIP is addressing the DbC syntax. If people demand an alternative to the built-in assert, it's not hard to have the compiler lower the syntax into some globally-defined symbol that can be redefined by the user. Or, indeed, simply funnel the expression into a user-defined assert alternative, e.g.: int myFunc(Args...)(Args args) if (args.length > 1) in (myAssert(args[0] > 0)) { return doStuff(args); } bool myAssert(T)(T t) { // do whatever alternative assert stuff you need to do // here return true; // bypass the built-in assert } I guess the optimizer can elide the assert if it knows it's always true. If this method was sure not to incur a performance penalty, then it may be better than my approach. But the semantics is a different issue than the syntax, which is the scope of this DIP. The scope of the DIP can change, if need be. My primary goal is in the title, to "Improve Contract Usability". I used this title on purpose because I didn't want to get stuck if my proposal turned out to be worse than some other one. If adding a new semantics is actually preferable I can rewrite the DIP (and give you credit — or you can do it yourself, if you want). It was just as important to me to get the ball rolling as to have my particular suggestion accepted. I wanted to stay close to the shore, because I thought it was a little outlandish to propose a whole new semantics. I still think it's a little outlandish, because I can imagine a large organization wanting to rig up its own bailout mechanism, and the new semantics would prevent them from doing that. But so far, the comments suggest that it's worth it to many people.
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Wednesday, 21 June 2017 at 04:16:22 UTC, Moritz Maxeiner wrote: What *I* need from a DIP that addresses DbC in D (to make it viable for me) is to make the simple case as easy as possible to read while not introducing language inconsistencies. With that in mind I am strongly in favor of the syntax H. S. Teoh already proposed: --- int myFunc(Args...)(Args args) if (Args.length > 2) in (args[0] != 0) in (args[1] > 1) out (result => result > 0); int myFunc(Args...)(Args args) if (Args.length > 2) in (args[0] != 0) in (args[1] > 1) out (result => result > 0) { ... } --- - in contracts take a parenthesis delimited bool expression - out contracts take a parenthesis delimited bool function literal. `out` contracts would also have to account for the case where they don't check the return value. This would confuse the grammar a little in the case of function literals as boolean expressions. A different possible grammar that wouldn't have this problem is: OutStatement: out ( IfCondition ) out ( Identifier ) ( IfCondition ) plus the existing ones: OutStatement: out BlockStatement out ( Identifier ) BlockStatement
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Tuesday, 20 June 2017 at 21:04:16 UTC, Steven Schveighoffer wrote: On 6/20/17 1:42 PM, H. S. Teoh via Digitalmars-d wrote: Here's my counter-proposal: since the sig constraint line uses parentheses (and yes, I deliberately planted a sig constraint above just to make this point), why not go for syntactical symmetry? I.e., like this: int myFunc(Args...)(Args args) if (Args.length > 2) in (args[0] != 0) in (args[1] > 1);// one semicolon to end them all This is much much better. The verbosity of contracts isn't really the brace, it's the asserts. I think it's both, and I think the brace is the only thing that can be improved upon. How could you justify insisting that everyone use the built-in asserts for their contracts? If you can, then okay, and other avenues are worth exploring. Are there not, however, many reasons to want to use other types of contracts? That's the main reason I went with my design, because I thought it was going too far to imply `assert` when people might want or need to use other things. This also gives the compiler a better handle on what causes the thing to fail (better error message). I'm pretty sure that the reason asserts are so sparse in terms of error information is due to the fear of slowdown, were they to contain more information. This tradeoff would be present regardless of contract syntax. IMO, this whole proposal doesn't carry enough weight, either your version or the DIP itself. I would not be in favor. Current syntax is understandable, and not too verbose IMO. That's a fair opinion. I wish I had a crystal ball to see how many more people would use contracts if this DIP were accepted. I imagine a lot of people will agree with you. I also know that some people don't [1]. http://forum.dlang.org/post/mailman.2288.1494811099.31550.digitalmar...@puremagic.com
Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1
On Tuesday, 20 June 2017 at 17:42:13 UTC, H. S. Teoh wrote: What would a body-less declaration of a function look like under the new syntax? Hopefully not this: int myFunc(Args...)(Args args) if (Args.length > 2) in assert(args[0] != 0);// semicolon: ouch in assert(args[1] > 1); // semicolon: ouch // How do we end the declaration here? Another semicolon? ; // ouch Such declarations are only legal when declaring interfaces. An investigation reveals that the existing grammar actually does not require that extra semicolon [1]. Thus, the parser would check for `body` (or `do`) after the contract statement, like it already does anyway, and just keep parsing. That said, it's certainly reasonable to disallow the new syntax in virtual interface functions, as is also done for enhancement 3: "Virtual interface functions cannot use this syntax..." But I think a more reasonable solution — and the one I prefer — is simply to disallow semicolon contracts outside the function body, which is also mentioned in enhancement 3: "Note that it's possible to allow enhancements 1 and 2 only within function bodies." What that would boil down to is that existing contracts remain the same. Within function bodies, they can now be expressed as one-liners. Also, I don't like the idea of putting contracts inside the function body. As the DIP already mentions, this makes parsing of contracts more difficult. It also causes cognitive dissonance (contracts are a part of the function's signature, not its implementation). I think people could get used to the cognitive dissonance. I've already gotten used to it just by writing this DIP. As for the parsing, it isn't much more difficult. The compiler just adds any `in` or `out` statement to the list of statements in the contract, creating one when necessary. The only reason it _might_ be more difficult is in the case of a certain kind of documentation parsing which I'm not sure even exists as of yet (somebody tell me if it does!). Such documentation parsing is that which actually wants to publish the contracts verbatim, as part of the documentation. Normally if you're scanning for documentation, you can speed up parsing by skipping the function body. If you don't need to document the contracts verbatim, then you can still just skip them like you would the rest of the function body. Only if you _did_ want to parse the contracts verbatim would it get more complicated. But the problems aren't that bad. The easiest way to find the contracts is to require that they occur at the top of the function. This would allow searching for the tokens `in` and `out` to detect contracts. Anything other than `in` or `out` just gets skipped. But remember, I don't even know if this will be a problem, as in any other scenario, you have to parse the whole program anyway. The compiler just has to add any `in` and `out` statement to the existing contracts as it encounters them. With the alternative enhancement listed in the DIP as 4 (not part of the basic proposal), there is a little more difficulty with something like: int fun(int x) { static if(...) in assert(x); } ...because in this case, there's no existing semantics for that construction, and the compiler will need to work a little magic. I suggested simply rewriting it as: int fun(int x) { in static if(...) assert(x); } which lowers to: int fun(int x) in { static if(...) assert(x); } body { } Which seems to work. But of course the compiler would need to be able to catch what was going on and lower the syntax as necessary, which may or may not be trivial. It's even worse if you allow contracts in arbitrary places inside the function body -- then even somebody reading the code wouldn't know, at a glance, what the contracts are, without scanning the entire function body! That makes contracts *harder* to read and use, rather than easier, in direct contradiction of the purpose of this DIP. This is a strong argument in favor of the existing proposal, which states, under enhancement 3, "They must occur at the beginning of the function..." In the Alternatives section, as enhancement 5, I mentioned the possibility of allowing contracts anywhere in the function. I don't think it's a good idea. I think you're right. But I thought that it was worth mentioning, at least as an alternative. Here's my counter-proposal: since the sig constraint line uses parentheses (and yes, I deliberately planted a sig constraint above just to make this point), why not go for syntactical symmetry? I.e., like this: int myFunc(Args...)(Args args) if (Args.length > 2) in (args[0] != 0) in (args[1] > 1);// one semicolon to end them all This proposal has syntax and semantics too. The syntax is that contracts occur inside parentheses, which I have no problems with. The semantics, however,
Re: Revised DIP Info
On Wednesday, 14 June 2017 at 12:53:21 UTC, MysticZach wrote: On Wednesday, 14 June 2017 at 12:17:50 UTC, Mike Parker wrote: In this thread, I'm specifically looking for feedback on my updates to the readme and the guidelines. Sorry for any confusion. s/GUIDLINES.md/GUIDELINES.md/ In the readme file. The link is good, but the label is wrong.
Re: Revised DIP Info
On Wednesday, 14 June 2017 at 12:17:50 UTC, Mike Parker wrote: In this thread, I'm specifically looking for feedback on my updates to the readme and the guidelines. Sorry for any confusion. s/GUIDLINES.md/GUIDELINES.md/
Re: Revised DIP Info
On Wednesday, 14 June 2017 at 10:32:50 UTC, Andre Pany wrote: [3] https://github.com/dlang/DIPs/pull/71 Hi, the work on this dip is highly appreciated. For my AWS SDK this DIP would make the coding much more readable and also smaller for several use cases. At this point in the process, it's better to comment on the github page for that DIP than here on the forums. I'm sure your comments will be welcome there.
Re: Compile-Time Sort in D
On Tuesday, 6 June 2017 at 01:08:45 UTC, Mike Parker wrote: On Monday, 5 June 2017 at 17:54:05 UTC, Jon Degenhardt wrote: Very nice post! Thanks! If it gets half as many page views as yours did, I'll be happy. Yours is the most-viewed post on the blog -- over 1000 views more than #2 (my GC post), and 5,000 more than #3 (A New Import Idiom). Seems like this crowd-editing stuff really works!
Re: DIP 1008 Preliminary Review Round 1
On Friday, 19 May 2017 at 15:45:28 UTC, Mike Parker wrote: DIP 1008 is titled "Exceptions and @nogc". https://github.com/dlang/DIPs/blob/master/DIPs/DIP1008.md I would like the DIP to fully articulate the choice that it's facing, that special-casing the language for `throw new` comes with some downsides, but that the alternative is to force programmers to rewrite all their exceptions if they want to mark their functions `@nogc`. This requires an analysis of the similarities and differences between `throw new` and other uses of `new`. My personal impression is that exceptions do indeed fall into a distinct category, where they are easier to contain and shorter-lived than ordinary `new` memory. But the downside is that the language loses a little elegance by having another special case, and there might be corner cases where the special case is undesirable. I can only assume that at minimum, should this DIP be _rejected_, it should be replaced by some official documentation and methods on how to properly throw exceptions in `@nogc` code.
Re: DIP 1003 (Remove body as a Keyword) Accepted!
On Sunday, 4 June 2017 at 03:01:41 UTC, Walter Bright wrote: On 6/3/2017 5:20 PM, Mike Parker wrote: There's currently a proposal in the PR queue to enhance the contract syntax. https://github.com/dlang/DIPs/pull/66 I know. That's as it should be! Well that's encouraging! Thanks!
Re: Value closures (no GC allocation)
On Tuesday, 30 May 2017 at 19:29:38 UTC, deadalnix wrote: What are your thoughts? Has something similar been proposed before? https://wiki.dlang.org/DIP30 Also, while no syntax is provided, this is how SDC works internally and this is how it can handle multiple context pointers. FWIW, I think your three DIPs are elegant. Aside from questions of backward compatibility with current D, I like the way you designed functions and delegates there. Does this design integrate with the OP of this thread? It seems to. That's a question for the author of this thread too, if he reads this.
Re: DIP 1003 (Remove body as a Keyword) Accepted!
On Friday, 2 June 2017 at 14:17:10 UTC, Mike Parker wrote: Congratulations are in order for Jared Hanson. Walter and Andrei have approved his proposal to remove body as a keyword. I've added a summary of their decision to the end of the DIP for anyone who cares to read it. In short: * body temporarily becomes a contextual keyword and is deprecated * do is immediately allowed in its place * body is removed and do replaces it fully Congratulations, Jared! https://github.com/dlang/DIPs/blob/master/DIPs/DIP1003.md Yes, congratulations are in order. Although those of us who were questioning the need for any keyword at all in `body`s place may be a little disappointed that it has merely been replaced with `do`, I think no one can doubt the main thrust of the DIP, which is that `body` is an incredibly useful identifier, and that having it newly available makes D a better language. Also, I've been following the forums for several years now, and this is the first DIP that I know of that was not written by the language authors, and yet was still accepted into the language. Correct me if I'm wrong, but that seems like a real landmark! Also Mike Parker seems to be doing a very good job in his appointed position as DIP manager.
Re: DIP 1003 Formal Review
On Friday, 26 May 2017 at 01:23:59 UTC, Timon Gehr wrote: On 25.05.2017 20:57, MysticZach wrote: struct body {} interface I { int foo(int i) in { assert(i); } body bar(); } The ambiguity is fixable by modifying the parser to look ahead after `body` for `{`. Since virtual interface functions are not even allowed to have bodies, if it finds `{`, then `body` should be interpreted as a keyword, and an error issued. In all other cases `body` should be interpreted as an identifier. This is not a hard problem, but it is indeed a semantic ambiguity, so it bears mentioning. There is no ambiguity, because only one valid interpretation exists. Well the parser needs to be aware of `body` here both as a keyword and as an identifier, and to use context to determine which one it is. So to me, that counts as a semantic ambiguity, one that is resolved trivially, by a single additional token. It doesn't seem like it lives up to a more generalized fear of having contextual keywords, unless it's like guy https://www.youtube.com/watch?v=tgj3nZWtOfA
Re: DIP 1003 Formal Review
On Thursday, 25 May 2017 at 11:49:47 UTC, MysticZach wrote: ...there is no known possibility of semantic confusion between the two potential uses of `body`, I spoke too soon. I found a place where such semantic ambiguity is possible. It can only occur in interface declarations, and will not exist in any currently compilable D code, as it requires `body` to be an identifier to be legal in the first place. Currently, the only place in D where you can declare a function that has a contract, but no body, is in an interface. D syntax, it turns out, does not require a semicolon at the end of such declarations. Referencing https://dlang.org/spec/interface.html#interface-contracts we have: interface I { int foo(int i) in { assert(i); } // <-- no semicolon required void bar(); } Therefore, with `body` as an identifier, you might have this ambiguity: struct body {} interface I { int foo(int i) in { assert(i); } body bar(); } The ambiguity is fixable by modifying the parser to look ahead after `body` for `{`. Since virtual interface functions are not even allowed to have bodies, if it finds `{`, then `body` should be interpreted as a keyword, and an error issued. In all other cases `body` should be interpreted as an identifier. This is not a hard problem, but it is indeed a semantic ambiguity, so it bears mentioning.
Re: DIP 1003 Formal Review
On Friday, 12 May 2017 at 16:17:03 UTC, Mike Parker wrote: The first stage of the formal review for DIP 1003 [1], "Remove body as a Keyword", is now underway. From now until 11:59 PM ET on May 26 (3:59 AM GMT on May 27), the community has the opportunity to provide last-minute feedback. If you missed the preliminary review [2], this is your chance to provide input. At the end of the feedback period, I will submit the DIP to Walter and Andrei for their final decision. Thanks in advance to those of you who participate. [1] https://github.com/dlang/DIPs/blob/fbb797f61ac92300eda1d63202157cd2a30ba555/DIPs/DIP1003.md [2] http://forum.dlang.org/thread/qgxvrbxrvkxtimzvn...@forum.dlang.org I believe the relevant discussion for this DIP can be simplified to just these two questions: 1. Should `body` be allowed as an identifier? 2. Should the keyword `body` remain as it is? But it's been demonstrated that these two issues do _not_ need to be decided together. Because there is no known possibility of semantic confusion between the two potential uses of `body`, the arguments against allowing `body` as a contextual keyword are reduced to two minor points: A. syntax highlighters will get confused B. some programmers consider contextual keywords to be "bad karma" It's possible to answer Question 1 based on these points alone. Only if one decides that the answer to Question 2 is "no" — i.e. that `body` as a keyword needs to change — does it open up the discussion on the various options for changing it. But that could technically be the subject of a different DIP.
Re: Value closures (no GC allocation)
On Wednesday, 24 May 2017 at 20:15:37 UTC, Vittorio Romeo wrote: On Monday, 22 May 2017 at 15:17:24 UTC, Stanislav Blinov wrote: On Monday, 22 May 2017 at 14:06:54 UTC, Vittorio Romeo wrote: On Sunday, 21 May 2017 at 20:25:14 UTC, Adam D. Ruppe wrote: Blah. Well, let's go ahead and formally propose the C++ syntax, our library solutions are all fat. Are you going to create a DIP for this? I would be happy to contribute, but I don't feel confident enough to create a DIP on my own (I just started learning the language) :) The three of us could do it together through the magics of github. I've created a very WIP draft here: https://github.com/SuperV1234/DIPs/blob/master/DIPs/DIP1009.md If you're interested in contributing, please let me know and I'll add you as a collaborator. As a matter of procedure, you don't want to assign a DIP number to it yourself. I'm pretty sure that is for the DIP manager.
Re: DIP 1008 Preliminary Review Round 1
On Tuesday, 23 May 2017 at 22:40:43 UTC, Martin Nowak wrote: The proposal is a very mechanical fix, throwing several special cases at one specific problem. Why does it have to be refcounted? Seems like there is only ever one reference to the current exception (the catch variable). The only thing that seems necessary is to require scope on catch variable declarations, so that people do not escape the class reference, then this info might be used by the runtime to free exception objects after the catch handler is done. Amaury put a bit more words into that. http://forum.dlang.org/post/gtqsojgqqaorubcsn...@forum.dlang.org Has staticError been considered? It has a potential issue with multiple nested exceptions, but otherwise works fine. https://github.com/dlang/druntime/blob/bc832b18430ce1c85bf2dded07bbcfe348ff0813/src/core/exception.d#L683 I'm trying to understand your and Amaury's point. Normally, when you say `new` you get memory from the GC allocator. The @nogc attribute is supposed to prevent this, if I understand it correctly. Are you saying that `@nogc` as such is misconceived, because what a good language feature should really be doing is identifying and preventing new memory that _can't_ be deterministically destroyed? Is the problem here with the @nogc attribute? Because I think Walter's goal with this DIP is to make it so that you can put @nogc on _called_ functions that throw using `new`. Whereas your solution is to ignore that `new Exception` allocation, on account of the fact that you can deterministically destroy the Exception, provided you use `scope` catch blocks at, or above, the call site. Your solution might actually have its priorities straight, and `@nogc` may be designed badly because it clumps all GC allocations into one big basket. However, getting new memory from the GC still could trigger a collection cycle, which is what @nogc was created for, and simply knowing that you can reliably destroy the allocated memory doesn't change that. Thus, if I understand correctly, you and Amaury are arguing that `@nogc` as currently designed is a false goal to be chasing, that the more important goal is memory that can be deterministically destroyed, and therefore it distresses you that the language may be altered to chase the false prize of `@nogc` everywhere, instead of focusing on a real prize worth attaining?
Re: new contract syntax DIP
On Tuesday, 23 May 2017 at 19:04:46 UTC, arturg wrote: how about @uda based contracts? @in(x => x < 100) @out((ret) { assert(ret > 0, "some text"); }) int fun(int i) { return someVal; } they could also be used on type definitions, @out((t) { assert(t); }) class NotNull {} or temporarly on instances @in(t => t !is null) auto notNull = new NotNull; you could also have @inout as a combination. another feature would be that they could be introspected. Well I was going for three things: 1. contracts simple to write, with minimal "extra plumbing", i.e. without brackets and parentheses 2. utilize existing contract infrastructure 3. minimal divergence from existing syntax and semantics. While not having to write `assert` in contracts would save a little space, it reduces what you can do with them, and also introduces a whole new semantics. The @uda contract system you suggest would require extensive description, documentation, and probably implementation effort. It would have to demonstrate that there was no better way to solve the problems it solves. (I'm not even sure I can justify my little syntax change, let alone a whole new semantics. I don't even know if contracts in general are important enough to be worth improving their syntax.) So yeah, one could do things differently. But just because you _can_ do things differently doesn't mean you should. And justifying _why_ you should is not easy. And if people are being reasonable, they should maintain very high standards for what goes into a general-purpose programming language. Because there are a lot of things you can't take back once they're in there. (On the other hand, you don't want to stagnate, and not change _anything_, just for fear of making a mistake. One should strive for a balance.)
Re: DIP 1003 Formal Review
On Wednesday, 17 May 2017 at 01:01:29 UTC, MysticZach wrote: I think there are several issues at hand, and they need to be dealt with individually: 1. `body` is a very useful identifier. It would be nice to have it available. 2. Contract syntax is too verbose. 3. a. Some people think code looks better with a keyword, e.g. `body`, `do`, etc. distinguishing the function from the contracts. 3. b. Other people think that such a keyword is unnecessarily redundant and does not justify its own existence. I think the thread will be more productive if the posters commit to answering just one of these issues, and reserve other issues for other threads. As the DIP in question is directly meant to address issue #1, it makes sense to try to solve that problem and only that problem here. I made a related DIP discussing issue 2, contract syntax is too verbose. The thread for discussing that one is here: http://forum.dlang.org/post/tuzdqqpcoguatepgx...@forum.dlang.org
new contract syntax DIP
I made a pull request for a new DIP dealing with contract syntax: https://github.com/dlang/DIPs/pull/66 I write the DIP in response to the discussions for DIP 1003: http://forum.dlang.org/thread/wcqebjzdjxldeywlx...@forum.dlang.org This DIP is not under any kind of formal review yet. I just wanted to let people know that it's there.
Re: DMD now has colorized syntax highlighting in error messages
On Thursday, 18 May 2017 at 01:52:17 UTC, Adam D. Ruppe wrote: On Tuesday, 16 May 2017 at 14:17:41 UTC, Adam D. Ruppe wrote: Similarly, what I want to see in the future is highlighting of specific parts of code where the error applies. Fear me. I combined Walter's code with my own to form some kind of Voltron! https://github.com/dlang/dmd/pull/6806 I think the compiler's error design could use a complete overhaul. I'm wondering if it wouldn't be wise to start a new git branch for all changes to error messages. Call it `stderr.experimental` or something cute like that. The idea is that D won't break people's test code that checks error output until a more complete design has been worked out and approved of. I'm not in favor of or against this idea. I just wanted to propose it.
Re: DIP 1003 Formal Review
On Thursday, 18 May 2017 at 13:06:38 UTC, Petar Kirov [ZombineDev] wrote: On Thursday, 18 May 2017 at 12:56:31 UTC, Meta wrote: This is pretty much the same as option 2. The short-term contextual part is covered by Walter's suggestion. No it's not. What MysticZach suggests, and what I suggested even earlier [0] is to make 'body' contextual and optional which is very different than replacing it with another keyword. The main difference is that it would make code that uses contracts cleaner and there would be no breakage. In contrast, deprecating 'body' is a breaking change. IMO, option 2 and variations of it are *the worst* way forward. [0]: http://forum.dlang.org/post/pmldhzgcpuoydllfr...@forum.dlang.org Yes. Our proposal is actually a variation on option 3. Added to the current DIP, it would read: "Option 6: allow omitting `body`, and also allow it as an identifier" The two known downsides to this option so far are: 1. Different code will continue include the keyword version of `body` or not based on arbitrary programmer preferences. 2. Syntax highlighters that choose to highlight the word `body` will have to be modified to detect its different uses. Note that in the case of 1., strong preferences have been stated here for both styles, thus increasing the feeling that it's okay to allow both. Also note that the opposition to any inclusion of contextual keywords on principle is largely countered by the fact that there is no danger of semantic ambiguity between the two uses of `body` here.
Re: Weak Eco System?
On Thursday, 18 May 2017 at 05:43:48 UTC, Manu wrote: On 17 May 2017 at 00:51, Benro via Digitalmars-d < digitalmars-d@puremagic.com> wrote: [...] 4 Hours work. Discouraged and gave up after this. Visual Studio proper is the only IDE that 'just works' well, VisualD is very good. MonoDevelop also has good 'just works' support last I checked, but debugging is much better in Visual Studio. I think the lack of clear signals about what works and what doesn't in the most easily reached places on the website, forums, wiki, etc. is probably as big a problem as is any of those things not working in the first place...?
Re: DIP 1003 Formal Review
On Thursday, 18 May 2017 at 03:59:49 UTC, MysticZach wrote: http://forum.dlang.org/post/kybywnscisxpebezw...@forum.dlang.org ) represents yet another distinct option. i.e. continue to allow `body`, but make it optional, that is, you can simply omit it if you want, while also allowing it as an identifier. For the record, this was first suggested by H. S. Teoh: http://forum.dlang.org/post/mailman.2204.1494612727.31550.digitalmar...@puremagic.com
Re: DIP 1003 Formal Review
On Thursday, 18 May 2017 at 02:13:52 UTC, Meta wrote: On Wednesday, 17 May 2017 at 11:46:07 UTC, Meta wrote: I'll add this option to the DIP. https://github.com/dlang/DIPs/pull/65 I think ( http://forum.dlang.org/post/kybywnscisxpebezw...@forum.dlang.org ) represents yet another distinct option. i.e. continue to allow `body`, but make it optional, that is, you can simply omit it if you want, while also allowing it as an identifier.
Re: DIP 1003 Formal Review
On Wednesday, 17 May 2017 at 09:57:41 UTC, Basile B. wrote: On Wednesday, 17 May 2017 at 09:53:49 UTC, MysticZach wrote: Option 4) Keep `body`, but make it both contextual *and* optional. It becomes usable as an identifier, and those who think it's unnecessary are appeased. The downside is that different programmers will include it or not, based on arbitrary preferences. The problem with this option is the IDEs. D syntax so far doesn't require parsing to highlight, i.e you have a token and you know what is it directly, and this without looking at the previous tokens (which is basically what parsing does, detect token patterns). I don't feel like it's much of a problem: 1. I suspect a simple matching of the three tokens '}', 'body', '{' would detect it most of the time. 2. Without that, remove `body` from your highlighter's list of keywords. When used as a keyword, it's very conspicuous anyway. Code won't lose much readability with just this one word unlit. 3. If `body` were optional, probably a lot of people wouldn't be using it to begin with. I suspect that Jonathan and I are not alone in thinking that it's not just useless, it's annoying. Thus, only code that uses it would have this problem.
Re: DIP 1003 Formal Review
On Wednesday, 17 May 2017 at 08:03:13 UTC, Mike Parker wrote: * Is it a good idea to remove body's status as a reserved keyword? * If so, which option is best? 1) Make it contextual 2) Replace it with another keyword (`function` was suggested in the DIP, `do` in this thread). 3) A three-stage process of removal: make it optional, then deprecate it, then remove it completely (meaning, no keyword, reserved or contextual, is required for the function body in a contract). Option 4) Keep `body`, but make it both contextual *and* optional. It becomes usable as an identifier, and those who think it's unnecessary are appeased. The downside is that different programmers will include it or not, based on arbitrary preferences.
Re: DIP 1003 Formal Review
On Tuesday, 16 May 2017 at 18:57:37 UTC, H. S. Teoh wrote: To me, it's actually worse, because now you have a visual conflation with do-loops. Overall, what I don't like about contract syntax is that it is so unbearably verbose. It's not just the in and out blocks and the (IMO redundant) marking of the function body; it's also the repeated 'assert's that occur in the in and out blocks. int foo(T, U)(T t, U u) if (sigContraints!T && sigConstraints!U) in { assert(t > 0 && u < 10); } out(val) { assert(val > 1 && val < 5); } body { // function body here } I understand this DIP is only to address the `body` part of this ugly verbosity, but imagine how much better it would be if we could write something like this instead: int foo(T, U)(T t, U u) if (sigConstraints!T && sigConstraints!U) in (t > 0 && u < 10) out(foo > 1 && foo < 5 ) { // function body here } This is just tentative example syntax, of course. We can argue over its fine points later, but the point is that the current syntax is far too verbose, and can easily be reduced to half the number of lines. Merely changing `body` to `do` does nothing to address this, and seems to me to be just more useless churn, replacing one bit of verbosity with another bit of verbosity. (Not to mention the IMO very ugly syntax clash with do-loops, which will reduce code readability even more.) T I think there are several issues at hand, and they need to be dealt with individually: 1. `body` is a very useful identifier. It would be nice to have it available. 2. Contract syntax is too verbose. 3. a. Some people think code looks better with a keyword, e.g. `body`, `do`, etc. distinguishing the function from the contracts. 3. b. Other people think that such a keyword is unnecessarily redundant and does not justify its own existence. I think the thread will be more productive if the posters commit to answering just one of these issues, and reserve other issues for other threads. As the DIP in question is directly meant to address issue #1, it makes sense to try to solve that problem and only that problem here.
Re: DIP 1003 Formal Review
On Tuesday, 16 May 2017 at 17:42:11 UTC, MysticZach wrote: On Tuesday, 16 May 2017 at 15:22:12 UTC, Timon Gehr wrote: auto foo()in{ assert(true); }out{ assert(true); }{ return 3; } Are you really arguing for this? I don't want to write code like this. It's not any better than this: I meant any worse.
Re: DIP 1003 Formal Review
On Tuesday, 16 May 2017 at 15:22:12 UTC, Timon Gehr wrote: auto foo()in{ assert(true); }out{ assert(true); }{ return 3; } Are you really arguing for this? I don't want to write code like this. It's not any better than this: auto foo()in{ assert(true); }out{ assert(true); }body{ return 3; } They are both bad, but not because of the presence or absence of the `body` keyword, in my opinion.
Re: DIP 1003 Formal Review
On Tuesday, 16 May 2017 at 13:50:59 UTC, Jonathan M Davis wrote: All I'm arguing for is that if we're removing body as a keyword, there's no need to replace it with function or any other word in contracts. We can simply deprecate its use as a keyword and not replace it, letting it then be used as a normal identifier in whatever fashion makes the most sense. +1, Makes total sense to me. So simple. I'm for this. Actually changing the overall syntax of contracts is a whole other can of worms. Yeah. One thing at a time.
Re: DIP 1003 Formal Review
On Tuesday, 16 May 2017 at 03:44:54 UTC, MysticZach wrote: It seems to me that the compiler could detect a presence or lack of a body simply by the presence or absence of any statement after the contracts, i.e., interface D { // fun is implicitly overridable here int fun() { in assert(...); } } Also, does a final function with contracts, but no body, make any sense? What's the use case? Even if there were some use case for it, I can think of two solutions. One is to keep and require the current syntax for an interface function without a body. This is the natural way to install contracts anyway, for a function with no body. The other solution is to recommend the addition of an empty statement, for an empty final function, e.g.: // final int fun() { in assert(...); {} } Considering what Jonathan said about how he never uses contracts because they're so bulky, might it not be worth it to solve the interface problem in either of the above two ways? I should have said *three* ways, because it's quite possible to conclude that there will never be a use case for a final function in an interface to have contracts, but no body, and therefore assume that contracts plus a lack of statements --> an overridable function.
Re: On the subject of error messages
On Saturday, 13 May 2017 at 14:41:50 UTC, Stanislav Blinov wrote: file(line): Error: template foo cannot deduce function from argument types !()(int, string), candidates are: file(line): foo(Args...)(auto ref Args arg) if (!anySatisfy!(isString, Args)) Ya know, even a simple new line before "candidates are:" would improve this error message! https://issues.dlang.org/show_bug.cgi?id=17400 I know it seems trivial, but attention to detail does make a difference, so I decided to make an issue for it anyway... :-/
Re: DIP 1003 Formal Review
On Monday, 15 May 2017 at 02:02:42 UTC, Basile B. wrote: On Monday, 15 May 2017 at 01:39:34 UTC, MysticZach wrote: Not that a whole new way of doing things is called for... but I think a better design would have been to allow 'in' and 'out' statements in the function itself, with no need for brackets if you only have one line's worth of contract, e.g., int fun(int a) { in assert(...); out(x) assert(...); // do stuff } It's nice, i like it but it cant work as simply. You're forgetting that interface member functions can have contracts. With this syntax interfaces member functions would always have a body BUT the current semantic is that interface member functions with bodies are final methods. Boom. Interfaces don't work anymore because there's no easy way to make the difference between an interface member function that's final and an interface member function that's not pre-implemented (so overridable) but has contracts. It seems to me that the compiler could detect a presence or lack of a body simply by the presence or absence of any statement after the contracts, i.e., interface D { // fun is implicitly overridable here int fun() { in assert(...); } } Also, does a final function with contracts, but no body, make any sense? What's the use case? Even if there were some use case for it, I can think of two solutions. One is to keep and require the current syntax for an interface function without a body. This is the natural way to install contracts anyway, for a function with no body. The other solution is to recommend the addition of an empty statement, for an empty final function, e.g.: // final int fun() { in assert(...); {} } Considering what Jonathan said about how he never uses contracts because they're so bulky, might it not be worth it to solve the interface problem in either of the above two ways?
Re: DIP 1003 Formal Review
On Monday, 15 May 2017 at 01:39:34 UTC, MysticZach wrote: Not that a whole new way of doing things is called for... but I think a better design would have been to allow 'in' and 'out' statements in the function itself, with no need for brackets if you only have one line's worth of contract, e.g., int fun(int a) { in assert(...); out(x) assert(...); // do stuff } You could even accumulate in statement if you want to save on brackets and indentation: int fun() { in assert(...); in assert2(...); // etc. }
Re: DIP 1003 Formal Review
On Monday, 15 May 2017 at 01:18:02 UTC, Jonathan M Davis wrote: Why would we want to introduce function as an alternative to body? Personally, I've always found the need to use body to be very odd and annoying. It doesn't need to be there when you don't have in or out contracts, and it just makes contracts that much more verbose. It's not even like you can put in our out contracts after the function body, so body is needed to indicate which block the function body is - the contracts have to go first. So, as far as I can tell, body serves no useful function. It just makes the code longer, and the amount of extra code required around in/out contracts is part of why I almost never use them. In most cases, it just makes more sense to put the assertions in the function body and not have all of that extra plumbing right after the function signature. Not that a whole new way of doing things is called for... but I think a better design would have been to allow 'in' and 'out' statements in the function itself, with no need for brackets if you only have one line's worth of contract, e.g., int fun(int a) { in assert(...); out(x) assert(...); // do stuff }
Re: DMD now has colorized syntax highlighting in error messages
On Sunday, 14 May 2017 at 16:25:36 UTC, Walter Bright wrote: On 5/14/2017 9:04 AM, Andre Pany wrote: Thanks a lot. In my opinion these kind of changes are small but have huge impact on the acceptance of a language. I agree. A couple other improvements needed for error messages: In the PR you say that someone with a better color sense ought to choose the default colors. I don't have such a sense myself. But I recognize that as a real task for which help should be sought. Maybe this thread is a good place to get a volunteer?
Re: DConf 2017 Day 3 Livestream
On Saturday, 6 May 2017 at 22:12:10 UTC, Joshua Niehus wrote: On Saturday, 6 May 2017 at 08:03:11 UTC, Mike Parker wrote: https://www.youtube.com/watch?v=XTtruC3D2Ag Is anyone else having issues viewing the livestream? It's over. The video has already been take down. They will chop it into individual lectures and repost them on Monday or thereabouts, I think.
Re: [OT] Algorithm question
On Thursday, 4 May 2017 at 13:19:43 UTC, MysticZach wrote: On Thursday, 4 May 2017 at 08:04:22 UTC, Timon Gehr wrote: On 03.05.2017 01:09, MysticZach wrote: That's true. Two points, though: If the range of error is within 1/(n*(n-1)), with array length n, It's not though. For example, [1,1,1,0,...,0] (length 29), you get 0 and 2 each with probability 43/116, but 1 only with probability 30/116. It might be interesting to figure out how far from uniform the distribution can get. Or how close it can get, depending on the range of intervals used. My math skill is shaky here. Maybe there's no way to deterministically jump to every element of an array with equal probability of hitting any given element satisfying a given predicate first. It sure would be cool if there were. Within a small range of error, I mean.
Re: [OT] Algorithm question
On Thursday, 4 May 2017 at 08:04:22 UTC, Timon Gehr wrote: On 03.05.2017 01:09, MysticZach wrote: Counterexample: [1,1,1,0,0] Your algorithm returns 0 with probability 7/20, 1 with probability 6/20 and 2 with probability 7/20. Note that there is a simple reason why your algorithm cannot work for this case: it picks one of 20 numbers at random. The resulting probability mass cannot be evenly distributed among the three elements, because 20 is not divisible by 3. That's true. Two points, though: If the range of error is within 1/(n*(n-1)), with array length n, It's not though. For example, [1,1,1,0,...,0] (length 29), you get 0 and 2 each with probability 43/116, but 1 only with probability 30/116. It might be interesting to figure out how far from uniform the distribution can get. Or how close it can get, depending on the range of intervals used. My math skill is shaky here. Maybe there's no way to deterministically jump to every element of an array with equal probability of hitting any given element satisfying a given predicate first. It sure would be cool if there were.
Re: [OT] Algorithm question
On Tuesday, 2 May 2017 at 23:09:54 UTC, MysticZach wrote: On Tuesday, 2 May 2017 at 21:00:36 UTC, Timon Gehr wrote: On 02.05.2017 22:42, MysticZach wrote: On Tuesday, 2 May 2017 at 13:44:03 UTC, MysticZach wrote: for (;;) { if (P(a[i])) return i; ++count; if (count == length) return -1; i += hop; if (i < length) continue; if (i < skipLength) i += hop; (I guess this should be 'while'.) skipLength is determined modulo hop, thus it can't be more than one hop away. Actually, I did botch the implementation. The hopping interval must be based on the prime rather than on n. But you could still short circuit the while loop, I think. `if (prime - n > hop) { skipLength = n + ((prime - n) % hop); }
Re: [OT] Algorithm question
On Tuesday, 2 May 2017 at 21:00:36 UTC, Timon Gehr wrote: On 02.05.2017 22:42, MysticZach wrote: On Tuesday, 2 May 2017 at 13:44:03 UTC, MysticZach wrote: for (;;) { if (P(a[i])) return i; ++count; if (count == length) return -1; i += hop; if (i < length) continue; if (i < skipLength) i += hop; (I guess this should be 'while'.) skipLength is determined modulo hop, thus it can't be more than one hop away. Counterexample: [1,1,1,0,0] Your algorithm returns 0 with probability 7/20, 1 with probability 6/20 and 2 with probability 7/20. Note that there is a simple reason why your algorithm cannot work for this case: it picks one of 20 numbers at random. The resulting probability mass cannot be evenly distributed among the three elements, because 20 is not divisible by 3. That's true. Two points, though: If the range of error is within 1/(n*(n-1)), with array length n, it may be close enough for a given real world use case. 2. n is known to be large, which makes 1/(n*(n-1)) even smaller. You'd probably have to trade accuracy for performance. I wonder how much less performant a truly accurate algorithm would be. Also, whether there's a way to make an algorithm of this style completely accurate.
Re: [OT] Algorithm question
On Tuesday, 2 May 2017 at 13:44:03 UTC, MysticZach wrote: 1. Test a random element in the array. If it satisfies P, return it. 2. Choose a hopper interval, h, that is relatively prime to the number of elements in the array, n. You could do this by randomly selecting from a pre-made list of primes of various orders of magnitude larger than n, with h = the prime % n. 3. Hop along the array, testing each element as you go. Increment a counter. If you reach the end of the array, cycle back to the beginning starting with the remainder of h that you didn't use. I think that h being relatively prime means it will thereby hit every element in the array. 4. Return the first hit. If the counter reaches n, return failure. Taking this a step further, it occurred to me that you could use *any* hopping interval from 1 to array.length, if the length of the array were prime. So artificially extend the array and just skip a jump when you land in the extended area. And since you'd skip lots of jumps if the extension were any bigger that the hopping interval, reduce its length to modulo the hopping interval. // returns a random index of array satisfying P(x), -1 if not found int randomlySatisfy(A[] array) { auto length = array.length; if (!length) return -1; auto i = uniform(0, length); auto hop = uniform(1, length); // greatest prime < 2^^31, for simplicity enum prime = 2147483477; assert (length <= prime); auto skipLength = ((prime - length) % hop) + length; auto count = 0; for (;;) { if (P(a[i])) return i; ++count; if (count == length) return -1; i += hop; if (i < length) continue; if (i < skipLength) i += hop; i -= skipLength; } return -1; } This solution is stupidly simple and I haven't tested it. But I believe it's truly random, since the hopping interval is arbitrary. Who knows, it might work.
Re: [OT] Algorithm question
On Tuesday, 2 May 2017 at 11:27:17 UTC, Ivan Kazmenko wrote: On Tuesday, 2 May 2017 at 10:35:46 UTC, Ivan Kazmenko wrote: I hope some part of the idea is still salvageable. For example, what if we put the intervals in a queue instead of a stack? I tried to implement a similar approach, but instead of a queue or a stack, I used a random-access array of intervals. Sadly, it is still far from uniform, since it does not take interval lengths into account, and I don't see how to do that without at least O(log n) time per interval insertion or deletion. Implementation and empiric frequencies for n=5 elements in a permutation: http://ideone.com/3zSxLN Ivan Kazmenko. Well, I thought of another idea that may not be technically random, but which I imagine would get pretty close in real world use cases: 1. Test a random element in the array. If it satisfies P, return it. 2. Choose a hopper interval, h, that is relatively prime to the number of elements in the array, n. You could do this by randomly selecting from a pre-made list of primes of various orders of magnitude larger than n, with h = the prime % n. 3. Hop along the array, testing each element as you go. Increment a counter. If you reach the end of the array, cycle back to the beginning starting with the remainder of h that you didn't use. I think that h being relatively prime means it will thereby hit every element in the array. 4. Return the first hit. If the counter reaches n, return failure. The way I see it, with a random start position, and a *mostly* random interval, the only way to defeat the randomness of the result would be if the elements that satisfy P were dispersed precisely according to the random interval specified for that particular evocation of the function — in which case the first in the dispersed set would be chosen more often. This would require a rare convergence depending on both n and h, and would not repeat from one call to the next.
Re: [OT] Algorithm question
On Monday, 1 May 2017 at 16:56:58 UTC, MysticZach wrote: The goal is to have the first hit be the one you return. The method: if a random pick doesn't satisfy, randomly choose the partition greater than or less than based on uniform(0..array.length-1), and do the same procedure on that partition, reusing the random index to avoid having to call uniform twice on each recursion (one to choose a partition and one to choose an index within that partition). If the probability of choosing a partition is precisely proportional to the number of elements in that partition, it seems to me that the result will be truly random, but I'm not sure. Now I'm questioning this, because if the positive cases are unevenly distributed, i.e., [11000100], the last one has about 50% chance to get picked instead of a 1 in 7 chance with my method. I guess you'd need to build a whole new array like the others are saying.
Re: [OT] Algorithm question
On Monday, 1 May 2017 at 16:56:58 UTC, MysticZach wrote: // choose a random partition proportionally auto j = uniform(da.length - 1); if (j < i) { // the lower partition int a = randomlySatisfyImpl(da[0..i], j); if (a != -1) return a; else return randomlySatisfyImpl(da[i+1 .. da.length], j - (i + 1)); } else { // higher partition, investigate in reverse order int a = randomlySatisfyImpl(da[i+1 .. da.length], j - (i + 1)); if (a != -1) return i +1 + a; else return i + 1 + randomlySatisfyImpl(da[0..i], j); The line above has a bug. Replace it with: else { a = randomlySatisfyImpl(da[0..i], j); return (a == -1) ? -1 : i + 1 + a; } } } But the idea's the same. Hopefully it's clear.
Re: [OT] Algorithm question
On Monday, 1 May 2017 at 04:15:35 UTC, H. S. Teoh wrote: Given a set A of n elements (let's say it's a random-access range of size n, where n is relatively large), and a predicate P(x) that specifies some subset of A of elements that we're interested in, what's the best algorithm (in terms of big-O time complexity) for selecting a random element x satisfying P(x), such that elements that satisfy P(x) have equal probability of being chosen? (Elements that do not satisfy P(x) are disregarded.) Here's how I would do it: // returns a random index of array satisfying P(x), -1 if not found int randomlySatisfy(A[] array) { if (array.length == 0) return -1; int i = uniform(0, array.length); return randomlySatisfyImpl(array, i); } // recursive function private int randomlySatisfyImpl(A[] da, int i) { if (P(da[i])) return i; if (da.length == 1) return -1; // choose a random partition proportionally auto j = uniform(da.length - 1); if (j < i) { // the lower partition int a = randomlySatisfyImpl(da[0..i], j); if (a != -1) return a; else return randomlySatisfyImpl(da[i+1 .. da.length], j - (i + 1)); } else { // higher partition, investigate in reverse order int a = randomlySatisfyImpl(da[i+1 .. da.length], j - (i + 1)); if (a != -1) return i +1 + a; else return i + 1 + randomlySatisfyImpl(da[0..i], j); } } The goal is to have the first hit be the one you return. The method: if a random pick doesn't satisfy, randomly choose the partition greater than or less than based on uniform(0..array.length-1), and do the same procedure on that partition, reusing the random index to avoid having to call uniform twice on each recursion (one to choose a partition and one to choose an index within that partition). If the probability of choosing a partition is precisely proportional to the number of elements in that partition, it seems to me that the result will be truly random, but I'm not sure.
Re: Proposal 2: Exceptions and @nogc
On Sunday, 9 April 2017 at 20:14:24 UTC, Walter Bright wrote: ... a general mechanism for safe refcounting of classes has eluded us. Regardless of my other comments, which are maybe a little uninformed, DIP74 seems pretty good: https://wiki.dlang.org/DIP74 Manu started a thread asking about it, but that thread dissolved into a bitter dispute: http://forum.dlang.org/post/mailman.1002.1444519548.22025.digitalmar...@puremagic.com The only valuable information regarding the question was in this post of Andrei's, which did not say very much: http://forum.dlang.org/post/mvgoa9$1gda$1...@digitalmars.com So what are the corner cases of DIP74? What are the actual problems with it?
Re: Proposal 2: Exceptions and @nogc
On Wednesday, 12 April 2017 at 19:01:25 UTC, Walter Bright wrote: On 4/11/2017 10:24 AM, MysticZach wrote: Hi guys. Hey Walter. So, about this point. On the lifetime study thread, http://forum.dlang.org/post/56301a8c.1060...@erdani.com , the following two problems were stated by Andrei, but I don't think they were adequately addressed in the subsequent posts: The way they will be addressed is to increment the reference count in the call to the function that takes a reference to an RC object. Makes sense, and I thought the same thing until after I wrote my post — but now I realize it's not quite good enough. Merely incrementing the refcount (and decrementing it afterwards) has the following problem: @rc class RC; void fun(ref RC a, RC b) { a = new RC; // (1) // b... } void main() { auto r = new RC; // (2) --> r.opInc(); // compiler insert fun(r, r); --> r.opDec(); } Let's assume the reference counting scheme involves the methods opInc and opDec, inserted automatically by the compiler as the result of detecting a duplicate parameter. If you read closely, you'll realize that at mark 1 above, the program will leak the data acquired at mark 2. The assign statement of the refcounted object will decrement the data it points to before it is reassigned. But since the data at (2)'s refcount was prematurely incremented, it will fall to 1 and never get deleted. Furthermore, the opDec in main() will decrement and delete the data acquired at mark 1, thinking it was the mark 2 data. The problem is that the calling context at "fun(r,r);" fails to keep a real reference to the mark 2 data. If one of the parameters is sent by reference, we can't assume it points to the same data upon returning as when it was sent. And the mark 2 data can't be deleted before fun() returns, or it will invalidate 'b' in fun(). This suggests we need to save a real, separate reference to 'r' before sending two or more versions of it. That said, I believe the following compiler inserts in main() would do the trick: void main() { auto r = new RC; // (2) --> RC __rsave = r; // compiler insert --> scope(exit) __rsave = null; fun(r, r); } This solution uses only the assign method of RC to inc and dec the refcount, suggesting that opInc and opDec are ultimately unnecessary, except as (very rare) optimizations. But you still need for the compiler to distinguish a refcounted class from a regular one, so maybe the presence of an opDec() could indicate that, opDec being the quasi-destroyer that turns a refcounted class variable into an RAII type. Otherwise, you might need something like an @rc attribute. At any rate, your original claim was, "a general mechanism for safe refcounting of classes has eluded us." Is this still the case, considering the above? As far as the original post, even if a general mechanism were found, it doesn't mean you'd have to use it in the case of Exception anyway. To generalize the expression 'throw new ...', you'd have to redefine 'new' to be different with refcounted classes than with regular ones. Exceptions are probably worth a more specialized solution like the one you proposed. Otherwise everyone will have to change their 'throw new' code to accommodate '@nogc'. Adam D. Ruppe gave us his solution here: http://arsdnet.net/exception.d tl;dr Everyone would now have to say things like 'throw emplace!...' or 'raise!"my_exception"(...)'. I guess the proposed hack of 'throw new Exception' is simply the shadow of D's original philosophy of wanting the GC to do too much.
Re: Proposal 2: Exceptions and @nogc
On Sunday, 9 April 2017 at 20:14:24 UTC, Walter Bright wrote: On 4/9/2017 1:16 AM, Daniel N wrote: ... but why not go all the way, making it "always" refcounted? (for any "new E", not emplace). Backwards compatibility, for one. For another, a general mechanism for safe refcounting of classes has eluded us. Hi guys. Hey Walter. So, about this point. On the lifetime study thread, http://forum.dlang.org/post/56301a8c.1060...@erdani.com , the following two problems were stated by Andrei, but I don't think they were adequately addressed in the subsequent posts: === Widget global; @rc class Widget { int x; void fun() { global = null; ++x; } } void main() { global = new Widget; global.fun(); } In this example, if global has a refcount==1 upon entering fun(), the assignment "global = null" deletes the Widget object and ++x accesses dangling memory. I should add here another pattern that turned problematic for our older attempts in DIP74: C c = new C(); foo(c); int foo(scope C d) { c = new C();// c's old instance gets deleted return d.i;// oops! d is invalid } === So here's my analysis of both these problems. When calling a function, the reference count for an object must increase by the total number of aliases created by the call — *minus the ones lost*. Globals are special in this regard, because access to them is not lost in the called function. Local variables, however, are lost to the called function — they cannot be accessed except through the new alias they receive as a parameter. Thus, only globals must modify the reference count when passed. Thinking about this is made easier if we turn all accessible aliases into function parameters. For this, we need to consider the set of globals as a hidden parameter to the function. Any global is therefore already passed to all functions. If we pass it again via parameter, that amounts to two aliases, thus two references. The same logic applies, 1. to duplicating any given variable in the argument list, e.g. "fun(c, c);", 2. to duplicating the hidden 'this' parameter, 3. to recognizing and outer function's stack frame as an additional alias. All these can be verified at compile time. Also, it is optimistic regarding the most common case, i.e. passing a local does not require increasing the reference count. --Zach