Hi,
I want to check whether a given part of an expression exists, e.g., to
determine whether a list is empty or not, and I suspect I am missing
something obvious:
Setting PARTSWITCH to TRUE and checking whether INPART(expr,1) returns
END would seem like a convenient way to get the answer, but this does
not work in the presence of a literal END:
,----
| (C52) block([partswitch: true], inpart(1,1));
|
| (D52) END
| (C53) block([partswitch: true], inpart([end],1));
|
| (D53) END
| (C54) block([partswitch: true], is(equal(inpart(1,1), inpart([end],1))));
|
| (D54) TRUE
`----
The only reliable ways I can see are:
- checking length(errcatch(inpart(expr,...))) = 1, but that gives me
annoying messages like ``INPART called on atom: 1'';
- the simple-minded check length(expr) >= ... (taking care of INFLAG),
which seems like it would waste a lot of effort when the length of
expr is much longer than the index to be checked, and checking for
part(expr, 1,2,3...) would be cumbersome at least.
When it is only the first part one is interested in, the clumsy
not(symbol(expr)) and
(catch (block([n], for n in expr do throw(true), false)))
seems to work perfectly, but part(expr, 3) or part(expr, 1,2,3) would
be cumbersome again.
Just in case I am not missing something obvious, I think that a
slightly different behavior of PART and INPART might help with this:
If the requested part is not found,
- if PARTSWITCH is FALSE, error out as now,
- if PARTSWITCH is TRUE, return END as now for compatibility,
- otherwise, return the value of PARTSWITCH.
In that case, a macro like
buidq([gs: ?gensym()],
block([partswitch: gs], is(equal(gs, part(...)))))
should do the job.
Albert.