From: Logan Capaldo Date: 2006-05-07T03:43:25+09:00 Subject: Re: Sharp knives and glue On May 6, 2006, at 12:30 PM, Leslie Viljoen wrote: > On 5/6/06, Dick Davies wrote: >> On 06/05/06, Leslie Viljoen wrote: >> >> > ie. my function needs strings in culy braces. So the natural >> thing for >> > me would be this: >> > >> > class String >> > def curlify >> > "{"+self+"}" >> > end >> > end >> > >> > This is where I need the curlies and it makes sense for them to >> be there. >> >> But then you've tampered with the very fabric of reality (HPL >> would be >> proud) [1]. >> >> You could just modify the object you were passed: >> >> def func_that_needs_strings_to_have_a_curlify_method(str) >> def str.curlify >> "{" + self + "}" >> end >> >> # do something with str >> end >> >> This has the side effect on permanently adding a curlify method to >> whatever >> str points at, but not all Strings in the universe. >> >> You might not want that, of course - but it has less impact than >> modifying all strings. (If you only wanted that method to apply >> with your >> function, you could dup the object you were passed before meddling >> with it. > > Yes... and if I have 50 functions that need curlify? How would I add > curlify to all strings that are passed to methods in my module, for > example? > I've been thinking about this recently. #curlify and friends aren't really instance methods for strings, but the functuality isn't dramatically different enough to create a subclass. What curlify really is, is a function that we want to be able to call like str.curlify instead of curlify(str). Ruby already has a mechanism for declaring 'functions', private methods on object. Why not use that? You don't even _have_ to write it def curlify(str) "{#{str}}" end you can do this: public def curlify "{#{self}}" end This has many advantages over monkeying about in other classes. first, as a general rule people expect you to add methods to Object (it's how ruby does top level functions after all) Secondly, it won't kill any pre-existing definition of curlify. Any other class that does it's own curlify is going to override it, so it's safe from your meddling. Consider the case that curlify is added to core, but does some thing else, some thing else useful to other String methods, and is used in the new implementations of many of them. You won't have broken String since your curlify is higher in the inheritance chain, the only thing that will have been broken is your curlify, which will probably be easier to spot, since there's a good chance you wrote unit tests for your curlify (but probably not for every method in the String class). Now, I know it looks funny not having this method inside a class, but it doesn't realy belong in String anyway, and in pretty much any other language you would have made it a function ( curlify(str) ) or sub-classed String. It's only because of ruby's openn classes that people get encouraged to change core classes to make life easier. I figure public def meth(...) end is even easier, and less typing than class SomeClass def meth(...) end end and it puts it in the same territory as top-level functions (e.g. this is for this particular program's convenience.) Plus if you want to avoid namespace pollution just stick this methods in a module and include the module e.g. module Curlify def curlify "{#{self}}" end end include Curlify