19

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?

Pindatjuh
  • 10,550
  • 1
  • 41
  • 68
  • 1
    AND/OR is the same as OR, in a Boolean sense. – Paul R Mar 24 '10 at 23:14
  • This clearly is not Boolean algebra. Note the self-reference in the definition. – Pindatjuh Mar 24 '10 at 23:14
  • 1
    Using the "and/or" terminology is probably not such a great idea then - maybe you could use a term which is less ambiguous and gives some hint as to what you are actually trying to achieve ? – Paul R Mar 24 '10 at 23:16
  • That's the whole point: I do not know how it's called ;-) I've called it and/or because sometimes it's the Boolean's `and`, and sometimes it's its `or`. – Pindatjuh Mar 24 '10 at 23:17
  • 4
    You haven't specified what you mean except by using words which you admit are not entirely accurate. Try giving some examples with expected output... – dmckee --- ex-moderator kitten Mar 24 '10 at 23:21
  • Look at his blog post, and you might get the idea – Samuel Carrijo Mar 24 '10 at 23:30
  • Looks like a short hand way for working with arrays – Bob Mar 24 '10 at 23:33
  • So, basically you're saying "|" is a union operator and "==", when performed on a union object, is an intersection operator that modifies the object itself, restricting visible values to those on the right hand side? I like the union operator concept, but I think overloading the comparison operator like that is a poor choice. In no other (sane) situation does the comparison operator actually change the way one of its operands behaves. Why not instead have an actual intersect operator that works like the union operator, in that it doesn't change its operands but the result can be assigned? – tloflin Mar 24 '10 at 23:41
  • @tloflin: thanks for the suggestion! Still working on syntax; but I thought it was easier to understand using conventional syntax. – Pindatjuh Mar 24 '10 at 23:45
  • 2
    It sounds like you're looking to define a highly declarative language, rather than a procedural language. I applaude the brain-space you have to do that! – staticsan Mar 24 '10 at 23:48
  • 1
    I think it would be a lot clearer if the word 'if' were replaced with 'with' – Dan Bryant Mar 24 '10 at 23:55
  • Why is this question a community wiki??? (I probably should ask that on Meta) – Pindatjuh Mar 25 '10 at 21:24
  • So if i understand correctly, all with blocks are executed (more-or less but we don't care) simultaneously? – RCIX Mar 27 '10 at 10:59
  • Interesting... Definitely bookmarked your blog! :) – RCIX Mar 28 '10 at 00:34

10 Answers10

4

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
  • 114,894
  • 38
  • 205
  • 284
  • No; it'll mean: `(x == a) | (x == b)`. The `||` is a Boolean operator, `|` is not, here. – Pindatjuh Mar 24 '10 at 23:30
  • 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 Mar 24 '10 at 23:34
  • 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 Mar 24 '10 at 23:35
  • 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 Mar 24 '10 at 23:53
  • 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 Mar 24 '10 at 23:58
  • "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 Mar 25 '10 at 00:08
  • 2
    Thank you. I'll try not to have nightmares! :) – Daniel Earwicker Mar 25 '10 at 00:11
4

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.

Community
  • 1
  • 1
MaD70
  • 4,078
  • 1
  • 25
  • 20
3

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
  • 198,648
  • 61
  • 360
  • 533
3

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
  • 647,829
  • 179
  • 1,238
  • 2,067
3

Your language feature resembles junctions in Perl 6.

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

Jordão
  • 55,340
  • 13
  • 112
  • 144
2

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
  • 29,935
  • 4
  • 60
  • 73
  • Yes, saw that. Thanks. I added some more comments as a response. – staticsan Mar 24 '10 at 23:46
  • Yield means something different in Ruby as compared with Python. Also I believe the first language with iterators was CLU. – Daniel Earwicker Mar 25 '10 at 00:08
  • Fair enough. I don't have much experience with either Ruby or Python. – staticsan Mar 25 '10 at 05:58
  • 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 Mar 27 '10 at 23:38
0

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
  • 1,588
  • 13
  • 15
0

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
  • 528,062
  • 107
  • 651
  • 834
0

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 --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234
0

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;
}