Skip to content

Semantics of+= and the like #1610

@z-rui

Description

@z-rui

In the documentation of +=, it's unspecified whether x is evaluated once or twice:

    (+= x & ns)

    Increments the var x by n.

Although for *=, it seems to imply that x is evaluated twice:

    (*= x & ns)

    Shorthand for (set x (* x n)).

Because x may be an indexing expression, this can sometimes cause problems, like doubling the side effect or inefficient bytecode. E.g.,

(+= (x (inc i)) 42)

Here inc will be called twice.

Would it be more reasonable to change/clarify the spec so that the lvalue is only evaluated once? This matches the expectation from most users, and aligns with other languages that have this kind of shorthand. I think it can be achieved by defining those macros as

(defn- op-assign-temlate [op x & ys]
  (match x
    [ds i] (with-syms [DS I]
             ~(let [,DS ,ds ,I ,i]
                (set (,DS ,I) (,op (,DS ,I) ,;ys))))
    ~(set ,x (,op ,x ,;ys))))

(defmacro += [x & ys] (op-assign-temlate + x ;ys))
# etc.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions