Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warn that let is complex in the manual #2590

Merged
merged 2 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions NEWS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ Removals
* `(fn/a …)` is now `(fn :async …)`.
* `(with/a […] …)` is now `(with [:async …] …)`.

* As with `for`, `:async` must precede each name to be bound
asynchronously, because you can mix synchronous and asynchronous
types.
* As with `for`, `:async` must precede each name to be bound
asynchronously, because you can mix synchronous and asynchronous
types.

* `(yield-from …)` is now `(yield :from …)`.

Expand Down
17 changes: 13 additions & 4 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,19 @@ Assignment, mutation, and annotation

.. hy:macro:: (let [bindings #* body])

``let`` creates local variables with lexically scoped names. This form takes a
list of binding pairs followed by a ``body`` which gets executed. A let-bound
name ceases to refer to that local outside the ``let`` form, but arguments in
nested functions, and bindings in nested ``let`` forms, can shadow these names. ::
``let`` is a macro for simulating traditional block scoping as seen in other
Lisps. Since it coexists with ordinary Python scoping, its consequences can
be complex, so it's wise to get a solid understanding of Python scoping
before you use it. Beginners to Python should note particularly that
:hy:func:`setv` inside a function or class typically creates a local
variable, so ``let`` isn't required for local variables or closures as it is
in many other Lisps.

That disclaimer aside, ``let`` creates local variables with lexically scoped
names. The macro takes a list of binding pairs followed by a ``body`` which
gets executed. A let-bound name ceases to refer to that local outside the
``let`` form, but arguments in nested functions, and bindings in nested
``let`` forms, can shadow these names. ::

(let [x 5 y 6] ; Create `x` and `y`
(print x y) ; => 5 6
Expand Down