Live data from Hacker News

The Day Python Embarassed Imperative Programming

the-27th-comrade.appspot.com

71–80 of 80 posts

Re: The Day Python Embarassed Imperative Programming

#71
I don't see anything here showing Python to be embarrassing. Python IS dynamically typed, which puts the burden on you to do type checking when it is necessary. But everybody already knew that.

None is just a singleton value. A particular object may be None, or may be 4, or may be whatever. However, you cannot assign a new value to 4, or None, so it isn't accurate to say that any object could have a value of None. It isn't that an object might have something in it, or not. It's that the object might be None, or something other than None, JUST as it might be 4, or something other than 4. That is just how it works in Python's type system. There really is no notion of "has no value". None IS a value. If (for some reason, hopefully a good one) you mean to exclude it and raise an error, you must deal with that in exactly the same way as you would exclude and raise an error on any other particular value you found important.

In Python, it is not true that anything might not have a value. Python itself doesn't even have predicates for "has something in it" or "doesn't have something in it." That might be a common idiom using None by convention, but it's by no means inherent to Python, or necessary. It's really not the same as NULL.

What's true is that any argument (or namespace binding) could have a value of None. OR 4, or a certain dict, or whatever. That's just because Python isn't doing automatic type checking. None does not take any special role which you do not give to it. Its semantics are up for grabs. NOTHING in Python actually forces you to use None to denote "no value." And it is BY DESIGN that Python does not automatically type check everything. YOU must decide whether and how to type check arguments - not at all, by using your own decorators or asserts or some library, or by not using Python. Python isn't a bondage and discipline language. If you don't like that, don't use it, it's just that simple. There's no need to call it embarrassing, or gloat about how you schooled somebody who showed interest in your favorite language.

So. If you use the return value of a function without a return statement, you are asking for a value which may be None, the same as if you had written 'return None'. You bear responsibility for that decision - the same as you bear responsibility for feeding int(4) or a module object to your functions. If you don't like that, then don't do it.

Under normal circumstances, without doing anything special, you will get something like a TypeError if someone (e.g. you) feeds a None to a function not anticipating it.

You only have to handle that in the case where it is vitally important to have a different exception or other behavior. You don't need "six hundred and forty nine thousand two hundred and eighty-eight if statements" unless you are being needlessly compulsive to begin with, in a vain effort to emulate a bondage-and-discipline language. Python isn't even supposed to be a bondage-and-discipline language, so it's no revelation that it isn't good at that. Trying to use it that way is just doing it wrong.

(n.b. Instead of using imperative if-statements, you might prefer: f(v) if v else None, for those instances where it's even necessary).

Dear Author:

It's cool that you are proud of yourself, but in this case I think your advocacy is being hurt by your ego. I have never gotten the impression that Haskell programmers in general are smug and boastful. If YOU don't want to be thought of as smug and boastful, then don't publish articles like this where you are smugly bragging about who you schooled.

Re: The Day Python Embarassed Imperative Programming

#72
post #15

Earlier quoted context omitted.

It does come with an overhead for a beginner, to be sure. But because it is a consistent abstraction we can build idioms on top of the concept of a monad, and in doing so it actually becomes easier to reason about. The best things in life have a learning curve. Edit: Wow, I was downvoted for this?

(not downvoter) I come to completely the opposite conclusion: http://williamedwardscoder.tumblr.com/post/18319031919/progr... There's nothing stopping someone writing a haskell-alike with readable syntax as long as they stay away from trying to create terms like monads to explain things that don't need explaining ;)

> There's nothing stopping someone writing a haskell-alike with readable syntax as long as they stay away from trying to create terms like monads to explain things that don't need explaining ;)

There's nothing stopping someone from doing that while trying to create such terms, either; witness Haskell. (Or maybe your argument is that the syntax isn't readable? Well, is `>>=` really worse than `?:` in terms of immediate apprehensibility?)

However, I think it's important to recognise that the use of 'monad' is not a case of "creat[ing] terms … to explain things that don't need explaining". A pattern was identified, and it was realised that it fit into the existing mathematical formalism of monads (http://en.wikipedia.org/wiki/Monad_%28category_theory%29).

This can hardly be regarded as a willfully abstruse activity; identifying and naming existing patterns, especially if the name is already out there, is part of a (good) computer programmer's toolkit, right? http://en.wikipedia.org/wiki/Design_Patterns

Re: The Day Python Embarassed Imperative Programming

#73
Shouldn't `hamon2` be

    hamon2 f (Just x) = f x
    hamon2 f Nothing  = Nothing
? The author's definition doesn't seem to typecheck if `f :: a -> Maybe b` (as in `(>>=)`).

EDIT: Ah, I see; looking at the blackboard picture suggests that the author has confused `(>>=) :: Monad m => m a -> (a -> m b) -> m b` with `fmap :: Functor m => (a -> b) -> m a -> m b`.

Re: The Day Python Embarassed Imperative Programming

#74

Perhaps the author is just glossing over the bigger picture for the sake of explanation, but it's a bit of a narrow view of monads to say that they are just "conditional function calls". That's true if the monad in question is Maybe, Either e, or (if you're squinting at it just right) []. But >>= in the State s and IO monads, for instance, has little to do with conditionally calling functions; there, it's more about…

I completely agree. It's hard for beginners to learn that a monad isn't a thing, it's an property that can apply to many different things. A monad is so general it's hard to have a single intuition about it.

I think perhaps another reason why beginners find monads so hard to understand, especially those coming from a math background, is that >>= is a bizarre presentation of monads. I think, for example, defining a monad as an applicative with a join operation would have been a much better idea - most monads, like Maybe or [], make the most sense to me as "containers" that can be joined. The bind operator never really made intuitive sense to me when thinking about a monad as a container with a structure. Plus, to me, m (m a) -> m a is a lot easier to recognize than m a -> (a -> m b) -> m b.

This is especially true since applicatives are now becoming a very popular language idiom. It seems unfair to beginners to make them try to understand applicatives and then make them learn an unrelated typeclass for monads, when mathematically the two are very similar objects.

Re: The Day Python Embarassed Imperative Programming

#75

Earlier quoted context omitted.

Well, that's the idea of monads -- you can see them everywhere because their original purpose is to express imperative programming mathematically. It's like thinking that all numbers can be represented with digits; of course -- digits were invented to represent all numbers. But the thing that makes Haskell unique is not that you have explicit monads. It's that you can (1) use monads other than the IO monad (like Mayb…

I'm not disputing that Haskell makes it easier, but from a practical perspective I'd challenge the idea that nullability can't be turned off in Java with @NotNull annotations (and nullability inference tools like JastAdd[0]), or with decorators in Python. Do you see an essential difference in kind, or just a spectrum of ease of reasoning? [0] http://jastadd.org/web/jastaddj/extensions.php

Would you mind expounding on that use of decorators? I'm not making the connection and it sounds like an interesting one.

Re: The Day Python Embarassed Imperative Programming

#76
post #75

Earlier quoted context omitted.

I'm not disputing that Haskell makes it easier, but from a practical perspective I'd challenge the idea that nullability can't be turned off in Java with @NotNull annotations (and nullability inference tools like JastAdd[0]), or with decorators in Python. Do you see an essential difference in kind, or just a spectrum of ease of reasoning? [0] http://jastadd.org/web/jastaddj/extensions.php

Would you mind expounding on that use of decorators? I'm not making the connection and it sounds like an interesting one.

Sure, it's just a specific kind of type-checking decorator in the same vein as the ones you can see at e.g. [0]. Obviously it can be made a lot more sophisticated to only pick up certain arguments. You can do a similar thing with metaclasses to prevent object attributes being set as None, too.

  def isnotnone(fn):
    def decorator(*args, **kwargs):
      for arg in args:
        if arg is None:
          raise TypeError("{0} does not accept None".format(fn.func_name))
      for arg in kwargs.values():
        if arg is None:
          raise TypeError("{0} does not accept None".format(fn.func_name))
      return fn(*args,**kwargs)
    return decorator

  @isnotnone
  def f(a, b=dict):
    return a(), b()

  >>> f(None)
  Traceback (most recent call last):
    File "", line 1, in 
    File "", line 5, in decorator
  TypeError: f does not accept None
  >>> f(b=None)
  Traceback (most recent call last):
    File "", line 1, in 
    File "", line 8, in decorator
  TypeError: f does not accept None
  >>> f()
  Traceback (most recent call last):
    File "", line 1, in 
    File "", line 9, in decorator
  TypeError: f() takes at least 1 argument (0 given)
  >>> f(str)
  ('', {})
  >>>
[0]http://code.activestate.com/recipes/454322-type-checking-dec...

Re: The Day Python Embarassed Imperative Programming

#77
post #75

Earlier quoted context omitted.

Would you mind expounding on that use of decorators? I'm not making the connection and it sounds like an interesting one.

Sure, it's just a specific kind of type-checking decorator in the same vein as the ones you can see at e.g. [0]. Obviously it can be made a lot more sophisticated to only pick up certain arguments. You can do a similar thing with metaclasses to prevent object attributes being set as None, too. def isnotnone(fn): def decorator(*args, **kwargs): for arg in args: if arg is None: raise TypeError("{0} does not accept None…

Thanks!

Re: The Day Python Embarassed Imperative Programming

#78
post #72

Earlier quoted context omitted.

(not downvoter) I come to completely the opposite conclusion: http://williamedwardscoder.tumblr.com/post/18319031919/progr... There's nothing stopping someone writing a haskell-alike with readable syntax as long as they stay away from trying to create terms like monads to explain things that don't need explaining ;)

> There's nothing stopping someone writing a haskell-alike with readable syntax as long as they stay away from trying to create terms like monads to explain things that don't need explaining ;) There's nothing stopping someone from doing that while trying to create such terms, either; witness Haskell. (Or maybe your argument is that the syntax isn't readable? Well, is `>>=` really worse than `?:` in terms of immediat…

And python should be embarrassed how exactly?

Re: The Day Python Embarassed Imperative Programming

#79

Earlier quoted context omitted.

m a -> (a -> m b) -> m b Okay, so what does this mean? I thought it was `f x -> x * x` is a function definition, right? Or am I completely mistaken here? Because in the above code, what is the function name, the parameter and the return value? I know "everything is a function" in Haskell but I really can't see through the multiple arrows here. Any help?

This is one of those things that functional-programming people seem to "get" without ever making the explanation very clear. First of all, this is a function declaration (ie. prototype), not a definition. So this is describing a function type, not a function implementation. But that doesn't help very much because it's still not very obvious what the function type means. The shortcut way to understanding Haskell funct…

Thank you! It's coming back to me now :) This was taught to me in college, I know about currying, the right-associativity was the big part I missed!

Re: The Day Python Embarassed Imperative Programming

#80
post #72

Earlier quoted context omitted.

> There's nothing stopping someone writing a haskell-alike with readable syntax as long as they stay away from trying to create terms like monads to explain things that don't need explaining ;) There's nothing stopping someone from doing that while trying to create such terms, either; witness Haskell. (Or maybe your argument is that the syntax isn't readable? Well, is `>>=` really worse than `?:` in terms of immediat…

And python should be embarrassed how exactly?

I never said anything about embarrassment; I was just defending the virtue of using existing names to recognise pre-explored patterns, even if they frighten people.
Post reply on HN