Hi all,

I had an out-of-the-blue thought about this topic and thought I'd share. 
Two things:

1) Using _ for the undefined value, because that's already used for 
tuple assignment to mean the same thing and makes using it less wordy. 
refs or ins passed passed as _ will of course have space allocated for 
the call so it can be referenced/assigned in the function, but will be 
discarded when the stack is unwound. This may be a little hacky, but 
maybe the syntax "x == _" could be used to check if something is 
ignored. That construction is not valid anywhere right now, so I don't 
think there's any risk of ambiguity. It just might not be immediately 
clear, since its semantics are not really like == in the sense of 
checking a value.

2) Some kind of keyword to mean "the space in which the return value 
goes" that can be used as an l-value. In the callee, this would sort of 
feel like an inout passing of the assignment L-value from the caller 
scope. If it has a value already, the callee can even check what it is 
and modify it. Otherwise it will be the default value. If the return 
value is not assigned anywhere in the caller, in the callee it will be 
treated just like a _ passed in as above. I would like to suggest 
"return" to be that keyword, though very tentatively, because it should 
still be usable alone as a statement which exits the function. But 
there's a whole lot to consider when doing that, not least of which is 
diverging from every other language's use of the return keyword, so it's 
very iffy. Alternatively to that or a keyword, there can be some kind of 
syntax like "proc f():int as x { ... }" or "proc f():(x:int) { ... }", 
and then x will be that return value holder in the function scope. This 
might be clearer, though slightly more verbose.

Here's an example to illustrate what I'm proposing:

> proc f():int {
>   if return == _ then writeln("empty");
>   return += 2;
> }
> var x = 1, y = 6;
> x = f();  // x is now 3
> y = f();  // y is now 8
> var z = f();  // z is 2, since int's default value is 0.
> f();  // This will cause "empty" to be written, but still evaluates as 2
> f() + x;  // This evaluates to 5, but should it print "empty"?

These changes would make certain patterns more elegant to implement, 
though they also raise some issues. The last line in the example 
demonstrates some weirdness when used in expressions: from the callee's 
point of view, the return value is used to be added to x, however the 
value is not ultimately stored anywhere in the caller. Another issue(?) 
is that it follows pretty naturally that returns are no longer 
compulsory. I think it's fairly intuitive to just make that mean "return 
the default value", though. Anyway, just some thoughts I had. Let me 
know what you guys think.

-- Brandon

On 12/11/2013 12:40 PM, Brad Chamberlain wrote:
> Code size is a reasonable concern.  We can reconsider if/when it becomes
> an issue, but let's start there for now since you're open to it.
>
> -Brad
>
>
> On Wed, 11 Dec 2013, Michael Ferguson wrote:
>
>> Hi -
>>
>> Ok, thanks for clarifying. I'm on board with this solution to 1 and 2 (adding
>> also
>> the symmetric "return value used"). For 3, compile time vs. run time - I'm a
>> little
>> bit worried about code size, but am OK with it being compile time.
>>
>> Cheers,
>>
>> -michael
>>
>>
>> On 12/11/2013 11:45 AM, Brad Chamberlain wrote:
>>> I think what we agreed upon ("we" being me and Chris primarily, though in
>>> side conversations others have aquiesced as well) was an option D:
>>>
>>> 1) The presence of a default value for an argument marks it as optional
>>>      (this is what we already have today);
>>>
>>> 2) Some sort of built-in .defaultValueUsed method or procedure would be
>>>      used to determine whether the optional value was specified.  A function
>>>      would be almost trivial to implement but would clutter the namespace; a
>>>      method would be slightly harder to implement, but not too much
>>>      presumably.  I'm not tied to this specific name at all.
>>>
>>> 3) I view this as a compile-time (param) procedure since it's knowledge
>>>      that's known at compile-time and could be useful for folding away
>>>      unused code paths.
>>>
>>> I think the main possible objection to this approach is that we've
>>> essentially said that for a case like:
>>>
>>>       proc foo(ref x: int = 1000) { ... }
>>>
>>> there's some sleight of hand going on in that '1000' is not a legal lvalue
>>> so technically shouldn't be able to be "passed" to x by reference.  One
>>> interpretation here (as with 'inout' and 'out' intents currently) is that a
>>> temporary variable would be inserted to hold the default value and that is
>>> what would be "passed" by reference into the procedure.  An alternate
>>> interpretation would be that since the 1000 is only used when an 'x' was
>>> not supplied at the callsite, the 'ref' semantics are somewhat moot. I.e.,
>>> we may as well simply consider 'x' to have intent 'in' in this case (since
>>> there's nothing to refer back to) in which case 'x' is itself the temporary
>>> variable and it gets the value 1000 (this may also provide an
>>> optimization/specialization opportunity at compile-time since 'x' can be
>>> referred to more cheaply when the callsite doesn't supply one).
>>>
>>> While this feels, arguably, a little fiddly/sloppy, I think the consensus
>>> (again, of a small sample size) is that the utility, convenience, and lack
>>> of alternate reasonable interpretation for such a case makes it acceptable
>>> (combined with the corresponding syntactic baggage we expect for any other
>>> solution -- or maybe just the lack of one that feels sufficiently
>>> compelling and attractive?).
>>>
>>> -Brad
>>>
>>>
>>>
>>> On Wed, 11 Dec 2013, Michael Ferguson wrote:
>>>
>>>> Hi -
>>>>
>>>> Summarizing, and then questions.
>>>> - Chris proposed adding an 'undefined' value to check to see if an
>>>>   optional argument was provided
>>>> - Brad proposed allowing something like x.defaultValueUsed
>>>> - Chris proposed using e.g. ref err?:  errorstate to mark
>>>>   optional arguments.
>>>> - Brad suggested an example of proc foo(ref err = new errorstate());
>>>>   At that point, I stopped understanding the discussion...
>>>>
>>>> Is there some consensus about the design of this feature? In my mind,
>>>> there need to be three decisions:
>>>>
>>>> 1) How does a procedure mark an optional argument?
>>>> 2) How does the procedure check if the optional argument was specified?
>>>> 3) Is whether or not the argument was specified a compile-time
>>>>    or run-time variable inside the procedure?
>>>>
>>>> Solution A: ? marks parameters, .defaultValueUsed checks.
>>>> Variants on this solution include introducing another argument intent
>>>> 'optional' or 'optout' or ... and any other choice of name for
>>>> .defaultValueUsed  :
>>>>   proc foo(out err?: int = 0) {
>>>>     err = ...
>>>>     if err && err.defaultValueUsed then halt(err);
>>>>   }
>>>>   var err:int;
>>>>   foo(err);
>>>>
>>>>
>>>> Solution B: do everything with a class
>>>>   class MyClass {
>>>>      var isDefault:bool;
>>>>      var error:int;
>>>>   }
>>>>   proc foo(out error = new MyClass(true, 0)) {
>>>>     var defaultValueUsed = error.isDefault;
>>>>     err = ...
>>>>     if err && defaultValueUsed then halt(err);
>>>>     if !defaultValueUsed then error.errcode = err;
>>>>   }
>>>>   var getError = new MyClass(false, 0);
>>>>   foo(getError);
>>>>   ... use getError.error ...
>>>> (I don't like this solution because it adds noise to
>>>> the function call site if somebody wanted the error
>>>> code, and it adds unnecessary allocator activity).
>>>>
>>>>
>>>> Solution C: add a 'some' type (or 'optional'),
>>>> and then hope for automatic coercion:
>>>>   // in a library somewhere
>>>>   record some {
>>>>     var empty:bool = true;
>>>>     var value:ref;
>>>>     proc hasValue { return !empty; }
>>>>   }
>>>>   proc foo(out error = new some(int)) {
>>>>     err = ...
>>>>     if err && error.empty then halt(err);
>>>>   }
>>>>   var err:int;
>>>>   foo(err); // hopefully the int argument will promote to some(int)
>>>>   // but you would write foo(new some(err) if not.
>>>> A problem with this solution is that the value in some has to be
>>>> a reference to the original err argument, which seems to be asking
>>>> more of the language than the other options.  However, if the
>>>> 'some' type were defined in the language rather than in a library,
>>>> at least it would still be clear how to handle (2).
>>>>
>>>> I like A and C could be made to work (but it would probably
>>>> look more like a different way of writing A). I don't view B
>>>> as a solution, so I'm hoping that's not what you just agreed upon...
>>>>
>>>> Cheers,
>>>>
>>>> -michael
>>>>
>>>> On 12/09/2013 08:36 PM, Brad Chamberlain wrote:
>>>>> Oh, good!  Now we just need someone to implement the behavior for ref
>>>>> intents and document the old and new behavior...  :)  I'm hoping that the
>>>>> implementation will be a fairly simple matter of finding and duplicating
>>>>> the logic that's used for 'inout' intents.
>>>>>
>>>>> -Brad
>>>>>
>>>>>
>>>>> On Mon, 9 Dec 2013, Chris Doris wrote:
>>>>>
>>>>>> Aha! I was not aware that there was this special case for out and inout
>>>>>> intents --- it's not in the spec. If I was, I would merely have
>>>>>> suggested
>>>>>> extending it to the ref intent.  I agree that syntax shouldn't be added
>>>>>> without good reason, it was just the easiest way to explain the feature.
>>>>>>
>>>>>> This discussion has deepened my understanding of Chapel.  Thank you!
>>>>>>
>>>>>> Chris
>>>>>>
>>>>>
>>>>>
>>>>> ------------------------------------------------------------------------------
>>>>> Sponsored by Intel(R) XDK
>>>>> Develop, test and display web and hybrid apps with a single code base.
>>>>> Download it for free now!
>>>>> http://pubads.g.doubleclick.net/gampad/clk?id=111408631&iu=/4140/ostg.clktrk
>>>>> _______________________________________________
>>>>> Chapel-developers mailing list
>>>>> [email protected]
>>>>> https://lists.sourceforge.net/lists/listinfo/chapel-developers
>>>>>
>>>>
>>
> ------------------------------------------------------------------------------
> Rapidly troubleshoot problems before they affect your business. Most IT
> organizations don't have a clear picture of how application performance
> affects their revenue. With AppDynamics, you get 100% visibility into your
> Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
> http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
> _______________________________________________
> Chapel-developers mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/chapel-developers


------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
Chapel-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-developers

Reply via email to