Re: python philosophical question - strong vs duck typing

2012-01-13 Thread John Nagle

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

2012-01-10 Thread Lie Ryan

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

2012-01-09 Thread Robert Kern

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

2012-01-08 Thread John Nagle

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

2012-01-07 Thread 88888 Dihedral
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

2012-01-06 Thread Devin Jeanpierre
 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

2012-01-04 Thread Devin Jeanpierre
 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

2012-01-04 Thread Sean Wolfe
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

2012-01-04 Thread Evan Driscoll
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

2012-01-04 Thread Tim Wintle
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

2012-01-04 Thread Terry Reedy

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

2012-01-03 Thread Sean Wolfe
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

2012-01-03 Thread Nathan Rice
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

2012-01-03 Thread D'Arcy Cain

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

2012-01-03 Thread David Harks

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

2012-01-03 Thread Neil Cerutti
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

2012-01-03 Thread Evan Driscoll
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

2012-01-03 Thread Terry Reedy

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

2012-01-03 Thread Devin Jeanpierre
 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

2012-01-03 Thread Joshua Landau
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

2012-01-03 Thread Terry Reedy

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

2012-01-03 Thread Ben Finney
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

2012-01-03 Thread Ben Finney
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

2012-01-03 Thread Devin Jeanpierre
 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

2012-01-03 Thread alex23
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

2012-01-03 Thread Terry Reedy

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__