0

I'm trying to parse the output of ledger-context-at-point for the account name. The output looks something like:

  (acct-transaction
   account
   ((indent "   " 238117)
    (status nil nil)
    (account "asset:checking" 238121)))

I want "asset:checking".

I can get it by

(cadr (assq 'account (nth 2 

  ;; (ledger-context-at-point)                         
  (quote
    (acct-transaction
     account
     ((indent "   " 238117)
      (status nil nil)
      (account "asset:checking" 238121)))

  ))))

or by

(cadadr (cdaddr
 
  ;; (ledger-context-at-point)                         
  (quote
    (acct-transaction
     account
     ((indent "   " 238117)
      (status nil nil)
      (account "asset:checking" 238121)))


 )))

I would have expected a simple structure, like an alist or plist. Does this data structure follow a different idiom? Is there a conventional way to get at the list elements like these?

4
  • Define "elegant". This solicits opinion-based answers. Different styles can be useful for different purposes, and different people find different styles better or worse. This kind of question is not a specific "how to" question. You might try a discussion forum such as Reddit for this kind of question. – Drew Dec 6 '20 at 23:21
  • Good point. I have updated the question. – Lorem Ipsum Dec 7 '20 at 1:33
  • 1
    The structure is no doubt defined for other purposes than just your ease in extracting "asset-checking". To find out why the structure is as it is, you'll likely need to read the code that uses it or any associated doc. And there's no one conventional way to get at list elements (which in this case means a particular element of a list embedded within other lists). If access of things like "asset-checking" is frequent, and especially if it corresponds to something that naturally has a useful name, then more "elegant" code might have defined an accessor function or macro for that. – Drew Dec 7 '20 at 2:32
  • @Drew, thank you. You helped bring clarity to me. I have tried to update the question in a way which may be helpful to others. If it's still too broad, I understand, and we should probably close it. – Lorem Ipsum Dec 7 '20 at 3:39
1

Per @Drew's prompting and some poking around, I see within ledger-context.el the following definitions:

(defun ledger-context-field-info (context-info field-name)
  (assoc field-name (nth 2 context-info)))

(defun ledger-context-field-value (context-info field-name)
  (nth 1 (ledger-context-field-info context-info field-name)))

This corresponds, more or less, to the approaches given in the question (with the exception of assoc instead of assq).

The idiom, if it can be called that, is to compose simpler components into an expressive language tailored to the problem domain. The list accessor functions assoc, assq, nth, car, etc., are building blocks. As a developer, defining a function such as ledger-context-field-value may carry more meaning for users than (cadadr (cdaddr .. )).

To wit, which do you prefer,

(ledger-context-field-value (ledger-context-at-point) 'account)

;; vs

(cadadr (cdaddr (ledger-context-at-point)))

The ledger developers have decided the former to be the "conventional" way to get at the list elements like these. You can decide which you prefer (or find another).

If you encounter an unusual data structure, search for accessors defined elsewhere. There may not be a clear reason why data is the way it is, but such accessors can give you confidence in how to use it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.