has statement

The statement <OWNER VAR> has <ATTRIBUTE VAR> is used to identify the <OWNER VAR> as owning the <ATTRIBUTE VAR>.

Schema for the following examples
#!test[schema]
define
attribute name, value string;
entity person, owns name;

Inserting attribute ownership

The has keyword can be used to attach an attribute to an object.

#!test[write]
#{{
match $person isa person; $name isa name;
#}}
insert $person has $name;

An attribute can be created in-place by providing its type and value.

#!test[write]
#{{
match $person isa person;
#}}
insert $person has name "Alice";

If the value is a variable instead of a literal, you must use ==.

#!test[write]
#{{
match
$person isa person;
#}}
match let $name_value = "Alice";
insert $person has name == $name_value;

Writing insert $person has name $name_value; will result in an error: "The variable 'name_value' cannot be declared as both a 'Attribute' and as a 'Value'."

This is best understood by rewriting syntactic short-hands into atomic constraints.

$p has name $n; becomes $p has $n; $n isa T;.

$p has T == $n; becomes $p has $_a; $_a isa T; $_a == $n;

In the first case, $n is clearly an attribute. The second case, introduces a new variable $_a as the attribute and requires its value to be the same as that of $n.

The confusion arises from being able to write $p has name "Alice;". But:

$p has name "Alice;" becomes $p has T == "Alice";

This is syntax-sugar introduced ONLY for literals, and is rewritten further as above.

Deleting attribute ownership

The has keyword is used to remove an attribute from its owner.

#!test[write]
#{{
match $person isa person, has name $name;
#}}
delete has $name of $person;

Matching attributes

The has keyword can be used to match attributes of an object.

#!test[read]
match $person has $name;

The attribute type may be provided.

#!test[read]
match $person has name $name;

The attribute can be matched by attribute type and value instead of binding it to a variable.

#!test[read]
match $person has name "Alice";

Alternatively, a comparison can be used to constrain the attribute value.

#!test[read]
match $person has name < "Bob";