Hacker News new | ask | show | jobs
by rjn945 4324 days ago
I was really confused when I read "the constrain() call takes expressions that define the relationships you want to impose" (emphasis mine) and saw this code:

  container.constrain(button.TOP == container.TOP + 50)
Python doesn't let you pass expressions! Why isn't that just getting evaluated to true or false? Is this not vanilla Python? Is there a pre-processor?

I dove into the code and found the answer here[1]. button.TOP and container.TOP are both Toga Attributes, which have their equality operators redefined.

Very interesting and clever use of operator overloading.

[1] https://github.com/pybee/toga/blob/master/toga/constraint.py

5 comments

I am very conflicted about that trick. On the one hand it is a neat bit of syntax to express what you want, but it goes completely against your expectations of how Python syntax is parsed. 'Clever use of operator overloading' historically has always meant 'confusing use of operator overloading' - something the C++ community took some time to learn.

Python is very good at behaving as you expect it to, despite the fact that you can implement pretty much any magic. This is down to library design more than it is language design.

At least it's less magic than puLP:

  prob += x*2 + y, "foo"
This sets the objective function of prob to (2x+y), and assigns it a name of "foo".

  prob += x*2 + y > 3, "abcd"
That puts a constraint that 2x + y > 3, called "abcd".

On both of these the string is optional.

I'm also conflicted. On one hand, it's about the most compact syntax you can get for something like this - when similar libraries in languages without operator overloading resort to passing strings into functions... On the other hand, it can be utterly incomprehensible if you haven't gone through the documentation.

FWIW, I've seen the double-equals syntax in GSS as well. It's a common idiom in the constraint programming community; it's supposed to symbolize that the two sides change in sync -- container.TOP can change button.TOP or vice-versa.

I see your argument about overloaded operators being dangerous for newcomers, but the syntax isn't completely fabricated.

Thanks for the compliment. As others have pointed out, this isn't an idea of my own creation - others (e.g., SQLAlchemy) have taken similar approaches in other APIs. I'm just exploiting a pattern that I've seen used to good effect elsewhere.
some ORMs do operator overloading too, i.e. SQLAlchemy http://docs.sqlalchemy.org/en/rel_0_9/core/sqlelement.html
Google use operator overloading in their appengine stuff.