> That said, Python is also smarter than me. The possibilities with monkey patching and duck typing are endless.
Don't do it, 99.9% of the time. It's that simple.
There is seldom a reason to use more than just defs - and a little syntactic sugar (like list comprehensions) just to keep it readable.
Even the use of classes is typically bad idea (if I do say so). Just because: there is no advantage to using it, except when everything is super dynamic. And if that's the case, I suggest that's a smell, indicating that one is trying to do to many things at once, not properly knowing the data.
Nevertheless using classes (or any other superfluous feature) makes everything more complicated (less consistent - need new ways to structure the program, new criterions whether to go for a class or not to or where to bolt methods on,...).
Don't use "mechanisms" like monkey patching just because they exist. They are actually not mechanisms - just curiosities arising from an implementation detail. The original goal is simplicity: Make everything be represented as a dict (in the case of python)
> The possibilities with monkey patching and duck typing are endless.
I think there are many more "obvious" ways to do things in Haskell than in Python just because you as a developer need to draw the line between static and dynamic. And if you later notice that you chose the line wrong, you have to rewrite everything.
In Python - or any other simple language - there is typically one obvious way to do things. At least to me.
Classes definitely give you a lot of rope to hang yourself with (metaclasses, inheritance, MULTIPLE inheritance), but they have their place. I'll usually start with a function, but when it gets too big, you need to split it up. Sometimes helper functions is enough, but sometimes you have a lot of state that you need to keep track of. If the options are passing around a kwargs dictionary, and storing all that state on the class, I know which I'd pick.
You can memoize methods to the instance to get lazy evaluation, properties can be explicitly defined up-front, and the fact that everything is namespaced is nice. You can also make judicious use of @staticmethod to write functional code whenever possible.
You can always opt for explicit dict passing. You are right that it's more typing work (and one can get it wrong...), but the resulting complexity is constant in the sense that it is obvious upfront, never growing, not dependent on other factors like number of dependencies etc.
When opting for explicit, complexity is not hidden and functions are not needlessly coupled to actual data. Personally I'm much more productive this way. Also because it makes me think through properly so I usually end up not needing a dict at all.
Regarding namespacing, python modules act as namespaces already. Also manual namespacing (namespacename+underscore) is not that bad, and technically avoids an indirection. I'm really a C programmer, and there I have to prefix manually and that's not a problem.
Yup, this open field to do whatever with meta classes, inheritance, properties, etc. was what hanged my interest. Since all this "multiple meta monkey patching" was possible, there was no way of telling (for me) what's a good way to implement something in an elegant way. Simple was not good enough, but complex had no rules.
Don't do it, 99.9% of the time. It's that simple.
There is seldom a reason to use more than just defs - and a little syntactic sugar (like list comprehensions) just to keep it readable.
Even the use of classes is typically bad idea (if I do say so). Just because: there is no advantage to using it, except when everything is super dynamic. And if that's the case, I suggest that's a smell, indicating that one is trying to do to many things at once, not properly knowing the data.
Nevertheless using classes (or any other superfluous feature) makes everything more complicated (less consistent - need new ways to structure the program, new criterions whether to go for a class or not to or where to bolt methods on,...).
Don't use "mechanisms" like monkey patching just because they exist. They are actually not mechanisms - just curiosities arising from an implementation detail. The original goal is simplicity: Make everything be represented as a dict (in the case of python)
> The possibilities with monkey patching and duck typing are endless.
I think there are many more "obvious" ways to do things in Haskell than in Python just because you as a developer need to draw the line between static and dynamic. And if you later notice that you chose the line wrong, you have to rewrite everything.
In Python - or any other simple language - there is typically one obvious way to do things. At least to me.