w3c / cogai

for work by the Cognitive AI community group
Other
53 stars 24 forks source link

Negation operator "!" #31

Closed tidoust closed 3 years ago

tidoust commented 3 years ago

The informal document that introduces chunks describes a negation operator ! for conditions:

!present {@module facts; person Mary; room room1}

... which will match the facts module buffer after a failure to get a chunk of type present with the corresponding properties.

This operator needs to be formalized. Things to resolve:

  1. There needs to be a way to express the same thing in expanded form, for instance
    rule r1 {
      @condition !c1
      @action a1
    }
  2. The above example shows that we can probably reuse the ~ operator in the expanded form. Which begs the question as to whether we need a distinct character for the compact form, which could rather be:
    ~present {@module facts; person Mary; room room1}
  3. Actually, if we reuse the same operator, wouldn't ! be preferrable to ~ as a more universal negation operator?
draggett commented 3 years ago

Here is an example from the smart home demo:

# if John isn't present continue to step 5
state {step 3}, !person {@module facts; @id John}
=>
  present{@module facts; @do get; @id Janet},
  state {step 5}

where ! is applied to a condition chunk.

Here is an example from the counting demo:

# count up one at a time
count {state counting; start ?num1; end ~?num1},
increment {@module facts; number ?num1; successor ?num3} =>
    count {start ?num3},
    increment {@module facts; @do get; number ?num3},
    console {@do show; value ?num3}

where ~ is applied to a property value.

If we use the full form for the first example, we would have something like:

rule r1 {
    @condition c1, !c2
    @action a1, a2
}
state c1 {step 3}
person c2 {@module facts; @id John}
present a1 {@module facts; @do get; @id Janet}
state a2 {step 5}

Note that ! doesn't have the same semantics as ~. The current explanation of ~ is as follows:

Whilst normally, the condition property must match the buffered chunk property, sometimes you want a rule to apply only if the condition property doesn't match the buffered chunk property. For this you insert tilda (~) as a prefix to the condition's property value. You can further test that a property is undefined by using ~ on its own in place of a value. In an action you can use ~ on its own to set a property to be undefined.

You can thus use ~ on its own for a property value in a condition or action. Should we replace~ by ! for those cases as well as for the case where ~ is used as a prefix for a property value? Another possibility would be to introduce another term for undefined, e.g. @undefined. What do you think?

tidoust commented 3 years ago

Following today's discussion, idea is to start with only one operator.

draggett commented 3 years ago

The javascript library and test suite have been update to reflect the use of ! in place of ~.

! can be used on condition chunks and their properties, including list items. Note that ! on its own in acts as a wild card, matching any value.

! can be used as a property value for action chunks, but not for list items as the meaning isn't clear in such cases. ! on its own clears the corresponding property in the current chunk in the module buffer.

tidoust commented 3 years ago

One thing to note in the spec is that the ! operator cannot be used in front of a variable name during binding.

# Invalid: ?num1 cannot get negated before it gets bound
count {state counting; start !?num1} => ...
tidoust commented 3 years ago

! can be used on condition chunks and their properties, including list items. Note that ! on its own in acts as a wild card, matching any value.

When it is used on its own as property value, ! is used to test that a property is undefined as in:

# Matches a person chunk that does not have an animal property
person {animal !} => ...

It seems weird to me that the operator becomes a wild card that matches any value when it appears as atomic value in a list.

For instance, the test suite includes the following test:

run {test test6} => test6 {list a, b, c, d}
test6 {list a, !d, c, !} => action {@do result; test test6; result true}

For me, the second ! in the condition should mean "fourth value is undefined", and not "fourth value can be anything". I would actually forbid the use of ! on its own as an atomic value in a list because it does not mean much in practice: a list cannot have undefined atomic values. In the test example, the list can have 3 atomic values, but if it has 4 atomic values, then the fourth one cannot be undefined.

draggett commented 3 years ago

I agree with you about the use of ! as an atomic value in a list. Instead it would seem better to use a different symbol for use a wild card, e.g. *, which can be used on its own or as part of a list, and to forbid the use of ! as an atomic value in lists. What do you think?

tidoust commented 3 years ago

Spec now has a section that describes the negation operator and the wild card operator. Closing this issue accordingly.