5 ms·
>It seems there's no concrete example of where unstarred LET would be better. The unstarred let is a destructuring bind of an entire tuple. For example (let (
by dannymi 3y ago
>It seems there's no concrete example of where unstarred LET would be better.
The unstarred let is a destructuring bind of an entire tuple.
For example (let ((x 1) (y 2) (z 3)) ...) does the entirety of x := 1, y := 2, z := 3 at once, the right hand sides in the old frame and the left hand sides in the new frame.
So let introduces a new frame BUT only after all three substitutions are done.
For example in order to rotate x y z (from the surrounding frame) to the right:
(let ((y x) (z y) (x z))
...)
means:
((lambda (y z x)
...)
x y z)
For example:
(let ((x 1) (y 2) (z 3))
(let ((y x) (z y) (x z))
(list x y z)))
=> (3 1 2)
The starred let is the weird form. It's shorthand for having another let in the tail each time: With A, B, C each standing for a form:
(let* (A B C) ...) is defined to be (let (A) (let* (B C) ...). And so on. (let* (C) ...) is (let (C) ...), the base case.
(let* (A B C) ...) is (let (A) (let (B) (let (C) ...)))). Does that look natural to you?
(let (_) 5) is valid too.
>If a programmer ever falls in the habit of sometimes using unstarred LET, then it's likely he'll make a mistake by using it where starred LET* was the right thing.
Never happened to me so far and I'm using Lisp for 8 years now.
>It seems reasonable that when I write code, I shouldn't have to stop and worry about which of the gazillion different LET forms is appropriate
You do you, but you seem to think that this is an aesthetic choice rather than what the mathematics automatically gives. Lisp was not really designed, it was discovered. As long as you don't break any of the mathematical properties, go ahead and make it like you want it to be.
One thing you could safely do is remove the automatic tuple destructuring on let, basically removing the ability to have parallel-track bindings. Then you'd end up with something like Haskell:
main = let x = 1
y = 2
z = 3
in let y = x
z = y
x = z
in x
=> <<loop>>
- ogogmad 3y agoPython expresses destructuring bind using: x, y = foo, bar It occasionally comes in handy. It certainly does suggest there's compatibility with VAR syntax. Haskell's `do` notation also supports destructuring bind the Python way. It's even made into a special case of pattern matching. It also allows you to make declarations anywhere inside a block. This seems better than the Common Lisp approach.
- dannymi 3y ago> It[Python] certainly does suggest there's compatibility with VAR syntax. Maybe. Maybe not. >It[Haskell, or do notation] also allows you to make declarations anywhere inside a block. main = do let x = 1 let y = 2 let z = 3 let y = x z = y x = z print x => compilation error[1] Do you find that normal? How would you write what I wrote in Lisp in Haskell (for example using what you said)? Is it gonna need new concepts? Compare: main = do let x = 1 let y = 2 let z = 3 let y = x let z = y let x = z print [x, y, z] => [1, 1, 1] (as expected--but it's still dumb) [1] a.hs:9:5: error: • Ambiguous type variable ‘a0’ arising from a use of ‘print’ prevents the constraint ‘(Show a0)’ from being solved. Probable fix: use a type annotation to specify what ‘a0’ should be. These potential instances exist: instance Show Ordering -- Defined in ‘GHC.Show’ instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’ instance Show Integer -- Defined in ‘GHC.Show’ instance Show () -- Defined in ‘GHC.Show’ instance (Show a, Show b) => Show (a, b) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c) => Show (a, b, c) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d) => Show (a, b, c, d) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e) => Show (a, b, c, d, e) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e, Show f) => Show (a, b, c, d, e, f) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g) => Show (a, b, c, d, e, f, g) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h) => Show (a, b, c, d, e, f, g, h) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i) => Show (a, b, c, d, e, f, g, h, i) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j) => Show (a, b, c, d, e, f, g, h, i, j) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k) => Show (a, b, c, d, e, f, g, h, i, j, k) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l) => Show (a, b, c, d, e, f, g, h, i, j, k, l) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m) => Show (a, b, c, d, e, f, g, h, i, j, k, l, m) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m, Show n) => Show (a, b, c, d, e, f, g, h, i, j, k, l, m, n) -- Defined in ‘GHC.Show’ instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g, Show h, Show i, Show j, Show k, Show l, Show m, Show n, Show o) => Show (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) -- Defined in ‘GHC.Show’ instance Show a => Show (Solo a) -- Defined in ‘GHC.Show’ instance Show Bool -- Defined in ‘GHC.Show’ instance Show Char -- Defined in ‘GHC.Show’ instance Show Double -- Defined in ‘GHC.Float’ instance Show Float -- Defined in ‘GHC.Float’ instance Show Int -- Defined in ‘GHC.Show’ instance Show Word -- Defined in ‘GHC.Show’ instance Show a => Show [a] -- Defined in ‘GHC.Show’ ...plus 13 instances involving out-of-scope types instance Show GHC.Stack.Types.CallStack -- Defined in ‘GHC.Show’ instance Show GHC.Types.KindRep -- Defined in ‘GHC.Show’ instance Show GHC.Types.Levity -- Defined in ‘GHC.Show’ instance Show GHC.Types.Module -- Defined in ‘GHC.Show’ instance Show GHC.Num.Natural.Natural -- Defined in ‘GHC.Show’ instance Show a => Show (GHC.Base.NonEmpty a) -- Defined in ‘GHC.Show’ instance Show GHC.Types.RuntimeRep -- Defined in ‘GHC.Show’ instance Show GHC.Stack.Types.SrcLoc -- Defined in ‘GHC.Show’ instance Show GHC.Types.TrName -- Defined in ‘GHC.Show’ instance Show GHC.Types.TyCon -- Defined in ‘GHC.Show’ instance Show GHC.Types.TypeLitSort -- Defined in ‘GHC.Show’ instance Show GHC.Types.VecCount -- Defined in ‘GHC.Show’ instance Show GHC.Types.VecElem -- Defined in ‘GHC.Show’ • In a stmt of a 'do' block: print x In the expression: do let x = 1 let y = 2 let z = 3 let y = x z = y .... .... In an equation for ‘main’: main = do let x = ... let y = ... let z = ... .... | 9 | print x | ^^^^^ ^ Are you sure you want this in your language? :)