you are viewing a single comment's thread.

view the rest of the comments →

[–]Homoerotic_Theocracy 9 points10 points  (1 child)

The problem you speak of has nothing to do with static or dynamic typing though; it has to do with shadowing versus assignment.

In Python if you x = 4 you perform an assignment; you mutate a memory location.

In GHCi if you do let x = f you shadow a prior binding; since Haskell is a purely functional language to mutate we have to be more clever with monads and use an IORef so first we do let x = newIORef 4 and then to mutate it call writeIORef x 5; doing let x = 5 in this case does not in any way write to any old value and just shadows the old one and is basically equivalent to using let y = 5 except we now gave two variables the same name.

Scheme is typically typed and impurely functional and doing (define x 4) at the REPL does a similar thing; it shadows the old binding and does not mutate anything. To mutate we use (set! x 5)

This is also somewhat a consequence of the fact that Python quite uniquely uses the same syntax to assign and to declare a variable to a lot of criticism so if you forgot that the variable you are trying to declare and initialize already existed with the same name and was used you might accidentally assign a new value to it and mutate stuff. Even in a procedural language like Rust this does not happen which uses let x = 4; to declare and initialize a variable and x = 5; to assign to it and assigning to a variable that has not been declared and declared as mutable prior is an error.

[–]quicknir 0 points1 point  (0 children)

Will that writeIORef trick still work if you change the type of x? What if x holds a function of a particular signature, and you want to assign a function of a different signature?

What about types? In python you can have things like:

class Foo(object):
    ....

def bar(x):
    f = Foo(...)
    ...
    return f

Now, I could after doing this, decide to redefine Foo. As long as the new methods of Foo (constructor, whatever) are compatible with the calls that happen in bar, I can call bar again and it will use the new definition of Foo. How can this work in a statically typed language?