From: Bruno H. <br...@cl...> - 2017-07-20 17:08:29
|
Daniel wrote: > Note that this may lead to situations where loading the exact same code > will lead to different results, depending on previous definitions: a GF > without any declare expression would be dynamically modifiable depending on > whether there was a previous definition. Well explained. 100% agree. Sam wrote: > This is already the case. > If you have a file with > > (defun f (x) (lambda () (print x))) > (funcall (f 10)) > > then loading it will print 10. > If, however, you evaluate (defparameter x 100) before loading it, it > will print 100. This is precisely why DEFPARAMETER and DEFVAR are considered a problem in the CL language. The usual workaround is to separate the sets of symbols into two classes: those to which DEFPARAMETER and DEFVAR may be applied (those whose print name starts and ends with a * or + character) and those which, by convention (!), will not be subject to DEFPARAMETER or DEFVAR. Remember that this is merely a workaround to an ill design. It is not necessary to copy this ill design pattern to new areas, like generic functions. So, please, forget about DECLAIM here. > Then it will not be possible to change the dynamically-modifiable status > of a GF without redefining it. This is not a problem. The usual way of developing in any programming language, nowadays, is - to store the definitions in text files, - when making a change: change the file then LOAD it. The approach of InterLisp (change programs on-the-fly, in memory) became obsolete when the edit-file--reload--retry cycle became efficient enough. When you use closures e.g. (let ((balance 0)) (defun add (x) (incf balance x))) you cannot change the value of BALANCE, nor redefine ADD, without reloading the file. Yet this is considered completely normal programming style. Bruno |