alphapapa / org-super-agenda

Supercharge your Org daily/weekly agenda by grouping items
GNU General Public License v3.0
1.33k stars 107 forks source link

Grouping by curried predicates? #185

Open jcguu95 opened 3 years ago

jcguu95 commented 3 years ago

Does the grouping method by predicate supports curried functions? I couldn't make it work.. perhaps it's because it does not support byte-compiled function well? Below is a minimal example.

Setup

(defun foo (x y)
  "All true."
  (lambda () t))

Case one

(setq org-super-agenda-groups
      '((:name "All"
         :pred (apply-partially #'foo nil))))

Error:

Debugger entered--Lisp error: (error "No clause matching ‘function’")
  signal(error ("No clause matching ‘function’"))
  error("No clause matching `%S'" function)
  #f(compiled-function (arg) #<bytecode 0x15797acaca61>)(function)
  mapcar(#f(compiled-function (arg) #<bytecode 0x15797acaca61>) #'foo)
  -map(#f(compiled-function (arg) #<bytecode 0x15797acaca61>) #'foo)
  #f(compiled-function (arg) #<bytecode 0x15797acaca61>)(#'foo)
  mapcar(#f(compiled-function (arg) #<bytecode 0x15797acaca61>) (apply-partially #'foo nil))
  -map(#f(compiled-function (arg) #<bytecode 0x15797acaca61>) (apply-partially #'foo nil))
  #f(compiled-function (arg) #<bytecode 0x15797acaca61>)((apply-partially #'foo nil))
  org-super-agenda--group-pred [..]
  org-super-agenda--group-dispatch [..]
  org-super-agenda--group-items [..]
  org-super-agenda--filter-finalize-entries [..]
  org-agenda-finalize-entries [..]
  org-agenda-list(nil "-7d" 1)

Case two

(setq org-super-agenda-groups
      `((:name "All"
         :pred ,(apply-partially #'foo nil))))

; ERROR: Wrong type argument: symbolp, #[128 "ÂÀÃÁ\"\"‡"
[foo (nil) apply append] 6 "

Case three

(setq org-super-agenda-groups
      `((:name "All"
         :pred #',(apply-partially 'foo nil))))

; ERROR: No clause matching ‘function’
alphapapa commented 3 years ago

The test in question is here: https://github.com/alphapapa/org-super-agenda/blob/f5e80e4d0da6b2eeda9ba21e021838fa6a495376/org-super-agenda.el#L664

alphapapa commented 3 years ago

Actually, I think it's hitting this test first: https://github.com/alphapapa/org-super-agenda/blob/f5e80e4d0da6b2eeda9ba21e021838fa6a495376/org-super-agenda.el#L658

jcguu95 commented 3 years ago

Yeah.. there's a comment in the source that reads

                                                   ;; FIXME: What if the lambda's byte-compiled?

Do you by any chance remember what it means?

My elisp fu is pretty noobie, but if you'd point out that it's doable in the current setting, I will try my best to learn and make it work. In any case, thanks so much (and happy holiday if there's any :smiley: )

alphapapa commented 3 years ago

Well, it means what it says. :) IOW, at the time I wrote it, I considered that it might be a problem if the function is byte-compiled, and it turns out that it can be.

And it so happens that apply-partially sometimes (or always?) returns a byte-compiled function (although I don't know why, from looking at its code). So that code in org-super-agenda needs to be modified to handle those cases. You can see in the backtrace the line of code that signaled an error, then find that code in this package, and make the necessary changes.

For example, one of the errors is because symbol-name is called on a byte-compiled function, which isn't a symbol, so it signals an error.

Thanks, and Merry Christmas to you.

jcguu95 commented 3 years ago

This is the source of apply-partially that I got from counsel-find-function

(defun apply-partially (fun &rest args)
  "Return a function that is a partial application of FUN to ARGS.
ARGS is a list of the first N arguments to pass to FUN.
The result is a new function which does the same as FUN, except that
the first N arguments are fixed at the values with which this function
was called."
  (lambda (&rest args2)
    (apply fun (append args args2))))

Now, with emacs freshly loaded,

(defun foo (x y) t)
(apply-partially 'foo nil)

returns a byte-compiled function as I evaluated by C-x C-e. However, after evaluating the given definition of apply-partially again, it did not. So I suppose emacs secretly did something over it..


About the symbol-name error.. is it because that if I choose to use a single function (instead of a list of functions), symbol-name is called in (https://github.com/alphapapa/org-super-agenda/blob/f5e80e4d0da6b2eeda9ba21e021838fa6a495376/org-super-agenda.el#L661), and so I need to relax it for it to work?

alphapapa commented 3 years ago

returns a byte-compiled function as I evaluated by C-x C-e. However, after evaluating the given definition of apply-partially again, it did not. So I suppose emacs secretly did something over it..

I guess when apply-partially is byte-compiled, the lambdas it returns are also byte-compiled. Good to know.

About the symbol-name error..

Yes, because a byte-compiled function is not a symbol, and symbol-name only works on symbols.

alphapapa commented 3 weeks ago

I think it's impractical to derive a textual description of a predicate function for use in the section name this way (especially given recent changes in Emacs's internal function representations). So probably we should use a user-supplied section name if given, or otherwise just say something like "[predicate]".

This would be a bit more than a simple bug fix but more like a change in functionality, so retargeting for v1.4.