'when' keyword

Started by
18 comments, last by delta user 15 years, 2 months ago
I had this thought/idea a while ago, and was thinking about it again recently(this morning). Before/while I'm writing this post, I did/am-doing a quick Google search, and it seems the Ada language has this keyword already, although I haven't been able to find out if it was the same usage as I was thinking should be used for it. The way I was thinking involved properties, and might have the syntax of:
when <property> is <condition> <action>
So, for example, if I wished to alert the user when they try to scroll past the bounds of a scrollbar, I might have this in my constructor:

when scrollbar.Value is >scrollbar.Maximum
{
    MessageBox.Show("Scrollbar is at its limit!");
}
Implementation-wise, I'd imagine it'd 'add' the code(or, for all intents and purposes, just seem to add the code) to the Value property(without letting the code access internal/protected variables that it wouldn't normally have acces too, etc.). Then, when scrollbar.Value exceeds its Maximum(note that the actual "code" for '>scrollbar.Maximum' would be added, not the then-value of scrollbar.Maximum), it would pop-up the message box. So far, my idea only allows for the when code to exist for the entire duration that the class it is in exists, though I suppose an 'unwhen' keyword could be added... :/ So why am I tell you all this? :p Mainly cause I'd like to know if it is a good/bad idea, other than the "we don't need no more stinkin' keywords" line.
Advertisement
Quote:Original post by nerd_boy
when scrollbar.Value is >scrollbar.Maximum{    MessageBox.Show("Scrollbar is at its limit!");}

The keyword is called "if":
when if (scrollbar.Value is > scrollbar.Maximum) {    MessageBox.Show("Scrollbar is at its limit!");}

Quote:Original post by frob
The keyword is called "if":


XD

Sorry, I was just informed over IRC that I didn't make myself overly clear.
As jpetrie put it, '"when" is like injection of a delegate', whereas "if" is static.

if(scrollbar.Value>whatever) would only perform when the function/method/whatever containing was called.

when(scrollbar.Value is >whatever) would perform when scrollbar.Value is changed.

If that clears things up a bit...

I think he wants different behavior than 'if'. He wants what is essential injection of some callback into the property setter for the given property. E.g., using a C#-like example, given:
public int P {  get {    return p;  }  set {    p = value;  }}

then
when P > 10 {  Console.WriteLine("P > 10");}

would change the effective behavior of P's setter to be:
set {  p = value;  if( p > 10 ) {    Console.WriteLine("P > 10");  }}

So rather than direct execution of the conditional at that point in execution, execution of the conditional is deferred until the property in question is changed. You can, for example, simulate this in C# with interfaces supporting INotifyPropertyChanged. It's only useful to extend the properties of types you don't have control over or perhaps only want a localized, per-instance check.

It's an interesting idea, at least, but I find it a wee bit sketchy and full of a lot of edge cases that would be need to clearly defined -- what is the scope of the executing code, for example? Can it access 'this'? When exactly does it run for complex setters?
Edit: jpetrie posted while I was posting.

Since you used MessageBox.Show() in your example, I presume you are using C#. So why don't you just put it into the "setter" of the Value property?

public int Value{  get { ... }  set  {    if(Value > Maximum)       MessageBox.Show("Scrollbar is at its limit!");  }}


Or am I missing something? Oh, and I also don't like the use of is. It serves no purpose, and when you have a variable with a name in plural form, it becomes odd.

[Edited by - Heptagonal on January 20, 2009 11:23:22 AM]
I think that it could be a good idea to allow a shortcut syntax to conditional events on a property. More likely you'd want the syntax more like this:

class ScrollBar{    public auto int Maximum { ... }    public auto int Minimum { ... }    public auto int Position{        get;        set;        when (value > Maximum){ value = Maximum; }        when (value < Minimum){ value = Minimum; }    }}


It behaves a little like certain contract designs I'd bet, but the implementation would essentially generate a delegate for the setter and hook the two when clauses into it.

I'm a little skeptical that it could be implemented well and consistently for the general case. And I think that it is less important if a language could properly allow users to define property types that are more complex than the simple get/set/value case.
Quote:Original post by jpetrie
...what is the scope of the executing code, for example? Can it access 'this'


Eh, not sure how'd it be implemented, but scope would be the same as the injector. Which is to say scrollbar would be the scrollbar in the class using the when keyword, not the Scrollbar class. I'm not sure, exactly, what would be done in cases where the variable in question no longer exists. Class-wise, the when code could just be uninjected when the class is disposed/GC/whatever. But for variables who have a scope limited to a function or the inside of an if-statement, I'm not sure. >_> Perhaps a compile-time check to make sure the variable in use has a scope equivalent to that of the class?
Quote:Original post by jpetrie
When exactly does it run for complex setters?

Tacked on at the end, in order of injection.
public int SetMe{    set    {        me=value;        /*when usage 1*/        /*when usage 2*/        /*...*/        /*when usage n*/    }     }


Also, although C# like syntax is in use, this isn't inteded to mean I'm suggesting when for the C# language, but rather overall.

Quote:Original post by Heptagonal
Edit: jpetrie posted while I was posting.

Since you used
MessageBox.Show()
in your example, I presume you are using C#. So why don't you just put it into the "setter" of the Value property?


I'm presuming jpetrie's post explained for you that the properties' code isn't accessible? :/ I need to explain things better...

Quote:Original post by Heptagonal
Oh, and I also don't like the use of is. It serves no purpose, and when you have a variable with a name in plural form, it becomes odd.


The purpose it serves here is so the when keyword would know which property the condition/code is to be applied to.

when(scrollbar.Value>scrollbar.Maximum) could be used, yes, without the need for the is keyword, but then there might be confusion over something like when(scrollbar.Maximum>scrollbar.Value), where the condition/code would be injected into the scrollbar.Maximum property, since it is the first property 'found'.

Using the is keyword clears up which property the condition/code is to be applied to.

Bloody double-posting frown-upons.... ;-;
This behavior shows up in various disparate programming models. Probably the most familiar one is SQL triggers: Every time a row is inserted or updated, do such-and-such. Make the such-and-such conditional on the row itself, or on other data, and you have the basics of you when. Key constraints offer a similar but more implicit and limited version of this.

In imperative, procedural languages, the closest thing to SQL triggers -- and therefore to when -- is events. Add a delegate listener to Scrollbar.ValueChanged that checks the condition and shows the message box, and there you are.

What's missing here, of course, is full injectability. As a user of a class, you can latch on to any events that class exports, but if you're trying to watch for a change in data that may not be followed immediately by an event firing, you are out of luck. This dovetails nicely with the hardcore encapsulation of C#, but is for crap with nimbler languages like Python.

Python, speaking of which, actually does offer this (kind of). Simply inject a setter metamethod into an object which checks the condition. It's not necessarily polite, but it works. Hell, if you do it right, these things can even be chained.

There's significant problems to injecting things like this, though. The biggie is the potential for the predicate to execute when data is in a weird state. Normally a class will clean up after itself before invoking event listeners, such that class invariants are actually invariant during the listener executions. In contrast, injecting an observer can cause the predicate to execute in the middle of a transitionally invalid object state.
Quote:Original post by nerd_boy

Using the is keyword clears up which property the condition/code is to be applied to.


when scrollbar.Value is >=scrollbar.Maximum{  scrollbar.Value = scrollbar.Maximum-1;}when scrollbar.Value is <=scrollbar.Minimum{  scrollbar.Value = scrollbar.Minimum+1;}scrollbar.setMinimum(0);scrollbar.setMaximum(1);scrollbar.setValue(1);


If you want to find out more about problems that occur, try &#106avascript, which supports such injection. Then do something like that for built-in classes like strings, and try it across different browsers, or just with non-trivial inheritance.<br><br>As soon as you try non-trivial injection, you'll see why it's either not possible, or prohibitively expensive.
Quote:Original post by Sneftel
There's significant problems to injecting things like this, though. The biggie is the potential for the predicate to execute when data is in a weird state. Normally a class will clean up after itself before invoking event listeners, such that class invariants are actually invariant during the listener executions. In contrast, injecting an observer can cause the predicate to execute in the middle of a transitionally invalid object state.


Yeah, I'm not sure I've ever thought of that. A workaround comes to mind, however, if the language allowed for anonymous functions. Then, instead of injecting the code directly, either have it be when(<property>is<condition>)<function> or have the code in place of <function> be turned into an anonymous function for the class using the when keyword.

And, in this case, when it trys to call the function of 'a transitionally invalid object state', where, I assume, you wouldn't be able to call the function and would get an error/exception if you did, just ignore that specific error/exception.

This topic is closed to new replies.

Advertisement