Open DaddyWesker opened 4 months ago
Yes, case
doesn't reduce conditions, but with current implementation you can calculate the result of the condition in advance and then compare it with expected result. For instance following will work:
(= (check $x $y)
(case ($x (> $x $y)) (
((0 $_) 1)
(($_ True) $x)
($_ $y)
)))
Well, question was for general case and example was just to demonstrate my question. In general It could be needed to check several different conditions. Anyway, thanks for the answer.
In general It could be needed to check several different conditions.
I agree this approach is too verbose for many different conditions. You can also right your own case implementation:
(: my-case (-> %Undefined% Expression %Undefined%))
(= (my-case $x $conds)
(if (== $conds ())
(empty)
(let ($cond $templ) (car-atom $conds)
(let $tail (cdr-atom $conds)
(if $cond $templ (my-case $x $tail)) ))))
(= (check $x $y)
(my-case $x (
((== $x 0) 1)
((> $x $y) $x)
(True $y)
)))
But pay attention that check
also should be modified. In implementation from description unification pattern and boolean conditions are mixed in a list of conditions. To simplify implementation one need to choose either using unification (then use library case
) or conditioning (then use my-case
).
Yes, case
doesn't reduce conditions and works more like case
in functional languages, otherwise something like this would work
(= (check $x $y)
(case True
(((== 0 $x) 1)
((> $x $y) $x)
($_ $y))))
but it doesn't. This difference should be explained in a tutorial.
Another funny was would be to write:
(= (check $x $y)
(let $conds
(((== 0 $x) 1)
((> $x $y) $x)
($_ $y))
(case True $conds))
)
It seemingly works, but the difference with normal case
is that all the branches will be evaluated. It's not a tragedy for simple cases, but ruins the idea sequential mutually-exclusive evaluation in case
.
BTW, my guess is that in @vsbogd implementation (let $tail (cdr-atom $conds)
will also evaluate the whole tail. It may need a more careful consideration, but my first guess is that this
(= (my-case $x $conds)
(if (== $conds ())
(empty)
(let ($cond $templ) (car-atom $conds)
(if $cond
$templ
(let $tail (cdr-atom $conds) (my-case $x $tail)) ))))
will at least screen out evaluation of the tail if $cond
is true. Unfortunately, $templ
will be evaluated even if $cond
is false.
(let $tail (cdr-atom $conds) will also evaluate the whole tail.
Yes, unfortunately it is inevitable with current let
semantics. It can be eliminated in minimal MeTTa using chain
and eval
wisely though.
I've got some question regarding possibility to replace scheme's
cond
with metta'scase
. Is it possible? I've tried to write simple check function to see if my idea works:But apparently it doesn't work since, as i understand case, it will check not if $x larger than $y but instead if
(== $x (> $x $y))
(expression equality). Is there some way to write this code using case in current metta state? Or only consequent if's are usable in that case? @vsbogd @Necr0x0Der