Is it possible to monkey-patch a new control structure in Scala? Basically I want to define a couple of control structures, such as the following unless method, and have them accessible anywhere in my project.
def unless(condition: => Boolean)(body: => Unit):Unit = if(!condition) body
In Python, the term monkey patch refers to dynamic (or run-time) modifications of a class or module. In Python, we can actually change the behavior of code at run-time. We use above module (monk) in below code and change behavior of func() at run-time by assigning different value.
Monkey patching is a technique used to dynamically update the behavior of a piece of code at run-time. A monkey patch (also spelled monkey-patch, MonkeyPatch) is a way to extend or modify the runtime code of dynamic languages (e.g. Smalltalk, JavaScript, Objective-C, Ruby, Perl, Python, Groovy, etc.)
Etymology. Apparently from earlier guerilla patch (“code that sneakily changes other code”), understood as gorilla patch. A monkey patch was then a more carefully written instance of such a patch. Or simply derived from monkey (“to mess with”, verb).
In Ruby, a Monkey Patch (MP) is referred to as a dynamic modification to a class and by a dynamic modification to a class means to add new or overwrite existing methods at runtime. This ability is provided by ruby to give more flexibility to the coders.
You cannot monkey patch, which changes objects that already exist. However, you can write an implicit conversion that acts the same way (and is arguably safer) in most cases.
First of all, with unless
as written, you don't need it to be a method of every class. Just stick it in some object and import.
object Utility {
def unless(condition: => Boolean)(body: => Unit):Unit = if(!condition) body
}
import Utility._
But sometimes you do want it to act like a method on a class. For example, I often write
option.map(x => f(x)).getOrElse(default)
which could be more compactly written as a fold:
option.fold(default)(x => f(x))
except that Option
doesn't have fold. So I:
class OptionWrapper[A](o: Option[A]) {
def fold[Z](default: => Z)(action: A => Z) = o.map(action).getOrElse(default)
}
implicit def option_has_utility[A](o: Option[A]) = new OptionWrapper(o)
(this is called the "pimp my library" pattern). Now I can use fold to my heart's content, since any time there is an option and I call the fold
method, the compiler realizes that there is no fold
method and looks around for any way it can convert the class into something that does have a fold
. There is such a method, and the new class does to the existing option exactly what you would want from a fold
method on the class itself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With