4 ms·
I still get a real kick out of Ruby's elegant and powerful metaprogramming, which is something other languages don't often compare to. class String
by nixpulvis 5y ago
I still get a real kick out of Ruby's elegant and powerful metaprogramming, which is something other languages don't often compare to.
class String
def colorize(color_code)
"\e[#{color_code}m#{self}\e[0m"
end
end
The general advice is to avoid confusing others though, so changing base classes like this is not really a business-safe idea.
- shagie 5y agoIs there a good way to verify that all of the code is business-safe?
- nixpulvis 5y agoDelete it? Otherwise no. But this is true of any language. The truth is in the middle ground.
- shagie 5y agoIt's not entirely true of any language. In Java, for example, one can do static analysis and identify when a class is doing reflection... and flag as an error if the class is doing reflection on a class that is an instance of java.something.
- bradstewart 5y agoHow do you define "business safe"? Java won't prevent you from sending a message to the wrong customer or something like that.
- shagie 5y agoI can look at the code and see if anyone is doing: Class cache = Integer.class.getDeclaredClasses()[0]; Field c = cache.getDeclaredField("cache"); c.setAccessible(true); I can examine to see that java.lang.{something} class is getting reflected on. I can check to see if anything is calling getDeclaredField and flag that. I can see the setAccessible and really flag that. This isn't about coding errors. This is about being able to analyze the code and see if the code is using prohibited methods. Through static analysis, I can verify if anyone is trying to do something tricky with the String class. Can I verify if a method is being modified added to an instance of a String in Ruby through static analysis?
- WJW 5y agoI don't know of anyone actually doing that, but all the code is right there. You could probably wrangle the linter into checking those things if you really want to. That said, many Ruby frameworks rely on being able to dynamically add methods to classes at runtime so I don't think such a thing would be all that beneficial.
- slx26 5y agoAnd besides general craziness and DSLs as pointed above, you can also easily experiment with relatively complex language-level constructs, like derived attributes or cacheable functions [talked a bit about it here https://news.ycombinator.com/item?id=22338923 https://news.ycombinator.com/item?id=22338923]. Trying to make such experiments safe in Ruby would be unwise, but starting them in Ruby is happiness.
- sealthedeal 5y agoI do love this. The ability to change base classes so easily is such a "With great power comes great responsibility" lol.
- agumonkey 5y agoThat's pretty smalltalkish, also with the trend of extension functions you get that more often these days. I remember doing such things in kotlin. Maybe not perfect for large projects but a real pleasure for developpers.
- matsemann 5y agoWhat's nice about extension functions in Kotlin is that they are statically imported. So you're not really modifying the class, and there is no danger of collisions (like it was when people monkey-patched javascript built-ins back in the day).
- modal-soul 5y agoRuby's refinements sound somewhat similar; they let you scope your monkey-patches.
- sadfev 5y agoRuby is Smalltalk becoming successful. Ruby meta programming is very nice. Ruby is OO both internally and externally. Unlike Python which doesn’t feel very OO.
- blacktriangle 5y agoRuby is Smalltalk jettisoning everything that makes Smalltalk awesome.
- bitwize 5y agoA major difference between Smalltalk and Ruby is that in Smalltalk, the live system knows its own source code, and you program through the live running system. Ruby doesn't really do this, it's more of a scripting language with Smalltalk semantics. Ruby source reads like Monticello changesets, a suboptimal format for exploring and modifying a dynamic object system.
- burlesona 5y agoSupposing you need to do this kind of stuff a lot, one fairly nice workaround is to subclass the base class and then use that subclass when you need added mutative and/or chain able functionality. The drawback in this case is it's not as concise as just typing in a String literal :)