It bug or feature
vlad-km opened this issue · comments
We are defined a function such that:
(defun bof (input bundle &optional hook)
(let (store fbundle)
(when bundle
(if hook
(setq store #())
(setq store #()))
(setq fbundle t))
(cond (fbundle
((jscl::oget store "push") input)
store)
(t store))))
Evaluated it
CL-USER> (bof 1 t)
#(1)
CL-USER> (bof 1 t)
#(1 1)
CL-USER> (bof 1 t)
#(1 1 1)
CL-USER> (bof 1 t)
#(1 1 1 1)
CL-USER> (bof 1 t)
#(1 1 1 1 1)
CL-USER> (bof 1 nil)
NIL
CL-USER> (bof 1 nil)
NIL
CL-USER> (bof 1 nil)
NIL
CL-USER> (bof 2 t)
#(1 1 1 1 1 2)
In my case, this is definitely a bug
.
But in another case, it may be useful.
And your opinion?
It depends what is the expectation! I assume you were surprised by the fact that it returns different values on each invocation? If it is so, I think it is correct.
For example, look at this:
(defun f () #())
(eq (f) (f)) ; => T
The same thing happens with quoted lists. It is different from calls to list
, for instance, in that case lists are created every time.
I am aware it can be confusing, but as far as I know this is the compliant behaviour with the standard, and what for example SBCL does. Note that you can create a new empty vector every time by using (vector)
instead of #()
.
David,
the main thing here is - that local variable store
maintains its state.
Higly likely it is not bug, but features.
I don't think the state remains in the variable, but the literal vector #()
as I described, which is mutated.
the truth is somewhere near.
but this is the source of errors for most
That's true. We can detect destructive operations on constant data as other implementations do already. For example, in SBCL
(defun f ()
(let ((x #(1)))
(incf (aref x 0))
x))
will complain with
; in: DEFUN F
; (INCF (AREF X 0))
; --> LET* FUNCALL SB-C::%FUNCALL
; ==>
; ((SETF AREF) #:NEW1 #:X0 0)
;
; caught WARNING:
; Destructive function (SETF AREF) called on constant data: #(1)
; See also:
; The ANSI Standard, Special Operator QUOTE
; The ANSI Standard, Section 3.2.2.3
;
; compilation unit finished
; caught 1 WARNING condition
WARNING: redefining COMMON-LISP-USER::F in DEFUN
and the mutation indeed is ignored at run-time. I was thinking we can us Object.freeze
to provide that protection for constant objects as well.
I created a new issue #350 to track this new proposed functionality. Closing this issue.