views:

664

answers:

10

I'm currently developing a new language for programming in a continuous environment (compare it to electrical engineering), and I've got some ideas on a certain language construction.

Let me explain the feature by explanation and then by definition:

x = a U b;

Where x is a variable and a and b are other variables (or static values). This works like a union between a and b; no duplicates and no specific order.

with(x) {
    // regular 'with' usage; using the global interpretation of "x"
    x = 5;
    // effectively will do:
    // x = a U b U 5;
    // a = 5;
    // b = 5;
    // Thus, when "a" or "b" changes, "x" is still equal to "5".
}
with(x = a) {
    // this code block is executed when the "x" variable
    // has the "a" variable assigned. All references in
    // this code-block to "x" are references to "a". So saying:
    x = 5;
    // would only change the variable "a". If the variable "a"
    // later on changes, x still equals to 5, in this fashion:
    // 'x = a U b U 5;'
    // '[currentscope] = 5;'
    // thus, 'a = 5;'
}
with(x = b) {
    // same but with "b"
}
with(x != a) {
    // here the "x" variable refers to any variable
    // but "a"; thus saying
    x = 5;
    // is equal to the rewriting of
    // 'x = a U b U 5;'
    // 'b = 5;' (since it was the scope of this block)
}
with(x = (a U b)) {
    // guaranteed that "x" is 'a U b'; interacting with "x"
    // will interact with both "a" and "b".
    x = 5;
    // makes both "a" and "b" equal to 5; also the "x" variable
    // is updated to contain:
    // 'x = a U b U 5;'
    // '[currentscope] = 5;'
    // 'a U b = 5;'
    // and thus: 'a = 5; b = 5;'.
}
// etc.

In the above, all code-blocks are executed, but the "scope" changes in each block how x is interpreted. In the first block, x is guaranteed to be a: thus interacting with x inside that block will interact on a. The second and the third code-block are only equal in this situation (because not a: then there only remains b). The last block guarantees that x is at least a or b.

Further more; U is not the "bitwise or operator", but I've called it the "and/or"-operator. Its definition is:

"U" = "and" U "or"

(On my blog, http://cplang.wordpress.com/2009/12/19/binop-and-or/, there is more (mathematical) background information on this operator. It's loosely based on sets. Using different syntax, changed it in this question.)

Update: more examples.

print = "Hello world!" U "How are you?"; // this will print
                                         // both values, but the
                                         // order doesn't matter.
// 'userkey' is a variable containing a key.
with(userkey = "a") {
    print = userkey; // will only print "a".
}
with(userkey = ("shift" U "a")) {
    // pressed both "shift" and the "a" key.
    print = userkey; // will "print" shift and "a", even
                     // if the user also pressed "ctrl":
                     // the interpretation of "userkey" is changed,
                     // such that it only contains the matched cases.
}
with((userkey = "shift") U (userkey = "a")) {
    // same as if-statement above this one, showing the distributivity.
}

x = 5 U 6 U 7;
y = x + x; // will be:
// y = (5 U 6 U 7) + (5 U 6 U 7)
//   = 10 U 11 U 12 U 13 U 14

somewantedkey = "ctrl" U "alt" U "space"
with(userkey = somewantedkey) {
    // must match all elements of "somewantedkey"
    // (distributed the Boolean equals operated)
    // thus only executed when all the defined keys are pressed
}
with(somewantedkey = userkey) {
    // matches only one of the provided "somewantedkey"
    // thus when only "space" is pressed, this block is executed.
}

Update2: more examples and some more context.

with(x = (a U b)) {
    // this
}
// can be written as
with((x = a) U (x = b)) {
    // this: changing the variable like
    x = 5;
    // will be rewritten as:
    // a = 5 and b = 5
}

Some background information: I'm building a language which is "time-independent", like Java is "platform-independant". Everything stated in the language is "as is", and is continuously actively executed. This means; the programmer does not know in which order (unless explicitly stated using constructions) elements are, nor when statements are executed. The language is completely separated from the "time"-concept, i.e. it's continuously executed:

with(true) {
    a = 0; // only runs once (lazy execution)
}

with(a < 5) {
    a++;
} // this is a loop-structure;
  // how and when it's executed isn't known however.

with(a) {
    // everytime the "a" variable changes, this code-block is executed.
    with(true) {
        b = 3; // only 5 times (again lazy execution, but it's a sub-with)
    }
    with(b < 2) { // dependent on "b"
        // runs only 3 times * 5 times = 15 times.
    }
    with(b > 1) { // dependent on "b"
        b = b - 1; // runs 4 times * 5 times = 20 times.
    }
}

Update 3:

After pondering on the type of this language feature; it closely resemblances Netbeans Platform's Lookup, where each "with"-statement a synchronized agent is, working on it's specific "filter" of objects. Instead of type-based, this is variable-based (fundamentally quite the same; just a different way of identifiying objects).

I greatly thank all of you for providing me with very insightful information and links/hints to great topics I can research. Thanks.

I do not know if this construction already exists, so that's my question: does this language feature already exist?

+3  A: 

I'm finding this hard to follow, but do you mean that:

x == a | b 

will be syntax sugar equivalent to:

(x == a) || (x == b)

On the blog post you give this example:

1 + (2|3)

So the type of that expression is a pair of integers with the values 3 and 4, each representing one of the possible values. So we can also say:

4 == (1 + (2|3)
3 == (1 + (2|3)

and both of those would evaluate to true. So the operator == can compare a value with a kind of vector of values and will be true if any of the values in the vector are equal to the first value.

This could be implemented using operator overloading in a few languages (although you'd have to explicitly "lift" simple values into a wrapper type before you could operate on them).

Isn't it effectively the same as the union of two sets, and with == interpreted as "is a member of"? And operators like + being lifted so they apply to all the members of the set.

And if you did (1|2) + (4|8) you'd get the equivalent of (5|9|6|10), because those are the four possible outcomes.

Okay, from further examples you added, I see that == in fact requires the left and right sides to be the same set, rather than merely overlapping. But I still get the impression that your | is simply the union of two sets. What this entails (or means) will depend on what you do to all the other features of your language to deal with sets.

Regarding your statement:

The language is completely separated from the "time"-concept

Have you looked much at pure functional languages like Haskell? Programs are a series of definitions with no known order of execution, you can only write pure functions with no side-effects, and hence the interpreter can order execution however it likes as long as values are available when really needed.

Update:

You added this to your question:

if(x == a | b) {
    // this 
}
// can be written as
if((x == a) | (x == b)) {
    // this
}
// which can be written as
if(x == a) {
    // this
}
if(x == b) {
    // with this
}

I wonder how you think that's going to be illuminating!

The thing is, the first two versions have one block of code under the if. So if the third expanded version has two blocks, they must be the same block. In other words, this is just another way of writing:

if (x == a || x == b) {
    // this
}

Where || is the traditional boolean OR. Which is exactly the question I first asked.

Okay, one more time... You've now changed the syntax to indicate that you're doing unions and intersections. But then:

if(userkey I ("shift" U "a")) {
    // pressed both "shift" and the "a" key.

So I means take the intersection of the two sets... but if executes the code block under what circumstances? If the intersection is non-empty? Or is I in fact asking "are all the members of the set on the right members of the set on the left" And there are hints that userkey is replaced in the scope of the block by another value which actually just the set on the right.

I'm going to bed.

Daniel Earwicker
No; it'll mean: `(x == a) | (x == b)`. The `||` is a Boolean operator, `|` is not, here.
Pindatjuh
Yes, but == produces a boolean result, right? So does my expansion in terms of boolean "or" have the same behaviour for that specific example?
Daniel Earwicker
The `==` indeed provides a boolean result; thus the `if`-block is also distributed over all the `|` contents. I'll update the question; adding another example.
Pindatjuh
Yes, I have indeed looked at Haskell. But, this language also allows "nonpure-functions" mixed between "pure-functions" (Actually; it doesn't even have functions).
Pindatjuh
No, no obscure language intended, to help you wonder. The `||` actually, that rewrite was incorrect; since the two new if-blocks have a shared interpretation of the `x` variable. Removed it from the example, I'm sorry for that. It's hard to explain a new concept!
Pindatjuh
"Or is I in fact asking "are all the members of the set on the right members of the set on the left" And there are hints that userkey is replaced in the scope of the block by another value which actually just the set on the right." You've got it! Have a good night.
Pindatjuh
Thank you. I'll try not to have nightmares! :)
Daniel Earwicker
+2  A: 

You should have invented your own symbols, even just for the example.

It looks like you're trying to do variable references that dynamically change as the scope definition requires. That is a very subtle technique and I don't know any language that does it. Most languages require you to do this explicitly although I can see similarities with closures, generators and back-tracking.

Could you explain the context driving this unusual method? Your blog link was not very helpful. And the term 'continuous programming' is not defined or explained, either.

Update:

Okay, looking at your edited example, I can point to Icon as having something similar. It is not quite what you think you're asking for, and it is not common, but it seems close and it much better defined. It is called Goal-Directed Evaluation.

Many language elements provide or allow you to construct a generator which can give a number of alternatives if asked. The main difference between your example and Icon you have to provide a context for the language to keep trying alternatives. Assignment doesn't do it, but a comparison will. Once a generator runs out of values it can supply, it fails. This is also how ordinary comparison works and the whole feature integrates nicely into the wider language. (I sometimes describe this as being like miniature exceptions.)

Python and Ruby have a yield mechanism which is very similar and arguably influenced by Icon's generators.

staticsan
Updated the question.
Pindatjuh
Yes, saw that. Thanks. I added some more comments as a response.
staticsan
Yield means something different in Ruby as compared with Python. Also I believe the first language with iterators was CLU.
Daniel Earwicker
Fair enough. I don't have much experience with either Ruby or Python.
staticsan
Coroutines date from 1963. See Melvin Conway's paper in CACM from that year, *Design of a separable transition-diagram compiler*, for details. Iterators build very clearly on top of that. CLU dates from over a decade after that.
Donal Fellows
A: 

I advise you not to add that language feature. It would be very unclear to the programmer that the meaning of x changes if you do a "test" like:

if( x != a ) { ... }
bitc
+2  A: 

Your examples and your math could both use some work, but in at least one of the examples on your blog, your use of | closely resembles the use of the same operator (there called "alternation", I believe) in the Icon programming language.

If you're going to commit language design in this area, you should definitely read about

Norman Ramsey
A: 

The Inform IF-authoring language had this feature. From the DM:

if (alpha == 3 or 4) print "Scott";

It hasn't really caught on much further, though, as it's a bit weird to parse (you have to associate each or/| operator with a particular owner ==/!= comparator), and in modern scripting languages it's easy to replace with something like:

if alpha in (3, 4):
    print 'Scott';

(Python example.)

bobince
+3  A: 

C# certainly doesn't have the features you are describing. What you're talking about seems somewhat reminiscent of Robin Milner's pi calculus; it's all about defining a language for describing concurrent processes. You might consider doing some research into it if you haven't already.

Eric Lippert
A: 

You seem to be poking around several ideas at once:

  • A list syntax where you do something like 5 | 6 | 7
  • using the outer product where you've been writing ::list:: + ::list::
  • carefully defining the meaning of the equality, inequality, assignment, etc. operators when one or both arguments is a list. I.e. that ::scalor:: == ::list:: implements "is an element of", and so on

I'm not aware of a single syntaxtical feature that combines those idea, but then I don't have really wide experience...

dmckee
+4  A: 

I honestly find your explanation and examples difficult to follow (update: your blog is much better and reading Statement Ordering there I'm even more convinced that you are aiming at a form of dataflow programming).

However, your final description:

Everything stated in the language is "as is", and is continuously actively executed. This means; the programmer does not know in which order (unless explicitly stated using constructions) elements are, nor when statements are executed. The language is completely separated from the "time"-concept, i.e. it's continuously executed: saying that "a" is "b" and "b" is "a" is a simple loop-structure, for instance.

.. induces me to think that the general term that you are searching for is dataflow programming (even if loops are not permitted in the more simple instances of dataflow programming). Quoting from Wikipedia:

Dataflow is a software architecture based on the idea that changing the value of a variable should automatically force recalculation of the values of variables which depend on its value.

Reactive programming and functional reactive programming are, as I understand them, variations on the same theme.

Icon's goal-directed evaluation is more restricted in scope (see this A Brief Introduction to Icon: The backtracking implied by the goal-directed evaluation mechanism is limited to the expression in which it occurs).

See also this question on Stackoverflow: Dataflow Programming Languages.

Update: Pindatjuh asks in comments "Can you also comment, whether this language is a new variation on the theme of dataflow?". I think so, but the question is really about definitions and so about consensus. In a recent survey about dataflow languages, Advances in dataflow programming languages (published in ACM Computing Surveys, Volume 36 , Issue 1, March 2004), authors wrote (page 10):

The best list of features that constitute a dataflow language was put forward by Ackerman [1982] and reiterated by Whiting and Pascoe [1994] and Wail and Abramson [1995]. This list includes the following:

  1. freedom from side effects,
  2. locality of effect,
  3. data dependencies equivalent to scheduling,
  4. single assignment of variables,
  5. an unusual notation for iterations due to features 1 and 4,
  6. lack of history sensitivity in procedures.

I haven't read all your blog but just perused it lightly, so you are more qualified than me to judge about your programming language (which is a moving target anyway).

Update: I unconsciously missed the word "new" in your question "... this language is a new variation on...". It is an hard task: one needs to consider all the dataflow languages invented until now and carefully examine their semantics in detail to spot a novelty in your approach. I surely haven't the necessary knowledge at this time.

MaD70
Can you also comment, wether this language is a new variation on the theme of dataflow?
Pindatjuh
+2  A: 

Your language feature resembles junctions in Perl 6.

In Perl 5, there's the Quantum::Superpositions module.

Jordão
A: 

The "with" exist in as3:

private var _a:Number = 0.0;
public function get a():Number{
// Do stuff
    return _a;
}
public function set a(value:Number):void{
// Do stuff
    _a=value;
}
M28
I know AS3, but I can't see why the `with` is equal to that. Can you explain?
Pindatjuh
He said that the with will execute when the variable changes, that's what I understood
M28