News for hackers. Stuff that matters.
Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by Joker_vD on Tuesday April 09, 2024 @03:06AM (#39976844)
I really wonder what "more sane" languages you mean. Because a single [] does give you an empty list value in Python: one list, and not four different empty lists. Why would it give your four? That'd need to somehow bring in the surrounding context and in "sane" languages, (closed) expressions generally don't change the meaning because the context around them is changing.

Actually, if you really want to have re-evaluting (sub)expressions, then Python does give you an option: comprehensions.

Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by bmitc on Tuesday April 09, 2024 @03:17AM (#39976908)
F#:

    List.init 4 (fun _ -> [])

    [for _ in 1..4 -> []]
Or any sane language that uses immutable values by default like Elixir, Erlang, Clojure, Racket, Scheme, OCaml, etc.

> Actually, if you really want to have re-evaluting (sub)expressions, then Python does give you an option: comprehensions.

That's the complaint, that [[]]*4 is not shorthand for list comprehensions and that it's something entirely different. This is common in Python where two things you'd expect to be the same are indeed different in subtle ways.

List comprehensions in Python are closer to sane, but they still have unexpected behavior because of the way scoping works in Python.

Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by dragonwriter on Tuesday April 09, 2024 @03:41AM (#39977021)
> That's the complaint, that [[]]4 is not shorthand for list comprehensions

There are lots of reasons you would want items in a list repeated rather than having, essentially, the result of separate executions of the same constructor -- [] is just shorthand for list() -- so its good that [x()]4 is not shorthand for [x() for _ in range(4)]. Especially since that would mean it would have to be special-case sytax for list construction, and not a list operator that you could use on existing lists. The mildly annyoing edge case you need to learn about isn’t worth wiping out the whole broadly-useful language feature, or creating a great special-case inconsistency which would be more cognitive load to deal with, to eliminate.

Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by arijun on Tuesday April 09, 2024 @03:43AM (#39977034)
Why are you comparing functions/closures with values? You can do the same in python:

  [list() for _ in range(4)]
Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by bmitc on Tuesday April 09, 2024 @03:58AM (#39977100)
> Why are you comparing functions/closures with values?

I'm not. The fun _ -> [] is needed because the argument is the element's index. That's just what List.init happens to expect, a function that takes an index and initializes the element, but the index is not needed here.

Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by arijun on Tuesday April 09, 2024 @04:16AM (#39977191)
Are you saying f# special-cases something that looks like a closure, but isn’t in this one context? Because that, to me, seems like a much more grievous issue than the one at hand.
Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by bmitc on Tuesday April 09, 2024 @04:23AM (#39977228)
No. F# lambdas are closures. I was just saying that I'm not using the concept of closures to explain here. It's just a side effect of using the List.init function as a demonstration.
Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by arijun on Tuesday April 09, 2024 @04:36AM (#39977339)
(I can’t respond to your other comment)

Ah I see, you’re saying that the construction of a list in F# mandates a lambda, thereby reducing one possible point of confusion. I could agree with that. But then it comes at a cost of comfort: [0]*4 has less boilerplate than the F# version. So it comes down to trade-offs again.

Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by maxcoder4 on Tuesday April 09, 2024 @05:16AM (#39977618)
>That's the complaint, that [[]]*4 is not shorthand for list comprehensions and that it's something entirely different.

Well, of course. It's a shorthand for duplicating the list elements four times. In this case, the list contains a single reference to an empty list, do the result contains four references to an empty list.

Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by Joker_vD on Tuesday April 09, 2024 @05:26AM (#39977682)
And it's literally impossible for [[]]*4 to be a shorthand for a list comprehension, because nothing in Python can be a shorthand for a list comprehension. Instead, it is but a method call.
Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by dragonwriter on Tuesday April 09, 2024 @12:21PM (#39981028)
I mean, there is no reason Python couldn't special case something that looked like an operator call into shorthand for a comprehension instead of shorthand for a method call, other than the fact that it would make the parser more complex and make it harder to understand the language.

It would be bad for this case, though. As confusing as the particular case of:

  [[]] * 4
might be to people who haven't learned how it works, list multiplication doesn't just apply to single element lists, and is useful and usefully distinct from what people are suggesting the behavior should be for the operation based on this one case.
Re:Why Do Python Lists Multiply Oddly? Exploring the CPython... by Joker_vD on Wednesday April 10, 2024 @06:22AM (#39989061)
Well, Python is not Raku, so while it could be possible to make "[expr1, expr2, ..., exprN] * exprM" to mean "[*(expr1), *(expr2), ..., *(exprN) for _ in range(exprM)]", it would never happen.

Besides, that still doesn't help with the case of

    x = function_that_returns_a_list()
    x = x * 4
where there is no literal list expression.