jscl-project / jscl

A Lisp-to-JavaScript compiler bootstrapped from Common Lisp

Home Page:https://jscl-project.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

It bug or feature

vlad-km opened this issue · comments

commented

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 #().

commented

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.

commented

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.