3 ms·
I'm a bit confused by your example. Python has different design goals than Clojure. Clojure competes with rather high performance languages, Java and Scala, on
by todd8 10y ago
I'm a bit confused by your example. Python has different design goals than Clojure. Clojure competes with rather high performance languages, Java and Scala, on the JVM and it appears from the OP that its implementors have decided that it can't afford to spend too much time at run-time checking.
Python on the other hand at least attempts to adhere to a principle of least surprise and enforces strong type requirements at run-time. It does this because consistency is generally more important than performance considerations in Python, one of the reasons that Python is much slower than Clojure.
The API for the set constructor in Python accepts any iterable as an argument. Furthermore the elements of a set must be objects that are hashable.
Consequentially, Python sets rule out mutable members, such as Lists, Maps, and other Sets. Sets of Set Objects aren't allowed since Set Objects can be modified. Strings are immutable so Sets of strings are allowed and even frozensets (an immutable kind of set object) and tuples (which happen to be immutable in Python) can be members of sets in Python. I believe that this is all spelled out in the documentation pretty clearly, and the language's built ins and standard library enforce this simple model at the cost of run-time type checking.
Thus,
set([1,2,3,2]) == {1,2,3}
# the tuple (10,20) is immutable and hashable
set([1,2,"abc",(10,20)]) == {1,2,"abc",(10,20)}
# strings are iterables
set("abc") == {"a", "b", "c"}
# lists are iterable and strings immutable and hashable
set(["abc"]) == {"abc"}
# comprehensions and generators are iterable
set(i*2 for i in range(5)) == {0,2,4,6,8}
# sets are iterable
set({2,4,6}) == {2,4,6}
# int 14 is not an iterable
set(14) <--- error
# and [2,3] is a list and so mutable and not hashable
set([1,[2,3]]) <--- error
The interface to the union method for sets also takes an interable so,
set([1,2,3]).union(["a", "bc"]) == {1,2,3,"bc","a"}
set({1,2,3}).union({3,4,5}) == {1,2,3,4,5}
- blain_the_train 10y agoI'm not questioning that python api isn't clear. Neither is clojure one. Both require the user to read them in order to properly apply them. I think pythons resolutes only seem less surprising because someone would be used to them? Maybe that coercion is easier to reason about. Im honestly not sure. Like this example: In [19]: s = set([1, 2, 3]) In [20]: s.union({"x", "y"}) Out[20]: {1, 2, 3, 'y', 'x'} Is that more clear then explicitly requiring only sets be unioned? Why the key and the value? The meaning of the key and value have been drastically change now. Maybe this is what all languages do? anyway, I think i gained a lot thinking this through. Thanks everyone :) *One error Is I mistakenly said that strings weren't hashable.
- todd8 10y agoOh, I think I understand your question. This is a set literal, not a map literal: {"a", "b", "c"} This is a map: {"name": "Fido", "age": 8} Note the colons. The point I was making is that Python doesn't make performance trade offs with these set APIs. Set union is in no way surprising. It either gives the correct intuitive result or raises an exception because of incorrect argument types.
- blain_the_train 10y agoI'm having quite the day. I think switching between clojure and python is frying my circuit. I know the difference between a map syntax and set and somehow managed to use set in place of map. I think this happened in part because my point is that any output of union(set, dict) is up to the language designer and has no basis in set theory (though i would be interested to here other wise) >>> s = set([1, 2]) >>> d = dict(x="hi") >>> s.union(d) set([1, 2, 'x']) apologies for the confusion... I need to proof read my comments more throughly.