trueagi-io / hyperon-experimental

MeTTa programming language implementation
https://metta-lang.dev
MIT License
153 stars 50 forks source link

[BUGFIX] Fixing DAS vars resolution #729

Closed angeloprobst closed 4 months ago

angeloprobst commented 4 months ago

Rationale

While working with MeTTa and DAS Gate, I faced the following situation: the same query that works perfectly with the built-in atom space, when executed using DAS, does not resolve some variables if a function is defined and called to match some condition. For example:

[(parent of Paul = $y#40)]
[(parent of Paul = John)]

The first line is the output of a query on DAS. And the second one comes from the same query but using the built-in space.

The issue does not happen on DAS if the match is made without calling a function. For example, this query fails (output shows a non-resolved variable):

(= (get_parent_from_das $x) (match &das (Parent $y $x) $y))
!(parent of Paul = (get_parent_from_das Paul))

However, this match works perfectly (it shows the value):

!(match &das (Parent $y Paul) (parent of Paul = $y))

And both queries are equivalent.

Sample Script

(two first queries do not have variables properly resolved)

!(import! &self das_gate)

!(bind! &das (new-das))
!(bind! &local (new-space))

!(add-atom &das (Parent John Paul))  ; Paul is child of John
!(add-atom &das (Person Paul))

!(add-atom &local (Parent John Paul))  ; Paul is child of John
!(add-atom &local (Person Paul))

; getting parent from das using a function
(= (get_parent_from_das $x)
    (match &das (Parent $y $x) $y))
!(parent of Paul = (get_parent_from_das Paul))  ; person as a constant
!(match &das (Person $x)  ; person as a wildcard
    (parent of $x = (get_parent_from_das $x)))

; getting parent from das, inline, no function
!(match &das (Parent $y Paul) (parent of Paul = $y))  ; person as a constant
!(match &das (Person $x)  ; person as a wildcard
    (parent of $x = (match &das (Parent $y $x) $y)))

; getting parent from local using a function
(= (get_parent_from_local $x)
    (match &local (Parent $y $x) $y))
!(parent of Paul = (get_parent_from_local Paul))  ; person as a constant
!(match &local (Person $x)  ; person as a wildcard
    (parent of $x = (get_parent_from_local $x)))

; getting parent from local, inline, no function
!(match &local (Parent $y Paul) (parent of Paul = $y))  ; person as a constant
!(match &local (Person $x)  ; person as a wildcard
    (parent of $x = (match &local (Parent $y $x) $y)))

Output is: (two first lines should show John instead of $y#40 and $y#55)

[(Parent of Paul = $y#40)]
[(Parent of Paul = $y#55)]
[(Parent of Paul = John)]
[(Parent of Paul = John)]
[(Parent of Paul = John)]
[(Parent of Paul = John)]
[(Parent of Paul = John)]
[(Parent of Paul = John)]

Vitaly's feedback on Mattermost

Issue is on the DAS gate side. Variable's identity in hyperon-experimental consists of two parts: variable name and unique id. When DAS Gate converts variables to the DAS variables it merges these two parts into the the name like y#39. But when value is returned and should be applied to the template variable in template is not converted and has name y with 39 as unique id. Thus these two variables are not matched and value is not substituted. It is not a case for the simple query where variables doesn't have unique identifier.