tags:

views:

257

answers:

3

Possible Duplicate:
How to deal with Python ~ static typing?

I'm basically a Java programmer with little knowledge of python.I really like the syntax of python and the ease with which a programmer is able to express his idea's but also I'm aware that python is dynamically typed and thus is not as fast as Java.My question is why can't python infer type like languages such as scala ?

A: 

Python is dynamically-typed, whereas type inference is only possible in statically typed languages. Static typing would be impossible to implement without dropping support for features such as lists of arbitrary objects.

Gintautas Miliauskas
Not sure. For "x = 123" the compiler should be able to infer that x is an integer.
Thilo
@Thilo: "x = 123; x = str(x); x = [c for c in x]" , is x an int, a string, or a list?
Lie Ryan
@Lie Ryan, I guess the compiler could rewrite the identifier names, so that all can live together. `x_int = 123; x_str = str(x_str); x_list = [c for c in x_str]`.
Ionuț G. Stan
@Ionuț G. Stan: let's assume the compiler does that, how would you rewrite `x = 123 # assume this is from function argument`; `if x in [123, '234']:`; ` x = '123'`; `else:`; ` x = ['2', '3', '4']`; `print x if '3' in x else 'no 3'`; it gets really messy to retranslate that to statically typed names.
Lie Ryan
@Lie. Of course it would not work in all cases. That does not mean that it is not a useful optimization in cases where it does work.
Thilo
@Thilo: Psyco does a limited form of type inference at runtime. It basically detects the type of the objects, recompiles the python to x86 instructions under that type assumption, and then injects the compiled code into the running code and adds some type checking to ensure that the type inference is not violated; if the type inference do gets violated, two things can happen: the python version will get invoked or psyco will generate a second version of the compiled code using the second type assumption.
Lie Ryan
I assume that in effect something like this also happens on the Hotspot JVM for Jython. If this works well, type checking in the language compiler would be premature optimization (as some people claim) at least for the performance aspect. Compile-time error checks would still be nice (even if they would necessarily not be as comprehensive as for Java or Scala).
Thilo
+17  A: 

It is not that Python can't, but it don't. The difference is in the type systems that the designers of the languages choose to follow.

Python uses duck typing and has typed objects but untyped variable names. Type constraints are not checked at compile time; rather, operations on an object may fail, signifying that the given object is not of a suitable type. Despite being dynamically typed, Python is strongly typed, forbidding operations that are not well-defined (for example, adding a number to a string) rather than silently attempting to make sense of them.

Scala is a statically typed language, that is, types are checked at compile time. A local type inference mechanism takes care that the user is not required to annotate the program with redundant type information. Operations that break type constraints leads to compiler errors, not runtime errors. Also see The Purpose of Scala's Type System, especially the section where duck typing is discussed.

Vijay Mathew
+1  A: 

Python doesn't do static type inference, because it wants to let you do things that are impossible under such a scheme. For example:

def myfn():
  if random.random() > 0.5
    return "howdy"
  else:
    return 7

x = myfn() #  Am I a string or an integer?

What should the type of x be?

EDIT : example was:

def myfn(x):
  try:
    return str(x[0]+1) + " is my favourite"
  catch IndexError:
    return x+1

myfn(1) #  = 2
myfn( [2,4,6] ) # = "3 is my favourite"
Michael Anderson
Well... it could generate two behind-the-scene functions: Sequence -> str (or maybe Sequence -> Sequence) and int -> int. Kind of like overloading.
Ionuț G. Stan
OK, I'll ajust it to something that is even more trivial yet harder to track.
Michael Anderson
def myfn(x: Array[Int]) = try Left(str(x(0) + 1) catch { case e: ArrayIndexOutOfBoundsException => Right(x + 1)
Ricky Clarkson
You're right, that's trickier. In my opinion though, it matters a lot how that function is used, so in this latest case, the compiler knows that `myfn` returns a string or an int and can at least ensure that you're not calling list methods on the return value. Now, that's a strange example anyway, and I can't really see a real world usage of it, which tells me that some trade-offs can be employed, like forbidding functions returning really different type of arguments.
Ionuț G. Stan
Why would you ever want to use functions like these?
pelotom
@peletom - Maybe you need a function that returns an array or single value depending on whether you pass the "all" or "first" as the search_type argument.
Michael Anderson
Impossible? `def myfn = if (util.Random.nextBoolean) "rowdy" else 7; val x = myfn` <-- perfectly valid Scala.
Daniel
@Michael Anderson: but then you need to dynamically check the type of the result before you do anything with it, so what have you gained over always returning an array and then checking the size?
pelotom
@pelotom - Since I passed it the argument as either "all" or "first" I know whether I'll be getting back an array or a single value, no need to check anything.
Michael Anderson
@Michael how's that different than calling ".first()" on the result? I see no real advantage here.
pelotom
@daniel - In this case is the return type of myfn just Any? Then I expect that in a lot of pythonesque situations you end up passing around a lot of Any typed objects which the system then has to type check at run time... thus losing the benefits of scalas type inference? (I'm assuming a lot about how scala behaves that may well be wrong)
Michael Anderson
@Michael - yes, you would end up with the most general type that could contain two completely dissimilar types, which is usually Any. And yes, you would lose all the benefits of static type checking, but it would be no worse at that point than the situation in python. So the point is, you can do this in Scala, but why would you want to? I can think of one big reason *not* to: it becomes very hard to reason about what exactly your functions do.
pelotom
@Michael The return type is `Any`, indeed, and Scala won't let you do almost anything with it unless you match for its type or type cast it. The difference is that Scala won't let you call a method unless it knows at compile time that the object supports it, while Python will let you call any method, whose applicability will only be known at run-time. Using a dynamically typed language is like saying to the compiler "trust me, I know what I am doing." Using a statically typed language is like saying "check this to see if I am right."
Daniel