1

I'd like to use part to handle expressions of different length but have not been able to find anything in the documentation that addresses how to determine the number of parts of an expression.

I do have an upper bound for the number of parts so, in this particular case, I could loop over the terms until I get an error; however, I was wondering if there is a more direct method?

Rax Adaam
  • 790
  • 3
  • 11

1 Answers1

1

I can't believe this, but it appears length does the trick.

I assumed it was limited to lists because it returns an error for single numbers, because they are atoms. Apparently my brain decided "doesn't work with atoms" to mean "only work with lists."

However, this does mean that neither part nor length will work if the expression only has one part, so that case has to be handled separately.

I would still be interested in knowing if there is a solution that will work in all cases, so I won't mark this as the answer, just yet.

Rax Adaam
  • 790
  • 3
  • 11
  • 1
    There isn't a single `length`-like function to cover both atoms and nonatoms; the closest is to roll your own, something like `f(e) := if atom(e) then FOO else length(e)` where FOO represents whatever you expect for atoms, perhaps 0, anyway it depends on how you want stuff to work. But note that `length([])` is 0 and also `length(f())` is 0. So if you say that the length-like function of an atom is 0, then you can't distinguish atoms from empty, nonatomic expressions. I'm inclined to think doing that has the potential to cause confusion eventually. – Robert Dodier Feb 22 '21 at 16:30
  • 1
    Also, you mention `part`. I guess you are maybe trying to look at the arguments of an expression and figuring out what to do with it. A lot of that kind of stuff is implemented by the pattern matching functions (tellsimp / tellsimpafter / defrule / defmatch) and so if that's what you're doing, it might be clearer and simpler to use pattern matching, although pattern matching has its limitations, so sometimes there is no avoiding doing it by hand. – Robert Dodier Feb 22 '21 at 16:35
  • Thanks Robert -- in this case, I'm trying to call the terms of a polynomial whose length may vary (e.g. from 1 term to a max of ~8). I'm using these expressions to build the TeX output for general polynomial long-division (including colouring individual terms). I didn't think `args` would work for a polynomial, but just tested it & see that it does. Unfortunately, `args` has the same issue with atomic expressions, I believe. Spontaneously, I would've been inclined to define the "length" of an atomic expression as 1, not zero, but I imagine that has similar issues as what you described. – Rax Adaam Feb 22 '21 at 16:58
  • 1
    `op` and `args` work for all nonatomic expressions, as you have found. About `length()` equal to 1, then `length` doesn't distinguish `` from `[]` (i.e. a list of one element, namely ``). There is at least one other system which says, in effect, any `` is actually `()`, so that getting the operator gets `` and getting the argument gets `` itself. That's an interesting idea, but for better or worse Maxima distinguishes atoms and nonatoms. – Robert Dodier Feb 22 '21 at 17:28