> > I'm not suggesting to implement > `abbrev-get-active-expansions` differently. > I'm suggesting to implement something else. I.e. > > (defmacro abbrev-do-active-expansions (VAR &rest BODY) > "Bind VAR to an active expansion and run BODY with it. > Repeat it for all active expansions." > ...) > > or > > (defun abbrev-mapc-active-expansions (FUNC) > "Call FUNC on each active expansion." > > This way you don't need to build a list of active expansions: you run > FUNC or BODY on each expansion when you encounter it. > Ah, of course, got it now! :) I tried a few versions of this now. I need to go through the complete list of active abbrevs/expansions since I want to find one that is valid and I also want to find the "best" one (according to what we discussed before). I defined 10,000 dummy abbrevs (a1 .. a10000) and used the profiler to compare memory usage and... I did not get any conclusive results. And between runs I get different memory values reported. If I can draw any conclusions at all it would be that the old version (that used another function to get the active abbrevs) and the new one (that does what needs to be done while collecting the active abbrevs) are more or less the same, from the perspective on memory consumption. Here is the original version, slightly modified. I added a new cache to make the abbrev-suggest-expansion-exist-at-point function not have to call buffer-substring for a certain length many times. (defun abbrev-suggest () "Suggest an abbrev to the user based on the text before point. Uses `abbrev-suggest-hint-threshold' to find out if the user should be informed about the existing abbrev." (interactive) (abbrev-suggest-previous-chars-clear) (let (abbrev-found) (dolist (expansion (abbrev-get-active-expansions)) (when (and (abbrev-suggest-above-threshold expansion) (abbrev-suggest-expansion-exist-at-point expansion)) (setq abbrev-found (abbrev-suggest-best-abbrev expansion abbrev-found)))) (when abbrev-found (abbrev-suggest-inform-user abbrev-found)))) One of the profiler runs: Function Bytes % - command-execute 6,191,706 99% - call-interactively 6,191,706 99% - funcall-interactively 6,191,706 99% + profiler-stop 3,178,331 51% - abbrev-suggest 3,012,912 48% - let 3,012,912 48% - let 3,012,760 48% - while 2,046,520 33% - let 1,704,376 27% - if 1,704,376 27% - and 1,704,376 27% - abbrev-suggest-expansion-exist-at-point 1,023,256 16% - string= 1,023,256 16% - abbrev-suggest-previous-chars 682,168 11% + let 1,048 0% - abbrev-get-active-expansions 966,240 15% - let 966,240 15% - let 966,240 15% - while 966,240 15% - let 966,240 15% - mapatoms 966,240 15% - # 870,144 14% - let 771,936 12% - symbol-value 675,840 10% - abbrev--symbol 483,648 7% + let* 289,344 4% + if 96,096 1% + if 152 0% Here is the new version: (defun abbrev-suggest () "Suggest an abbrev to the user based on the text before point. Uses `abbrev-suggest-hint-threshold' to find out if the user should be informed about the existing abbrev." (interactive) (abbrev-suggest-previous-chars-clear) (let (best-abbrev) (dolist (table (abbrev--active-tables-including-parents)) (mapatoms (lambda (e) (let ((value (symbol-value (abbrev--symbol e table))) abbrev) (when value (setq abbrev (cons value (symbol-name e))) (when (and (abbrev-suggest-above-threshold abbrev) (abbrev-suggest-expansion-exist-at-point abbrev)) (setq best-abbrev (abbrev-suggest-best-abbrev abbrev best-abbrev)))))) table)) (when best-abbrev (abbrev-suggest-inform-user best-abbrev)))) Here is a run with the profiler of the above: Function Bytes % - command-execute 4,996,751 99% - call-interactively 4,996,751 99% - funcall-interactively 4,996,751 99% + profiler-stop 3,179,816 63% - abbrev-suggest 1,816,472 36% - let 1,816,472 36% - let 1,815,264 36% - while 1,815,264 36% - let 1,815,264 36% - mapatoms 1,815,264 36% - # 1,815,264 36% - let 284,064 5% - if 284,064 5% - progn 284,064 5% setq 284,064 5% + if 1,208 0% profiler-start 463 0% Are these numbers as expected? Sometimes, all of a sudden, regardless of what version of the function I use, the memory consumed by abbrev-suggest can be as low as 80,000 bytes. What have happened then? Something the GC does? Thanks! /Mathias