4 ms·
>some_array.has_my_thing() is better than has_my_thing(some_array). ? one of the reasons i prefer python to ruby. sorted(my_thing) will sort anything that can
by fernandotakai 5y ago
>some_array.has_my_thing() is better than has_my_thing(some_array). ?
one of the reasons i prefer python to ruby. sorted(my_thing) will sort anything that can be sorted. no need for monkey patching -- you just call it and, if it can be sorted, it will be sorted.
- matheusmoreira 5y agoIn Ruby, anything that can be sorted will respond to sort. So thing.sort will also sort anything that can be sorted. Python does the exact same thing, it just hides it from you using ugly __methods__ that the language itself will call by convention. What determines sortability? "Anything that can be sorted" just means anything that implements the __lt__ method. In Ruby, this method is called <=> and the Comparable module builds upon it.
- remram 5y agoNothing like sort is hidden in class methods in Python.
- radlad 5y agoThat's not true - Python implements sorted by calling `__lt__` on the object: https://docs.python.org/3/library/functions.html#sorted https://docs.python.org/3/library/functions.html#sorted
- int_19h 5y ago__lt__ is just the way to overload the comparison operator, which of course is going to be called by the sort. What OP is saying is that there's no __sort__ or anything like that.
- radlad 5y agoBut that's not really true either - there's __len__ which len() calls: https://docs.python.org/3/reference/datamodel.html#object.__len__ https://docs.python.org/3/reference/datamodel.html#object.__... You can add iterators with __iter__, reversed() calls __reversed__, etc.
- dwaite 5y agoSorted mandates the type you give it implements __iter__, aka that it is iterable. Ruby defines sort as a method on Enumerable. The difference is that most likely that CPython and CRuby started with different capabilities to map native implementations into the language. The biggest difference between the two is python adds more functions into the global namespace, while Ruby pushes pretty hard to encapsulate logic within types.
- remram 5y agoThe discussion is about how to provide additional functionality. To be sortable, you collection has to be a collection, and it has to have comparable elements. That has to be provided by the type itself. The difference between Python and Ruby is how to add more functions. If you make a library to sort collections (or format phone numbers), the Ruby way is to monkey-patch collections (or numbers). Whereas the Python way is to offer a free function that takes an iterable (or number). This is what we are discussing. Of course Python classes have methods.
- matheusmoreira 5y agoNo, pretty much everything in the language is hidden from you behind methods. This hidden magic is in many cases literally baked into the language's syntax. Iterables use functions like __len__ and __next__. The with keyword is just a thing that implicitly calls __enter__ and __exit__ on a context management object.
- remram 5y agoYes, sorted() will use methods like __iter__ and __lt__ provided by the object. But sorting is not provided by the object and is therefore not (quoting GP) "the exact same thing, just hidden from you in an ugly __method__".
- dragonwriter 5y ago> Nothing like sort is hidden in class methods in Python. The discussion has mostly been about instance methods defined in classes, and how do you define “like sort” in this claim? list.sort() is a method in Python; it's the equivalent of Array#sort! in Ruby.
- remram 5y agoThere is nothing that sorts hidden in dunder methods on objects, even if they can be sorted. `sorted()` will use intrinsic methods like `__iter__` and `__lt__` to sort a collection, but the op is claiming that even though the syntax is different (`sorted(obj)` rather than `obj.sort!`), it's "the exact same thing, it just hides it from you using ugly __methods__". To that I reply that no, there is no method to sort hidden in __methods__. This is not how functionality is added to classes in Python. If you want to add something that works on all iterables, you don't insert new methods in iterable classes, like you do in Ruby. That free-standing sorted() function really is a free-standing function, it is not actually a method "hidden in ugly __methods__".
- dragonwriter 5y ago> If you want to add something that works on all iterables, you don't insert new methods in iterable classes, like you do in Ruby. You don't in Ruby, either. If you want something that works on all Enumerables, you normally write an (instance or class/module) method on some other class or module that takes an argument that supports the methods provided by the Enumerable API. (In Python, you might do this or write a bare function, but Ruby doesn't have bare functions; it's possible to make proc objects in a library which is the nearest equivalent, but you’d almost never do that, because module methods are much more convenient.) In either Python or Ruby you might also monkey-patch existing classes to add functionality to the., and this is slightly more common in Ruby than Python, but because Python iterable, unlike Ruby Enumerables, don't have a common superclass that isn't shared with non-iterables, you couldn't easily do a “for all iterables” thing in Python [0] by monkey-patching because you don't have a good target to monkey-patch, whereas in Ruby you might do something for (nearly, because duck typing is a thing and it's possible someone could build an enumerable by implementing the whole API without mixing in the module) all enumerables, not by adding methods directly to individual enumerable classes, but by monkey-patching the Enumerable module itself. The main difference here is that Python (despite having support for mixins because it uses multiple inheritance) tends in it's core to use a mix of OO public APIs and procedural public APIs built on top of OO protocols using (often dunder) methods, rather than either consistently-OO or consistently procedural APIs, whereas Ruby is consistently OO and uses mixins to provide shared functionality building on a narrower protocol where Python would use a suite of functions. (Python tends to be more OO in its stdlib and third party libs than in its core, except specifically when supporting protocols defined in the core and consumed through built-in functions.) [0] except by monkey-patching object with code that tries to use the dunder methods that underlie the iteration protocol and fails if they don't exist, but while theoretically possible I don't think anyone would do that.
- runevault 5y agoDid they ever fix the arbitrary nature of monkey patching where last in wins? I've not touched ruby in years (and never seriously after I read up on how prevalent MP was).
- RangerScience 5y agoSort of. They introduced "refinements" as the thing you're supposed to do instead of monkeypatching, but AFAIK it doesn't get wide-spread usage. IME you don't usually do monkey-patching, although there are circumstances where it makes A LOT of sense (usually test suites). It's one of those sharp knives - safe if you plan out using it, dangerous if you don't.
- jacobsenscott 5y agoYes, they added refinements several years ago. That said I've been programming rails for probably 10 years, and I never see anyone use refinements, and I can count on one hand the number of times monkey patching has actually been a problem for me personally. I'm sure there are cases where it bit someone hard, but this is one of those things that a theoretically bad, but never seem to really have any impact in practice.
- lamontcg 5y agoI have to maintain code that was written by a developer who has long since left the space. He monkeypatched in stuff like Hash#dig years before it landed in ruby with a slightly different API and blew up the codebase. Since he was a pretty clever developer and had some wide experience in other languages he would monkeypatch in useful stuff from other languages -- but by doing that collisions with the core language are actually pretty frequent. Many people have the same clever idea when its really just copying some pattern that was successful in some other language. Awhile back I gutted the code and ripped out 60% of it, including all the monkeypatching and the maintanence burden on every ruby release dropped sharply. (And I'm assuming we're talking about the more polite kind of Monkeypatching where you're adding methods to global classes that are net-new, not the practice of opening up a class and scribbling over methods that you didn't write and replacing behavior, where should you should always mental picture your SemVer contract being lit on fire)
- int_19h 5y agosorted() will return a new collection. You still need to do foo.sort() in Python if you want to sort in-place.
- drusepth 5y agoDon't mind me, just adding the equivalent ruby code for readers to compare: array.sort # returns a new collection array.sort! # sorts in place (Ruby convention is to add a ! when methods directly modify the object they're called on.)
- dragonwriter 5y ago> Ruby convention is to add a ! when methods directly modify the object they're called on No, Ruby convention is to add a “!” when there is a “less safe” version of an operation, for which a “more safe” version exists without a “!”. Mutating versions of methods where a nonmutating version also exists are one common example, but not the only one, and mutating methods without a nonmutating counterpart don't get “!”.
- dwaite 5y ago> one of the reasons i prefer python to ruby. sorted(my_thing) will sort anything that can be sorted. no need for monkey patching sort() in ruby is declared on Enumerable. Sorted() in python is declared to take an iterable first parameter. They are pretty much equivalent, except python has built-in functionality to reverse the order of the output array, while ruby you would have to negate your sort function. Ruby however allows types to override sort, such as when the underlying type is a red black tree which is already sorted. For duck typing, you can also declare a compatible sort method on types which do not implement Enumerable - doing so in python would require a separate method.