

I hate NULL and all its variants ... quick hack to alleviate the pain in Python - bad_user
http://blog.alexn.org/2010/05/i-hate-null-and-all-its-variants-heres.html

======
xenophanes
In Ruby I defined these on Object. A little ugly if you are doing a long
chain, but works fine in many cases.

    
    
      def if_present?
        # example: User.find_all_by_something.if_present? || User.find_all_by_something_else
        self  if present?
      end
    
      def send_if_respond_to(method, *args)
        # example: string_or_nil.send_if_respond_to(:strip)
        send(method, *args)  if respond_to?(method)
      end

~~~
jey
<http://andand.rubyforge.org/>

------
alrex021
Purely FP lang guys are having a good laugh now. :)

~~~
chadaustin
Why? I know short comments are easy, but you have a real opportunity here to
teach us something new. Can you elaborate?

~~~
pyre
I'm assuming b/c purely FP languages have handled this for a long time without
the need to program around the language.

~~~
bad_user
Monad comprehensions are not necessarily a trait of purely FP languages.

Yes, in Haskell or F# (the 2 languages I've played with) ... monads are so
natural you don't even notice them many times. But this goes both ways, what's
natural to do in Python, isn't so in other languages.

Also in this particular case you're not programming around the language ...
dynamic OOP languages are all about late-binding, that's their strength. If
you're using something like Python as if it were Java, you're missing on lots
of useful stuff.

~~~
pyre
Sorry. My entire statement was an assumption as I have little experience with
functional programming outside of fooling around with my xmonad.hs file. I was
just responding with that I took from the GP comment.

------
rglullis
Ignoring the memo part here and focusing on having None/empty list as a return
value, what is the problem of doing:

    
    
        soup.find('table', {'class':'search-params'}).findParent('form')\
        .find('td', {'class': 'elem'})\
        .find('input')\
        .get('name') or raise WebUIError("Web interface specification changed")
    
    

Shouldn't the boolean expression short-circuit and only raise WebUIError in
case the expression returns what he doesn't want to?

~~~
natrius
Any of those find calls can return None. None does not have a find method.

~~~
jey
This sounds more like a design flaw in BeautifulSoup than anything else. The
OP is wrong in directing his anger towards NULL/None/nil. (BeautifulSoup
should be returning an empty collection, not None.)

~~~
njharman
Bingo!

This api fail drives me crazy when using BS. Esp since it's otherwise pretty
slick.

------
Periodic
What you really want in this case is a way to overload the "." operator. If it
were just an alias for call you could change None to respond to call on an
undefined method with None. That would sort of short-circuit the chain and
avoid these errors.

It might require a few changes elsewhere as you would be getting None where
you used to get an error, but relying on the error might have been some lazy
programming to begin with.

~~~
njharman
Rather than localizing change to one api and requiring explicit effort to do
so. That makes the change global and transparent, affecting all code (your
code, std lib, 3rd party lib).

It's really, really not what you want. Or at least not what the poor guy who
has to maintain your poorly monkey patched code.

~~~
jerf
Not in Python, because you wouldn't globally override it. You would just
override the __getattr__ of the appropriate objects and be done with it, and
nothing else would be affected. If you want it to be isolated a bit of work
with "with" would make it easy.

Though I would go an entirely different direction, personally, something like:

    
    
        f = self.find
        result = maybe_apply((f, ('table', {'class': ...})),
                             (f, ('td', {'class': 'elem'})),
                             (f, ('input',)),
                             (self.get, ('name',)))
    

Explicit is better than implicit. For bonus points, the "query" is now
reusable and programmatically manipulable, which in my experience outweighs
the ugly factor.

~~~
bad_user
What do you mean by "reusable"?

You're basically using Python as if it were Lisp, which is kind of ugly :)

~~~
jerf
The "qeury" has been reified as data. Now you can do whatever you want to it,
including assign it to a variable.

Sometimes the ugly tradeoff is OK, even in Python. In this case it is still
less ugly than the code it is replacing, if you write correct code. Doing one
little piddly-ass thing (running one method), then copy/pasting in the same
four lines of error handling after every single one, well, it may be
aesthetically pleasing on your screen but it's far uglier than what I've
shown.

Python has many advantages, but it isn't perfect.

