1919 quicklambda as _quicklambda , f , _
2020from .letdo import do as _do , do0 as _do0 , local , \
2121 let as _let , letseq as _letseq , letrec as _letrec , \
22- let0 as _let0 , letseq0 as _letseq0 , letrec0 as _letrec0 , \
2322 dlet as _dlet , dletseq as _dletseq , dletrec as _dletrec , \
2423 blet as _blet , bletseq as _bletseq , bletrec as _bletrec
2524from .letsyntax import let_syntax_expr , let_syntax_block , block , expr
2625from .prefix import prefix as _prefix
2726from .tailtools import autoreturn as _autoreturn , tco as _tco , \
2827 continuations as _continuations , with_cc
2928
29+ from .util import UnexpandedLetView
3030from ..dynassign import dyn , make_dynvar
3131
3232from macropy .core .macros import Macros
@@ -160,16 +160,26 @@ def let(tree, args, *, gen_sym, **kw):
160160
161161 Usage::
162162
163- let(bindings )[body]
164- let(bindings )[[body0, ...]]
163+ let((k0, v0), ... )[body]
164+ let((k0, v0), ... )[[body0, ...]]
165165
166- where ``bindings`` is a comma-separated sequence of pairs ``(name, value)``
167- and ``body`` is an expression. The names bound by ``let`` are local;
166+ where ``body`` is an expression. The names bound by ``let`` are local;
168167 they are available in ``body``, and do not exist outside ``body``.
169168
170- For a body with multiple expressions, use an extra set of brackets.
171- This inserts a ``do``. Only the outermost extra brackets are interpreted
172- specially; all others in the bodies are interpreted as usual, as lists.
169+ Alternative haskelly syntax is also available::
170+
171+ let[((k0, v0), ...) in body]
172+ let[((k0, v0), ...) in [body0, ...]]
173+ let[body, where((k0, v0), ...)]
174+ let[[body0, ...], where((k0, v0), ...)]
175+
176+ For a body with multiple expressions, use an extra set of brackets,
177+ as shown above. This inserts a ``do``. Only the outermost extra brackets
178+ are interpreted specially; all others in the bodies are interpreted
179+ as usual, as lists.
180+
181+ Note that in the haskelly syntax, the extra brackets for a multi-expression
182+ body should enclose only the ``body`` part.
173183
174184 Each ``name`` in the same ``let`` must be unique.
175185
@@ -199,7 +209,7 @@ def let(tree, args, *, gen_sym, **kw):
199209 is applied first to ``[body0, ...]``, and the result becomes ``body``.
200210 """
201211 with dyn .let (gen_sym = gen_sym ):
202- return _let ( bindings = args , body = tree )
212+ return _destructure_and_apply_let ( tree , args , _let )
203213
204214@macros .expr
205215def letseq (tree , args , * , gen_sym , ** kw ):
@@ -211,7 +221,7 @@ def letseq(tree, args, *, gen_sym, **kw):
211221 Expands to nested ``let`` expressions.
212222 """
213223 with dyn .let (gen_sym = gen_sym ):
214- return _letseq ( bindings = args , body = tree )
224+ return _destructure_and_apply_let ( tree , args , _letseq )
215225
216226@macros .expr
217227def letrec (tree , args , * , gen_sym , ** kw ):
@@ -228,55 +238,14 @@ def letrec(tree, args, *, gen_sym, **kw):
228238 This is useful for locally defining mutually recursive functions.
229239 """
230240 with dyn .let (gen_sym = gen_sym ):
231- return _letrec (bindings = args , body = tree )
232-
233- # -----------------------------------------------------------------------------
234- # Inverted let, for situations where a body-first style improves readability.
235-
236- @macros .expr
237- def let0 (tree , * , gen_sym , ** kw ):
238- """[syntax, expr] Inverted let.
239-
240- Because sometimes it is more readable to give the body first.
241-
242- Usage::
243-
244- let0[body, where((k0, v0), ...)]
245- let0[[body0, ...], where((k0, v0), ...)]
246-
247- The ``where`` is literal.
248-
249- Use extra brackets around the body (only) for multiple-expression mode
250- (a.k.a. implicit ``do[]``).
251-
252- Inspired by Haskell's ``where``; this format is also common in mathematics.
253- """
254- with dyn .let (gen_sym = gen_sym ):
255- return _let0 (tree )
256-
257- @macros .expr
258- def letseq0 (tree , * , gen_sym , ** kw ):
259- """[syntax, expr] Inverted letseq.
260-
261- Usage::
262-
263- letseq0[body, where((k0, v0), ...)]
264- letseq0[[body0, ...], where((k0, v0), ...)]
265- """
266- with dyn .let (gen_sym = gen_sym ):
267- return _letseq0 (tree )
268-
269- @macros .expr
270- def letrec0 (tree , * , gen_sym , ** kw ):
271- """[syntax, expr] Inverted letrec.
272-
273- Usage::
274-
275- letrec0[body, where((k0, v0), ...)]
276- letrec0[[body0, ...], where((k0, v0), ...)]
277- """
278- with dyn .let (gen_sym = gen_sym ):
279- return _letrec0 (tree )
241+ return _destructure_and_apply_let (tree , args , _letrec )
242+
243+ def _destructure_and_apply_let (tree , args , expander ):
244+ if args :
245+ return expander (bindings = args , body = tree )
246+ # haskelly syntax
247+ view = UnexpandedLetView (tree ) # note this gets only the part inside the brackets
248+ return expander (bindings = view .bindings , body = view .body )
280249
281250# -----------------------------------------------------------------------------
282251# Decorator versions, for "let over def".
0 commit comments