Re: python philosophical question - strong vs duck typing
On 1/9/2012 2:45 AM, Robert Kern wrote: On 1/9/12 5:35 AM, John Nagle wrote: Python has some serious problems that preclude optimization. Basically, the language is designed to be run by a naive (non-optimizing) interpreter, and allows things that are easy for such an implementation but very tough to optimize. An example is the ability to store into the variables of a module from outside it, and even from another thread. Every attempt to get rid of the Global Interpreter Lock has hit that problem. You keep repeating this falsehood about the GIL. You have been repeatedly shown that this is false[1][2], though I have yet to see you acknowledge it. The GIL exists to protect Python's internal data structures, mostly the reference counts on objects. The reason that the attempts to remove the GIL from CPython have not been accepted is because they cause unacceptable performance losses in the common unthreaded case. In implementations of Python that do not use reference counting, there is no GIL. Neither Jython nor IronPython have a GIL, but they both have the standard Python semantics that let you store variables into modules from the outside, even from other threads. [1] http://mail.python.org/pipermail/python-list/2011-February/1265760.html [2] http://mail.python.org/pipermail/python-list/2011-April/1269056.html If you don't have a global lock, then you have to have lots of implicit locks, probably one on every symbol dictionary. IronPython does this well, though; their dictionaries do not require locking for read access, only for writes. So they avoid running up the overhead on routine symbol access. Some operations which CPython users assume are atomic, such as list append, are not atomic in IronPython. (See http://ironpython.codeplex.com/wikipage?title=FAQ;) The GIL does more than just protect memory allocation. If you want to retain the semantics of CPython, the implementation pretty much has to be slow. The Unladen Swallow project crashed and burned because of that fact. They couldn't even get 2x over CPython. There are still too many unnecessary dictionary lookups when running Python. Most of those could be optimized out at compile time if, when compiling a module, the compiler didn't have to worry about the module being altered from outside itself. John Nagle -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 01/09/2012 04:35 PM, John Nagle wrote: A type-inferring compiler has to analyze the whole program at once, because the type of a function's arguments is determined by its callers. This is slow. The alternative is to guess what the type of something is likely to be, compile code at run time, and be prepared to back out a bad guess. This requires a very complex system, but that's how PyPy does it. Performance does not seem to reach Shed Skin levels. With a smart enough compiler, JIT compiler can actually be faster than compile-time optimizations; the reason being that different people might use the same code differently. For example, say we have a function that takes an array of numbers which can be integer or float or a mix of integers and floats. A compile-time optimizer cannot optimize this function safely; but a run-time optimizer might notice that a certain user only ever use the function with an array of integers and generate an optimized code for that particular case. Profile-guided optimizations (PGO) can do something similar, but then it means a single program will have to have twenty different binaries for twenty different use cases; or a very large binary that contains code optimized for every possible thing. -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 1/9/12 5:35 AM, John Nagle wrote: Python has some serious problems that preclude optimization. Basically, the language is designed to be run by a naive (non-optimizing) interpreter, and allows things that are easy for such an implementation but very tough to optimize. An example is the ability to store into the variables of a module from outside it, and even from another thread. Every attempt to get rid of the Global Interpreter Lock has hit that problem. You keep repeating this falsehood about the GIL. You have been repeatedly shown that this is false[1][2], though I have yet to see you acknowledge it. The GIL exists to protect Python's internal data structures, mostly the reference counts on objects. The reason that the attempts to remove the GIL from CPython have not been accepted is because they cause unacceptable performance losses in the common unthreaded case. In implementations of Python that do not use reference counting, there is no GIL. Neither Jython nor IronPython have a GIL, but they both have the standard Python semantics that let you store variables into modules from the outside, even from other threads. [1] http://mail.python.org/pipermail/python-list/2011-February/1265760.html [2] http://mail.python.org/pipermail/python-list/2011-April/1269056.html -- Robert Kern I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth. -- Umberto Eco -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 1/3/2012 6:15 PM, alex23 wrote: On Jan 4, 6:38 am, Terry Reedytjre...@udel.edu wrote: Shredskin compiles a subset of Python, or a subset of usages, to C, with similar benefits. That is, of course, 'Shedskin' and 'C++' :) +1 for either Cython or Shedskin as your next step for more performant Python. I've tried Shed Skin, and it's an excellent idea that's not ready for prime time. One guy did it all, and it needs a greater level of effort than that. It does do well on numeric code. There's a reason for that. If you can figure out at compile time which variables can be represented as int, bool, char (or wchar_t) and double, performance on numeric work improves enormously. CPython boxes everything, including integers, in a CObject object, so there's dispatching overhead just to add two numbers. A type-inferring compiler has to analyze the whole program at once, because the type of a function's arguments is determined by its callers. This is slow. The alternative is to guess what the type of something is likely to be, compile code at run time, and be prepared to back out a bad guess. This requires a very complex system, but that's how PyPy does it. Performance does not seem to reach Shed Skin levels. Python has some serious problems that preclude optimization. Basically, the language is designed to be run by a naive (non-optimizing) interpreter, and allows things that are easy for such an implementation but very tough to optimize. An example is the ability to store into the variables of a module from outside it, and even from another thread. Every attempt to get rid of the Global Interpreter Lock has hit that problem. John Nagle -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
Terry Reedy於 2012年1月5日星期四UTC+8上午4時22分03秒寫道: On 1/4/2012 1:37 AM, Terry Reedy wrote: On 1/3/2012 8:04 PM, Devin Jeanpierre wrote: [ An example of a simple dependently typed program: http://codepad.org/eLr7lLJd ] Just got it after a minute delay. A followup now that I have read it. Removing the 40 line comment, the function itself is fun getitem{n,m:nat}(arr : array(int, n) , length : int(n), index : int m) : int = if index length then arr[index] else ~1 (* -1, error *) where n,m are compiler variables used to define the dependent (paramaterized) types array(int,n) and int(n)/ The double use of n means that the compiler checks that length n of the array equals the length passed. My response: in Python, there is no need to pass concrete collection sizes because they are packaged with the collection at runtime as an attribute. So: 1) In Python, there is no need for such checking. In addition, the for-loop construct, 'for item in iterable:', removes the possibility of indexing errors. 2) Python classes are, in a sense, or in effect, runtime dependent types. While the formal implementation type of a 'list' is just 'list', the effective computation type is 'mutable sequence of length n'. The type of an iterator is 'read-only sequence of indefinite length'. I find this an interesting way to look at Python. Also it is easy to turn an indexed object to be an iterator by a function decorator that returns a generator in the object level without declaring a new class from a class written by others. Thus this can lead to a decoupled design of software among many contributors in an elegant way. I prefer a factorized decoupled blocks of modules to be completed by several programmers to build a package. -- Terry Jan Reed -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
where n,m are compiler variables used to define the dependent (paramaterized) types array(int,n) and int(n)/ The double use of n means that the compiler checks that length n of the array equals the length passed. My response: in Python, there is no need to pass concrete collection sizes because they are packaged with the collection at runtime as an attribute. So: 1) In Python, there is no need for such checking. In addition, the for-loop construct, 'for item in iterable:', removes the possibility of indexing errors. Correct. This is a systems language, designed so that you do the least work possible and store the least amount possible in memory. For that reason it's one of the fastest languages on the language shootout, with the least memory usage overall. ( http://shootout.alioth.debian.org/ ) That is, you can also simply do A[k] = 3, and if the compiler can prove that k is always less than the length of the list, then this goes ahead without any extra work like a runtime check. This is similar to what Cython does above, but Python always does the check -- and ATS makes this optimization a core feature of the language, and predictable: you can force the compiler to try to do this, and if it can't, you can try to provide more information so that it can. The easiest way to prove it was provided above, by doing a runtime check -- but there are other ways (e.g. the inference Cython did; convenient constants; etc.) This is probably less appealing to Python programmers, who (rightly) don't really care about speed unless it becomes an issue. For them, ATS also has more advanced features like proofs of adherence to specification and so on (e.g. FIB above). On the other hand, ATS's main focus is, as far as I can tell, being something that's as fast as C, and safer than Haskell. I don't think it's meant for Pythonistas. :) (I've seen it compared to Ada, as well) I should also note that while Python stores the length information at runtime, you can do that in ATS too (it has exceptions). In fact, ATS has two array types: array0 keeps the size information at runtime, and array does not. With array0, out-of-bounds index access results in a runtime exception, with no compile-time checks performed. I don't really want to undestate how awesome Python is, though. I have long been of the opinion that C's attitude was unacceptable[**] -- if you forget to check, things go drastically wrong in undefined and unpredictable ways (that depend on your libc/compiler/etc.). Python offers a way out: all errors are checked for by Python itself. This makes your job easier and makes mistakes obvious. ATS is nowhere near as easy in general. :) Also, you make a good point about for loops. They are a wonderful thing. :) (ATS doesn't have them; it could get them in theory...) [*] With the idea being that in Python you can get unexpected errors at runtime, whereas in ATS you can try to prove they can't exist, at compile time. E.g. take AttributeError: None has no attribute 'split' versus non-nullable types [**] Unfortunately, C is still irreplaceable. ATS is never going to win this one. I do think that dependent typing will eventually enter the mainstream, though. It's a powerful concept we rely on implicitly all the time, and I seem to be seeing more of it lately. 2) Python classes are, in a sense, or in effect, runtime dependent types. While the formal implementation type of a 'list' is just 'list', the effective computation type is 'mutable sequence of length n'. The type of an iterator is 'read-only sequence of indefinite length'. I find this an interesting way to look at Python. I think that's reasonable. I don't think it would be outrageous to promote this concept to how we do isinstance checks, but nobody but me seems to like things like except IOError(errno.EBADF): (Usually the if-statements aren't really more complicated, but IOError is an exception (which is being rectified a different way)). But yes, even without it being part of the language we can model it that way. And it's something we do all the time. I think another good example of that is the k-tuple. k-tuples seem very different to n-tuples, for n != k. -- Devin On Wed, Jan 4, 2012 at 3:22 PM, Terry Reedy tjre...@udel.edu wrote: On 1/4/2012 1:37 AM, Terry Reedy wrote: On 1/3/2012 8:04 PM, Devin Jeanpierre wrote: [ An example of a simple dependently typed program: http://codepad.org/eLr7lLJd ] Just got it after a minute delay. A followup now that I have read it. Removing the 40 line comment, the function itself is fun getitem{n,m:nat}(arr : array(int, n) , length : int(n), index : int m) : int = if index length then arr[index] else ~1 (* -1, error *) where n,m are compiler variables used to define the dependent (paramaterized) types array(int,n) and int(n)/ The double use of n means that the compiler checks that length n of the array equals the length passed. My response: in Python,
Re: python philosophical question - strong vs duck typing
Since Python does not 'silently convert types' as I understand those 3 words, you lose me here. Can you give a code example of what you mean? I mean the reasoning behind the arguments like 'X isn't strongly typed because 2 + 3 = 5 but 3 + 2 = 32'. OCaml considers this a problem and bans all implicit conversions whatsoever. (Or maybe that's more to do with making their type inference better?) I actually stole the classification of continuums from a Python wiki page, and my terminology was influenced by the reading. See: http://wiki.python.org/moin/StrongVsWeakTyping I am aware that typed names lead to typed function signatures and that some languages in the ML family even type operators, so that different operators are required for 1+2 and 1.0+2.0 and mixed operations like 1+2.0 are prohibited. But we are talking about the typing of objects here. I should state up-front that I'm not sure we can only talk about the typing of objects. There's a bit of a problem in that dynamically typed and statically typed aren't exactly things that can be compared -- they're almost orthogonal. Almost. Dynamically typed languages like Python keep, by necessity, information about what they are and what they came from (at run-time). (The alternative is to be untyped, which is bad). Statically typed languages do not always have to keep them around. If you do enough at compile-time, you can forget everything at run-time. Run-time and compile-time are completely different, and a language can do any combination of things at both. It's weird that we've decided that there's only two options rather than four, and that we really want to compare these two options. I'm not sure how that fits into what I've said. Maybe I've already contradicted myself. Anyway, in answer, OCaml forbids both at run-time _and_ compile-time the coercion of floats to ints via the + operator, and in doing so enforces its notion of strong typing. You can't add a float to an int. So in this notion, it allows less implicit type conversion -- and run-time object conversion -- than Python, which freely converts floats to ints. This philosophy extends elsewhere in OCaml. Using induction, I can prove, for instance, that these two functions def f_tr(n, val=base): # tail recursive if n: return f_tr(n-1, rec(n, val)) else: return val def f_wi(n, val = base): # while iterative while n: n, val = n-1, rec(n, val) return val are equivalent, assuming enough stack and normal procedural Python semantics. (And assuming no typos ;-). f_tr(0) == base == f_wi(0) f_tr(n+1) == f_tr(n+1, base) == f_tr(n, rec(n+1, base)) == by inductive hypothsis f_wi(n, rec(n+1, base)) == f_wi(n+1, base) == f_wi(n+1) So it is not clear to me what such proofs have to do with types as I understand the term. Ah, I messed up and didn't explain that. It doesn't help that I've been too lazy to actually work with ATS proofs directly, so I might say some things that are wrong/vague. In some languages -- particularly dependently-typed languages -- a type can represent a computation. That is, the return type of a function might essentially be the computation that we wish to do, and therefore if the function typechecks then we know it does that computation. (This has all the caveats of formal methods as a whole). Many (all?) of the automated theorem provers are dependently typed languages in this fashion. In particular, if you pick some well-defined decidable computational language, you can try to make your type system powerful enough to encode it. (For example, the primitive recursive functions are a nice subset.) For an example, in ATS the following is a compiler-type which can be used as part of the type declaration for a function: dataprop FIB (int, int) = | FIB0 (0, 0) | FIB1 (1, 1) | {n:nat} {r0,r1:int} FIB2 (n+2, r0+r1) of (FIB (n, r0), FIB (n+1, r1)) The predicate FIB(X, Y) is true when Fibonacci(X) = Y, so this is essentially the same as defining fibonacci recursively: Fibonacci(0) = 0 Fibonacci(1) = 1 Fibonacci(A+2) = Fibonacci(A+1) + Fibonacci(A) It encodes the recursive definition of fibonacci, and if we declare a function as taking a value m, returning a value n, such that FIB(m, n), then a successful typecheck is equivalent to a successful proof that the implementation is correct. How does that typecheck work? I don't really know, I haven't at all investigated the proof structure for ATS. Sorry. :( Some cursory reading says that a function can return a proof that is typechecked against dataprop, as well as the value. Maybe that's it. :) I can imagine that if one overloads 'type' with enough extra information, the procedural reasoning involved in such proofs might reduce to a more calculational demonstration. The question is whether the months and years of intellectual investment required on the front end pay off in reduced intellectual effort across several applications. Yes. Well, the compiler writers
Re: python philosophical question - strong vs duck typing
On Tue, Jan 3, 2012 at 7:28 PM, Ben Finney ben+pyt...@benfinney.id.au wrote: Sean Wolfe ether@gmail.com writes: Hello everybody, I'm a happy pythonista newly subscribed to the group. Welcome! Thanks! and thanks to all, hjaha. I have a theoretical / philosophical question regarding strong vs duck typing in Python. Let's say we wanted to type strongly in Python There may be an unstated assumption there, and your wording confuses me. yep, probably. I am throwing around terminology a bit. Here's another attempt -- If I am willing to create some python code, when needed, where when I create a variable, let's say an integer, that it will be for all time an integer, and also that a method that returns say a Sprite custom object, and will for all time return only a Sprite object ... , does this get me significantly closer to being able to compile to C++? I am just thinking in my brain about the differences between cpp and python, and if there is a way to compromise a bit on the python-ness to get closer to cpp, but still be able to keep a lot of the goodness, then put in a translator or converter to cpp and gain performance by using cpp code. Sounds like Rpython, cython, shedskin are doing a lot or all of this, so lots to study up on. “Strongly-typed” is one end of a spectrum whose opposite end is “weakly-typed”. Weakly-typed objects are in languages like e.g. PHP, where an integer object can be added to a string object. Ah ok, I didn't realize this distinction. Now I grok it a bit better. Python does not have variables in the sense of languages like C; rather, Python has references bound to objects. A reference (e.g. a name, or a list index, etc.) never has a type. An object always has a type. yeah I've been learning a lot about this ... at times I have to 're-create' a variable to avoid modifying the original value as well. For example, when I pass a 'screen' object in my game, at times I have to duplicate the screen in the new method, then work on the duplicate, otherwise I will be using the original screen by reference. You may be thinking of “static typing” (identifiers have types, and won't allow themselves to refer to an object of a different type), versus “dynamic typing” (identifiers are ignorant of types – this is what you have in Python). Yep I think so. Thanks for the info all! -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 1/4/2012 12:37 AM, Terry Reedy wrote: Using induction, I can prove, for instance, that these two functions [snip] are equivalent, assuming enough stack and normal procedural Python semantics. (And assuming no typos ;-). YOU proved that; your type system didn't. With a powerful enough type system, those two functions would have the same type, while if you had made a typo they wouldn't. The extreme example of a powerful type system is something like Coq or Elf. In a language like that, a mathematical sentence is encoded in a type, and objects of a certain type represent a proof that that the sentence can be proved. Evan -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On Wed, 2012-01-04 at 11:30 -0300, Sean Wolfe wrote: On Tue, Jan 3, 2012 at 7:28 PM, Ben Finney ben+pyt...@benfinney.id.au wrote: Sean Wolfe ether@gmail.com writes: Hello everybody, I'm a happy pythonista newly subscribed to the group. Welcome! Thanks! and thanks to all, hjaha. I have a theoretical / philosophical question regarding strong vs duck typing in Python. Let's say we wanted to type strongly in Python There may be an unstated assumption there, and your wording confuses me. yep, probably. I am throwing around terminology a bit. Here's another attempt -- If I am willing to create some python code, when needed, where when I create a variable, let's say an integer, that it will be for all time an integer, and also that a method that returns say a Sprite custom object, and will for all time return only a Sprite object ... , does this get me significantly closer to being able to compile to C++? I'd really recommend looking at Cython - which has optional static typing and does compile into C / C++ (as a python extension) More generally, a compiler can perform static analysis on code which will re-order AST nodes into single constant assignments. I've forgotten the name but it's something like single static assignment form. When the return type of functions is known it can lead to known types for variables. It's being used heavily in the newest generation of javascript JITs to speed up generated native code. However, when a function has multiple return types (e.g. {}.get returns None if there is no result) then you can't imply the type of the variable even in this form. A JIT (such as pypy) can generate the native code for all seen return types - which is why JITs can in general be more useful to dynamically typed languages such as Python than compilers. Another issue is where types can be modified (e.g. in python you can modify the class of an object at runtime) - dynamic language features such as this make what counts as a type fairly flexible. JITs are getting around this using hidden classes (there are lots of other names for the same thing) - again it would be very difficult to statically compile this kind of thing to native code. I am just thinking in my brain about the differences between cpp and python, and if there is a way to compromise a bit on the python-ness to get closer to cpp, but still be able to keep a lot of the goodness, then put in a translator or converter to cpp and gain performance by using cpp code. Sounds like Rpython, cython, shedskin are doing a lot or all of this, so lots to study up on. Yup Tim Wintle -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 1/4/2012 1:37 AM, Terry Reedy wrote: On 1/3/2012 8:04 PM, Devin Jeanpierre wrote: [ An example of a simple dependently typed program: http://codepad.org/eLr7lLJd ] Just got it after a minute delay. A followup now that I have read it. Removing the 40 line comment, the function itself is fun getitem{n,m:nat}(arr : array(int, n) , length : int(n), index : int m) : int = if index length then arr[index] else ~1 (* -1, error *) where n,m are compiler variables used to define the dependent (paramaterized) types array(int,n) and int(n)/ The double use of n means that the compiler checks that length n of the array equals the length passed. My response: in Python, there is no need to pass concrete collection sizes because they are packaged with the collection at runtime as an attribute. So: 1) In Python, there is no need for such checking. In addition, the for-loop construct, 'for item in iterable:', removes the possibility of indexing errors. 2) Python classes are, in a sense, or in effect, runtime dependent types. While the formal implementation type of a 'list' is just 'list', the effective computation type is 'mutable sequence of length n'. The type of an iterator is 'read-only sequence of indefinite length'. I find this an interesting way to look at Python. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
python philosophical question - strong vs duck typing
Hello everybody, I'm a happy pythonista newly subscribed to the group. How is it going? I have a theoretical / philosophical question regarding strong vs duck typing in Python. Let's say we wanted to type strongly in Python and were willing to compromise our code to the extent necessary, eg not changing variable types or casting or whatever. Let's say there was a methodology in Python to declare variable types. The question is, given this possibility, would this get us closer to being able to compile down to a language like C or C++? What I am driving at is, if we are coding in python but looking for more performance, what if we had an option to 1) restrict ourselves somewhat by using strong typing to 2) make it easy to compile or convert down to C++ and thereby gain more performance. It seems to be that accepting the restrictions of strong typing might be worth it in certain circumstances. Basically the option to use a strongly-typed Python as desired. Does this get us closer to being able to convert to Cpp? Does the Cython project have anything to do with this? Thanks! -- A musician must make music, an artist must paint, a poet must write, if he is to be ultimately at peace with himself. - Abraham Maslow -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On Tue, Jan 3, 2012 at 1:13 PM, Sean Wolfe ether@gmail.com wrote: Hello everybody, I'm a happy pythonista newly subscribed to the group. How is it going? I have a theoretical / philosophical question regarding strong vs duck typing in Python. Let's say we wanted to type strongly in Python and were willing to compromise our code to the extent necessary, eg not changing variable types or casting or whatever. Let's say there was a methodology in Python to declare variable types. Do you think everyone who uses the code you write wants to deal with your type decisions? The question is, given this possibility, would this get us closer to being able to compile down to a language like C or C++? Declaring types would enable some additional optimizations, yes. No, it isn't worth it. What I am driving at is, if we are coding in python but looking for more performance, what if we had an option to 1) restrict ourselves somewhat by using strong typing to 2) make it easy to compile or convert down to C++ and thereby gain more performance. Take a look at PyPy, with RPython. That is the most future proof, forward thinking way of doing what you want. It seems to be that accepting the restrictions of strong typing might be worth it in certain circumstances. Basically the option to use a strongly-typed Python as desired. Does this get us closer to being able to convert to Cpp? Does the Cython project have anything to do with this? Declared typing is mostly annoying. Implicit static typing is less annoying, but still has issues. Cython fills the same niche as PyPy's Rpython. Use it if you have a lot of C code you want to call, as you will get better performance than a wrapper like SWIG. Nathan -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 12-01-03 01:13 PM, Sean Wolfe wrote: Hello everybody, I'm a happy pythonista newly subscribed to the group. Welcome. The question is, given this possibility, would this get us closer to being able to compile down to a language like C or C++? That's a question. The question is do you want to? Since we already run in machine language (doesn't everything) then how can you be sure that introducing another layer will improve performance? What I am driving at is, if we are coding in python but looking for more performance, what if we had an option to 1) restrict ourselves somewhat by using strong typing to 2) make it easy to compile or convert down to C++ and thereby gain more performance. Where is your bottleneck? I have seldom found Python to be it. Remember, almost everything you run was written in C. Python is just the glue that binds it all together. Consider ls(1) (dir in Windows/DOS) for example. If you need a directory listing you type that and get it pretty quickly. Is there a bottleneck? Yes, it's you. The command can probably do all of its work much faster than you can type the command. Now put the command into a script. Entering the command is no longer the bottleneck. It's now the time it takes to access the drive. Do we care? Probably not and if we did there's probably not much we can do about it. Python is simply a more powerful and efficient way to get to that machine language in a script. If you do have a pure Python function that is a bottleneck and you believe that C can solve it, you can always write just that part in C. However, run some tests first to make sure. 99% of the time you can fix it algorithmically or else it wasn't the bottleneck that you thought it was. And if it is and no one has already written a module for it, you just found a project to contribute back to the community. :-) It seems to be that accepting the restrictions of strong typing might be worth it in certain circumstances. Basically the option to use a So few as to not be worth changing the language for, especially when C is always available if you need it. Cheers. -- D'Arcy J.M. Cain da...@druid.net | Democracy is three wolves http://www.druid.net/darcy/| and a sheep voting on +1 416 425 1212 (DoD#0082)(eNTP) | what's for dinner. IM: da...@vex.net -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 1/3/2012 12:13 PM, Sean Wolfe wrote: if we are coding in python but looking for more performance, Are you in fact in this situation? Despite years of folks mentioning how Python is 'slower than C++', I've seen a project where a developer churned out a feature using Python's generators that performed much faster than the C++ implementation it replaced. It wasn't because the C++ was slower by nature; it's because it was harder to express the optimal algorithm in C++ so the C++ developer chose a sub-optimal approach in the interest of meeting a deadline. There's always a tradeoff. Making a language less expressive (constraining ourselves) in favor of runtime performance is not always the right tradeoff. -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 2012-01-03, David Harks d...@dwink.net wrote: On 1/3/2012 12:13 PM, Sean Wolfe wrote: if we are coding in python but looking for more performance, Are you in fact in this situation? Despite years of folks mentioning how Python is 'slower than C++', I've seen a project where a developer churned out a feature using Python's generators that performed much faster than the C++ implementation it replaced. It wasn't because the C++ was slower by nature; it's because it was harder to express the optimal algorithm in C++ so the C++ developer chose a sub-optimal approach in the interest of meeting a deadline. I was again looking through The Practice of Programming (Kernighan Pike) today, and the chapter on the Markov chain program makes similar tradeoffs. For educational purposes they implement the program in several languages, and the C implemenation is fastest by far. The C++ implementation is surprisingly not close in performance to the C version, for two main reasons. 1. They used a std::deque to store the prefixes, when a std::list is the correct container. They point this out in a note on the poor performance of the C++ program, but do not note the irony that they had automatically used a singly-linked list in C. 2. When building the data structure in C they store only pointers to the original text, which they munge in memory to create zero-terminated strings. This is idiomatic C. But there's no reason C++ can't do a similar optimization. A std::listchar* is certainly possible, but loses you most of the benefits of the standard containers. Best is probably to create a registry of words using a std::mapint, std::string, with your lists storing references to words in the registry. You still have to copy of the text, but only once. The C++ implementation starts to smell sort of like Python. ;) -- Neil Cerutti -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 1/3/2012 13:13, Sean Wolfe wrote: What I am driving at is, if we are coding in python but looking for more performance, what if we had an option to 1) restrict ourselves somewhat by using strong typing to 2) make it easy to compile or convert down to C++ and thereby gain more performance. I'm not sure it helps with compiling to C or C++ (that is neither necessary nor sufficient for being a high performance language), but it has the potential for helping quite a lot with performance. If you read stuff written by evangelical Common Lisp folks, they tout CL's optional type annotations as providing a mechanism for getting near-C-like performance. I haven't tested that myself though. Evan signature.asc Description: OpenPGP digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 1/3/2012 1:13 PM, Sean Wolfe wrote: I have a theoretical / philosophical question regarding strong vs duck typing in Python. Let's say we wanted to type strongly in Python and Python objects are strongly typed, in any sensible meaning of the term. What you mean is statically or explicitly typing names. were willing to compromise our code to the extent necessary, eg not changing variable types or casting or whatever. Let's say there was a methodology in Python to declare variable types. The question is, given this possibility, would this get us closer to being able to compile down to a language like C or C++? Cython compiles Python as is to C. It also gives the option to add type annotations to names to get faster code. Shredskin compiles a subset of Python, or a subset of usages, to C, with similar benefits. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
Python objects are strongly typed, in any sensible meaning of the term. There are people that hold definitions of strong typing that preclude Python. Those people think their definition is reasonable, but at the same time haven't confused static typing with strong typing. I guess the problem is that this boils down to opinion, but you're stating it as incontrovertible fact. What you mean is statically or explicitly typing names. Right, yes. Cython compiles Python as is to C. It also gives the option to add type annotations to names to get faster code. Shredskin compiles a subset of Python, or a subset of usages, to C, with similar benefits. I seem to remember there being a project which compiled the Python bytecode down to C in a very dumb way (basically just making C code that creates the bytecode and executes it in the CPython VM). I can't find it, though. Anyway, compiling Python to C is actually fairly trivial. People usually mean something else by it, though. -- Devin On Tue, Jan 3, 2012 at 3:38 PM, Terry Reedy tjre...@udel.edu wrote: On 1/3/2012 1:13 PM, Sean Wolfe wrote: I have a theoretical / philosophical question regarding strong vs duck typing in Python. Let's say we wanted to type strongly in Python and Python objects are strongly typed, in any sensible meaning of the term. What you mean is statically or explicitly typing names. were willing to compromise our code to the extent necessary, eg not changing variable types or casting or whatever. Let's say there was a methodology in Python to declare variable types. The question is, given this possibility, would this get us closer to being able to compile down to a language like C or C++? Cython compiles Python as is to C. It also gives the option to add type annotations to names to get faster code. Shredskin compiles a subset of Python, or a subset of usages, to C, with similar benefits. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 3 January 2012 20:38, Terry Reedy tjre...@udel.edu wrote: On 1/3/2012 1:13 PM, Sean Wolfe wrote: I have a theoretical / philosophical question regarding strong vs duck typing in Python. Let's say we wanted to type strongly in Python and Python objects are strongly typed, in any sensible meaning of the term. What you mean is statically or explicitly typing names. were willing to compromise our code to the extent necessary, eg not changing variable types or casting or whatever. Let's say there was a methodology in Python to declare variable types. The question is, given this possibility, would this get us closer to being able to compile down to a language like C or C++? Cython compiles Python as is to C. It also gives the option to add type annotations to names to get faster code. Shredskin compiles a subset of Python, or a subset of usages, to C, with similar benefits. A minor point of clarification here: although what you wrote is technically true, it's also misleading. AFAIK both Cython and Shedskin compile only a subset of Python, but the magnitude difference they drop off is large. Almost everything is Cython compliant, and that should just grow, but there are a few flakes here and there. However, Shedskin is a well defined subset, and does not encompass the whole of Python and will never do so. Shedskin *truly* compiles to C and thus is afflicted with several restrictions such as static typing. Cython is a lot less clear. What it compiles to is basically bytecode written in C. Instead of CPython reading the bytecode and the bytecode being parsed and then executed, *the computer natively parses the bytecode which tells CPython what to do*. This reduces a lot of overhead in tight loops, but doesn't help much in the general case. So why sacrifice so much for so little gain? Well - when your bytecode is C, you can interoperate other C code right inside. If you make some C variables you can do C-math inside your Python with no real overhead. Additionally, you can call C libraries really easily inside this code. What it results in is a really easy way to optimise the 5% that's slowing your code, and instead of rewriting it in C you use C-with-python-syntax. The types are sill horrible, though ;) -- To answer Devin: You're probably thinking of Cython ^^. -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 1/3/2012 4:06 PM, Devin Jeanpierre wrote: Python objects are strongly typed, in any sensible meaning of the term. There are people that hold definitions of strong typing that preclude Python. Those people think their definition is reasonable, but at the Can you give an actual example of such a definition of 'strongly typed object' that excludes Python objects? same time haven't confused static typing with strong typing. I guess the problem is that this boils down to opinion, but you're stating it as incontrovertible fact. This strikes me as petty hair-splitting. 1. By tacking on the qualification, I was acknowledging that someone, somewhere, might controvert it. If you allow for arbitrary redefinitions of words, you could claim that any statement is an opinion. So what? 2. It ignores the context established by the OP who began with 'Let's say we wanted to type strongly in Python' and continued with a question about declarations and compilation specifically to C or C++. In that context, I think my statement qualifies as a fact. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
Sean Wolfe ether@gmail.com writes: Hello everybody, I'm a happy pythonista newly subscribed to the group. Welcome! I have a theoretical / philosophical question regarding strong vs duck typing in Python. Let's say we wanted to type strongly in Python There may be an unstated assumption there, and your wording confuses me. Are you aware that Python has strong typing *and* duck typing, simultaneously? Every Python object is strongly-typed: they know exactly what type they are, what operations are permitted with objects of other types, and won't pretend to be a different type. (So an object of, e.g., type ‘int’, won't allow addition of itself with an object of type ‘str’.) “Strongly-typed” is one end of a spectrum whose opposite end is “weakly-typed”. Weakly-typed objects are in languages like e.g. PHP, where an integer object can be added to a string object. Every Python object allows duck typing: its operations are available to any code that wants to use that functionality, regardless of what type the client may assume it's working with. (This allows an object of, e.g., type ‘StringIO’, which has no relationship to the ‘file’ type, to be used by functions expecting a file object.) What do you mean to convey by “strong vs. duck typing”? and were willing to compromise our code to the extent necessary, eg not changing variable types or casting or whatever. Let's say there was a methodology in Python to declare variable types. Python does not have variables in the sense of languages like C; rather, Python has references bound to objects. A reference (e.g. a name, or a list index, etc.) never has a type. An object always has a type. You may be thinking of “static typing” (identifiers have types, and won't allow themselves to refer to an object of a different type), versus “dynamic typing” (identifiers are ignorant of types – this is what you have in Python). What I am driving at is, if we are coding in python but looking for more performance, what if we had an option to 1) restrict ourselves somewhat by using strong typing to 2) make it easy to compile or convert down to C++ and thereby gain more performance. I would need to know what you mean instead of “strong typing”, because Python already has that. -- \“If we ruin the Earth, there is no place else to go. This is | `\not a disposable world, and we are not yet able to re-engineer | _o__) other planets.” —Carl Sagan, _Cosmos_, 1980 | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
Terry Reedy tjre...@udel.edu writes: On 1/3/2012 1:13 PM, Sean Wolfe wrote: I have a theoretical / philosophical question regarding strong vs duck typing in Python. Let's say we wanted to type strongly in Python Python objects are strongly typed, in any sensible meaning of the term. What you mean is statically or explicitly typing names. For more on the various spectrums of type systems, and the terms to use, see URL:https://en.wikipedia.org/wiki/Type_system. -- \ “If I haven't seen as far as others, it is because giants were | `\ standing on my shoulders.” —Hal Abelson | _o__) | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
This strikes me as petty hair-splitting. Maybe it is! I don't know what petty means. 1. By tacking on the qualification, I was acknowledging that someone, somewhere, might controvert it. If you allow for arbitrary redefinitions of words, you could claim that any statement is an opinion. So what? I don't know where the original definition of strong typing came from. My experience has been that everyone has their own definition -- some people redefine it when faced with absurd consequences of their original definition, but usually to something roughly similar. I believe that people redefine it because to say your language is weakly typed sounds, well, like a weakness, or like an insult. It raises my hairs when people phrase it like that, anyway. 2. It ignores the context established by the OP who began with 'Let's say we wanted to type strongly in Python' and continued with a question about declarations and compilation specifically to C or C++. In that context, I think my statement qualifies as a fact. I agree, what I said there does ignore it. This is why I made a point of quoting you a second time, when you specifically referred to the OP, and stating my agreement. Sorry for any misunderstanding. As far as your correction to the OP goes, I am in favor. Aside from the small nit that applies to a statement if you take it out of context. Can you give an actual example of such a definition of 'strongly typed object' that excludes Python objects? I'd love to, but I neglected to above because I don't really know where we share ideas, and I wouldn't want to jump ahead and say something that seems outlandish. I hope I've done a decent enough job below. Stop me if I say something you don't agree with. Here's a short version: The term often refers to a continuum, where some languages are stronger than others, but there is no objective definition of strong -- it's like asking how big is big, or how smart is smart. The actual choice of what continuum strength refers to varies between people -- some specify it as reinterpretation of bits in memory, in which case every dynamic language in the world is strongly typed (so I'll move on from that), or some as implicit conversions between types, which is iffy because any function or overloaded operator can silently convert types (at least in Python), meaning the language is as weak as the user (?). But they're both kind of reasonable and held by a few people, and it's easy to see how maybe somebody used to significantly more strict rules (OCaml, for example) might accuse Python of not being all that strong. So you see it isn't really a change of definition, it's a redrawing of the lines on a continuum. The OCaml people are reasonable for saying what they say, because their point of reference is their favorite language, just as ours is ours. To us, maybe Haskell and OCaml are insanely strong/strict, to them, we're insanely weak. Here's another take, more in line with what I really meant: the continuums expressed above aren't universal either. IME they're chosen by dynamic typing advocates, which are worried about code readability and certain styles of immensely common errors that come from lower-level languages like C. Static typing advocates (at least in the functional programming language family) are instead concerned about correctness. For them, type systems are a way to reduce the number of errors in your code _in general_, not just the specific cases of type coercion or memory-safety. In this particular sense, Python is not very far from C -- it saves us from things that can crash the entire process or give us incorrect results rather than alerting us of a problem, but usually only so that we can encounter them in a more recoverable form. For example, out-of-bounds array access can no longer alter various parts of your stack and ruin the entire program state, but it is still a possible error. Static typing advocates say that strong typing can completely eliminate some types of errors, and the sensible time to detect such errors is at compile-time. This is absolutely an origin for the conflation of static vs strong typing, and it's hard to differentiate them in this sense, primarily because this notion of strong typing basically requires static typing for powerful results. On the other hand, you can clearly have stronger languages at runtime -- there are plenty of errors Python prevents, that C does not, even though python is dynamically typed and C is not. So Python's type system is clearly stronger than C. I hope this illustrates that strong and static are two different things even under this definition -- it's just that, most of the time, to really prevent an error, you prevent it from ever happening at compile-time. Type systems exist which are much stronger in what they can protect you against. As an extreme example, one might take a dependently-typed language. A statically dependently typed language can protect you against out-of-bounds array
Re: python philosophical question - strong vs duck typing
On Jan 4, 6:38 am, Terry Reedy tjre...@udel.edu wrote: Shredskin compiles a subset of Python, or a subset of usages, to C, with similar benefits. That is, of course, 'Shedskin' and 'C++' :) +1 for either Cython or Shedskin as your next step for more performant Python. -- http://mail.python.org/mailman/listinfo/python-list
Re: python philosophical question - strong vs duck typing
On 1/3/2012 8:04 PM, Devin Jeanpierre wrote: Can you give an actual example of such a definition of 'strongly typed object' that excludes Python objects? I'd love to, but I neglected to above because I don't really know where we share ideas, and I wouldn't want to jump ahead and say something that seems outlandish. I hope I've done a decent enough job below. Stop me if I say something you don't agree with. Here's a short version: The term often refers to a continuum, where some languages are stronger than others, but there is no objective definition of strong -- it's like asking how big is big, or how smart is smart. Fine so far. cold/hot, good/bad, etc are false dichotomies. Better to use there as comparatives -- better/worse that average, or than the middle 1/2. I don't use 'strong type' unless someone else does, and maybe I should stop being suckered into using it even then ;-). The actual choice of what continuum strength refers to varies between people -- some specify it as reinterpretation of bits in memory, in which case every dynamic language in the world is strongly typed (so I'll move on from that), Fine. or some as implicit conversions between types, which is iffy because any function or overloaded operator can silently convert types (at least in Python), Since Python does not 'silently convert types' as I understand those 3 words, you lose me here. Can you give a code example of what you mean? meaning the language is as weak as the user (?). But they're both kind of reasonable and held by a few people, and it's easy to see how maybe somebody used to significantly more strict rules (OCaml, for example) might accuse Python of not being all that strong. So you see it isn't really a change of definition, it's a redrawing of the lines on a continuum. The OCaml people are reasonable for saying what they say, because their point of reference is their favorite language, just as ours is ours. To us, maybe Haskell and OCaml are insanely strong/strict, to them, we're insanely weak. I am aware that typed names lead to typed function signatures and that some languages in the ML family even type operators, so that different operators are required for 1+2 and 1.0+2.0 and mixed operations like 1+2.0 are prohibited. But we are talking about the typing of objects here. Here's another take, more in line with what I really meant: the continuums expressed above aren't universal either. IME they're chosen by dynamic typing advocates, which are worried about code readability and certain styles of immensely common errors that come from lower-level languages like C. Static typing advocates (at least in the functional programming language family) are instead concerned about correctness. For them, type systems are a way to reduce the number of errors in your code _in general_, not just the specific cases of type coercion or memory-safety. In this particular sense, Python is not very far from C I see the object model of Python as being very different from the data model of C. The class of an object is an internal attribute of the object while the type of a block of bits is an external convention enforced by the compiler. I see Python's objects as more similar to the objects of many functional languages, except that Python has mutable objects. ... Type systems exist which are much stronger in what they can protect you against. As an extreme example, one might take a dependently-typed language. A statically dependently typed language can protect you against out-of-bounds array access with a proof at compile time. In I am familiar with the length-parameterized array types of Pascal (which seem in practice to be a nuisance), but I see from https://en.wikipedia.org/wiki/Dependent_type that there is a lot more to the subject. fact, a statically-dependently-typed language can do things like prove sometimes, though not always, that two different implementations of the same function are in fact implementations of the same function -- this is neat for implementing a non-recursive version of a recursive function, and verifying the change doesn't influence semantics. Using induction, I can prove, for instance, that these two functions def f_tr(n, val=base): # tail recursive if n: return f_tr(n-1, rec(n, val)) else: return val def f_wi(n, val = base): # while iterative while n: n, val = n-1, rec(n, val) return val are equivalent, assuming enough stack and normal procedural Python semantics. (And assuming no typos ;-). f_tr(0) == base == f_wi(0) f_tr(n+1) == f_tr(n+1, base) == f_tr(n, rec(n+1, base)) == by inductive hypothsis f_wi(n, rec(n+1, base)) == f_wi(n+1, base) == f_wi(n+1) So it is not clear to me what such proofs have to do with types as I understand the term. It's definitely true that there is something here that Python's types cannot do, at least not without extremely heavily mangling (technically __instancecheck__