back let
with dict for better defclass behavior
This commit is contained in:
parent
3707681056
commit
e90f082baf
@ -224,10 +224,6 @@ Arguments in nested functions and bindings in nested ``let`` forms can shadow th
|
|||||||
6
|
6
|
||||||
5
|
5
|
||||||
|
|
||||||
The ``global`` special form changes the meaning of names to refer to the
|
|
||||||
module-level variables instead of locals, and this change still applies inside a ``let`` form,
|
|
||||||
even if a global has the same name as a let binding.
|
|
||||||
|
|
||||||
Basic assignments (e.g. ``setv``, ``+=``) will update the local variable named by a let binding,
|
Basic assignments (e.g. ``setv``, ``+=``) will update the local variable named by a let binding,
|
||||||
when they assign to a let-bound name.
|
when they assign to a let-bound name.
|
||||||
|
|
||||||
@ -238,9 +234,6 @@ even if it shares the name of a let binding.
|
|||||||
Use ``__import__`` and ``type`` (or whatever metaclass) instead,
|
Use ``__import__`` and ``type`` (or whatever metaclass) instead,
|
||||||
if you must avoid this hoisting.
|
if you must avoid this hoisting.
|
||||||
|
|
||||||
When used in a nested function,
|
|
||||||
nonlocal assignments to let-bound variables still require a ``nonlocal`` form.
|
|
||||||
|
|
||||||
The ``let`` macro takes two parameters: a list defining *variables*
|
The ``let`` macro takes two parameters: a list defining *variables*
|
||||||
and the *body* which gets executed. *variables* is a vector of
|
and the *body* which gets executed. *variables* is a vector of
|
||||||
variable and value pairs.
|
variable and value pairs.
|
||||||
@ -254,4 +247,4 @@ variable and value pairs.
|
|||||||
... (print x y))
|
... (print x y))
|
||||||
5 6
|
5 6
|
||||||
|
|
||||||
|
It is an error to use a let-bound name in a ``global`` or ``nonlocal`` form.
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
(expand form))
|
(expand form))
|
||||||
|
|
||||||
;; TODO: move to hy.extra.reserved?
|
;; TODO: move to hy.extra.reserved?
|
||||||
|
(import hy)
|
||||||
(setv special-forms (list-comp k
|
(setv special-forms (list-comp k
|
||||||
[k (.keys hy.compiler._compile-table)]
|
[k (.keys hy.compiler._compile-table)]
|
||||||
(isinstance k hy._compat.string-types)))
|
(isinstance k hy._compat.string-types)))
|
||||||
@ -246,10 +247,9 @@ Arguments without a header are under None.
|
|||||||
(defn handle-call [self]
|
(defn handle-call [self]
|
||||||
(setv head (first self.form))
|
(setv head (first self.form))
|
||||||
(if (in head '[fn fn*]) (self.handle-fn)
|
(if (in head '[fn fn*]) (self.handle-fn)
|
||||||
(in head '[import quote]) (self.handle-base)
|
(in head '[import require quote]) (self.handle-base)
|
||||||
(= head 'except) (self.handle-except)
|
(= head 'except) (self.handle-except)
|
||||||
(= head ".") (self.handle-dot)
|
(= head ".") (self.handle-dot)
|
||||||
(= head 'global) (self.handle-global)
|
|
||||||
(= head 'defclass) (self.handle-defclass)
|
(= head 'defclass) (self.handle-defclass)
|
||||||
(= head 'quasiquote) (self.+quote)
|
(= head 'quasiquote) (self.+quote)
|
||||||
;; must be checked last!
|
;; must be checked last!
|
||||||
@ -320,9 +320,10 @@ as can nested let forms.
|
|||||||
(if (in '. k)
|
(if (in '. k)
|
||||||
(macro-error k "binding target may not contain a dot")))
|
(macro-error k "binding target may not contain a dot")))
|
||||||
(.append values (symbolexpand (macroexpand-all v &name) expander))
|
(.append values (symbolexpand (macroexpand-all v &name) expander))
|
||||||
(assoc replacements k (HySymbol (+ g!let "::" k))))
|
(assoc replacements k `(get ~g!let ~(name k))))
|
||||||
`(do
|
`(do
|
||||||
(setv ~@(interleave (.values replacements) values))
|
(setv ~g!let {}
|
||||||
|
~@(interleave (.values replacements) values))
|
||||||
~@(symbolexpand (macroexpand-all body &name) expander)))
|
~@(symbolexpand (macroexpand-all body &name) expander)))
|
||||||
|
|
||||||
;; (defmacro macrolet [])
|
;; (defmacro macrolet [])
|
||||||
|
@ -158,8 +158,8 @@
|
|||||||
(do
|
(do
|
||||||
foo
|
foo
|
||||||
(assert False))
|
(assert False))
|
||||||
(except [ne NameError]
|
(except [le LookupError]
|
||||||
(setv error ne)))
|
(setv error le)))
|
||||||
(setv foo 16)
|
(setv foo 16)
|
||||||
(assert (= foo 16))
|
(assert (= foo 16))
|
||||||
(setv [foo bar baz] [1 2 3])
|
(setv [foo bar baz] [1 2 3])
|
||||||
@ -217,7 +217,10 @@
|
|||||||
;; the name of the class is just a symbol, even if it's a let binding
|
;; the name of the class is just a symbol, even if it's a let binding
|
||||||
(defclass Foo [quux] ; let bindings apply in inheritance list
|
(defclass Foo [quux] ; let bindings apply in inheritance list
|
||||||
;; let bindings apply inside class body
|
;; let bindings apply inside class body
|
||||||
(setv x Foo)))
|
(setv x Foo)
|
||||||
|
;; quux is not local
|
||||||
|
(setv quux "quux"))
|
||||||
|
(assert (= quux "quux")))
|
||||||
;; defclass always creates a python-scoped variable, even if it's a let binding name
|
;; defclass always creates a python-scoped variable, even if it's a let binding name
|
||||||
(assert (= Foo.x 42)))
|
(assert (= Foo.x 42)))
|
||||||
|
|
||||||
@ -307,33 +310,15 @@
|
|||||||
(, 1 6 2)))))
|
(, 1 6 2)))))
|
||||||
|
|
||||||
(defn test-let-closure []
|
(defn test-let-closure []
|
||||||
(let [count [0]]
|
(let [count 0]
|
||||||
(defn +count [&optional [x 1]]
|
(defn +count [&optional [x 1]]
|
||||||
(+= (get count 0) x)
|
(+= count x)
|
||||||
(get count 0)))
|
count))
|
||||||
;; let bindings can still exist outside of a let body
|
;; let bindings can still exist outside of a let body
|
||||||
(assert (= 1 (+count)))
|
(assert (= 1 (+count)))
|
||||||
(assert (= 2 (+count)))
|
(assert (= 2 (+count)))
|
||||||
(assert (= 42 (+count 40))))
|
(assert (= 42 (+count 40))))
|
||||||
|
|
||||||
(defn test-let-global []
|
|
||||||
(setv (get (globals)
|
|
||||||
'let-global)
|
|
||||||
"global")
|
|
||||||
(let [let-global 1]
|
|
||||||
(assert (= let-global 1))
|
|
||||||
(defn foo []
|
|
||||||
(assert (= let-global 1))
|
|
||||||
(global let-global)
|
|
||||||
(assert (= let-global "global"))
|
|
||||||
(setv let-global "mutated")
|
|
||||||
(assert (= let-global "mutated")))
|
|
||||||
(foo)
|
|
||||||
(assert (= let-global 1))
|
|
||||||
(assert (= (get (globals)
|
|
||||||
'let-global)
|
|
||||||
"mutated"))))
|
|
||||||
|
|
||||||
(defmacro triple [a]
|
(defmacro triple [a]
|
||||||
(setv g!a (gensym a))
|
(setv g!a (gensym a))
|
||||||
`(do
|
`(do
|
||||||
@ -353,4 +338,3 @@
|
|||||||
3))
|
3))
|
||||||
(assert (= b 3))
|
(assert (= b 3))
|
||||||
(assert (= c 3))))
|
(assert (= c 3))))
|
||||||
|
|
||||||
|
@ -72,19 +72,6 @@
|
|||||||
(assert (= (list (yield-from-test)) [0 1 2 1 2 3 4])))
|
(assert (= (list (yield-from-test)) [0 1 2 1 2 3 4])))
|
||||||
|
|
||||||
(require [hy.contrib.walk [let]])
|
(require [hy.contrib.walk [let]])
|
||||||
(defn test-let-nonlocal []
|
|
||||||
(let [a 88
|
|
||||||
c 64]
|
|
||||||
(defn foo [a b]
|
|
||||||
(nonlocal c)
|
|
||||||
(-= a 1)
|
|
||||||
(-= c 1)
|
|
||||||
(, a b c))
|
|
||||||
(assert (= a 88))
|
|
||||||
(assert (= (foo 1 2)
|
|
||||||
(, 0 2 63)))
|
|
||||||
(assert (= c 63))
|
|
||||||
(assert (= a 88))))
|
|
||||||
|
|
||||||
(defn test-let-optional []
|
(defn test-let-optional []
|
||||||
(let [a 1
|
(let [a 1
|
||||||
|
Loading…
Reference in New Issue
Block a user