freenode/#lisp - IRC Chatlog
Search
17:48:57
mseddon
hmm, how can I add a new, completely empty dispatching macro character according to the ANSI spec from a virgin lisp world? It seems to me that I'd have to first (set-syntax-from-char #\# #\PlaceholderCharacter), and then remove all the dispatch macro characters that are default, but that is silly.
18:01:55
aeth
pve: one refactoring pitfall is that you could be calling a stale version of a function after you rename it because the old function object at the old name will still exist, even if you rename and start redefining parts of the new one. So you could accidentally have two bugs (mistaken refactoring of the function that doesn't preserve behavior that isn't detected yet, and calling the old function that still behaves the old way until you rest
18:03:18
aeth
pve: e.g. (defun foobar (x) (1+ x)) then rename it to (defun foo (x) (+ 2 x)) but if you forget to change the caller, you (1) won't get any errors until you restart since the old #'foobar still exists and (2) won't notice that you're adding two instead of 1 in your refactor until you fix this first problem
18:03:46
aeth
(obviously, with such a trivial example, it's clear FOOBAR and FOO do different things)
18:06:51
aeth
You can hopefully catch this if you restart your Lisp (e.g. for slime M-x slime-restart-inferior-lisp) and quickload with :verbose t (which unfortunately is quite verbose) to see errors/warnings/etc. (I think calling an undefined function is a warning in SBCL, but it might be a style warning.)
18:09:19
aeth
I personally do (ql:quickload :uiop) (ql:quickload :foo :verbose t) because UIOP is very noisy in SBCL because quickloading it redefines every single function (to upgrade from the built-in UIOP to the latest)
18:21:14
jackdaniel
not the best solution, because 1. foo could have been inlined, 2. further redefinitions will require "remembering" the old name to change a definition
18:22:01
jackdaniel
so maybe (setf (fdefinition 'foo) (lambda (&rest args) (warn "foo called") (apply #'foobar args)))
18:22:41
aeth
yes, but quickloading with :verbose t will warn you when foo is called at quickload time, if the implementation warns on undefined functions
18:38:18
pve
aeth: I've been hit by that so many times I now run my tests in a loop in a shell in a fresh image
18:47:00
pve
although the project I'm thinking of refactoring is decently sized so I'm not sure how well the "clean compile + test" loop would work in practice
19:59:59
aeth
I set a rule for myself that I must M-x s-r-i-lisp and quickload verbosely and run any unit tests (if there are any) before pushing to the git origin. And on a few of the occasions where I've broken this rule, I've pushed broken builds. Now, of course, this won't catch every refactoring error, but it will catch the ones that the CI process will also catch.
20:00:04
aeth
But jackdaniel pointed out some other solutions that will address this particular issue without restarting... Although, I think maybe uninterning so it shows up as an undefined function and requickloading might work. Maybe.
20:00:48
aeth
I'm not sure if there's a way to detect stale macros and inline functions in the callers of something that has now been redefined.
20:02:16
aeth
I think in general, if you think inlining/macros are involved, you probably should requickload and hopefully ASDF handles the redefinitions properly, at least if you redefined via changing the source rather than directly in the REPL
20:07:10
aeth
For refactoring, there are two complicating factors that I'm aware of if you want to redefine things. Redefining packages (e.g. no longer importing something that used to be imported; adding imports is fine) and redefining structs (afaik this is because accessors might be optimized, so the inlining problem comes up again). These are the ones that SBCL sort of complains about. There might be others that are permitted by the standard.
20:08:25
aeth
And on implementations complaining about something, you have to test in CCL after refactoring because a lot of refactoring is doing things like moving things into constants, and CCL is picky about when its constants are evaluated, requiring you to EVAL-WHEN some DEFCONSTANTs.
20:21:23
pve
aeth: I'm ashamed to admit I restart my repl probably more often than most, I even have a key bound to starting a new repl and loading a session file
20:22:27
aeth
This is why I find it amusing when people don't think about the necessity of inferior-lisps in their CL Emacs clone designs. Nope, you'd still need one.
20:23:25
pve
and I often have this tool running in the background: https://github.com/pve1/system-watcher
20:27:39
aeth
I save practically every keystroke, and tests could take up to minutes. They probably all should, but I don't test enough.
20:29:48
pve
hmm yeah I save all the time too, and the feedback isn't instantaneous if there's lots of tests, but saving a file won't interrupt an already started test run