Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to monkey patch new control structures in Scala?

Tags:

scala

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
like image 361
Filipe Miguel Fonseca Avatar asked Nov 06 '11 16:11

Filipe Miguel Fonseca


People also ask

What is monkey patching give example?

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.

What is the monkey patching concept?

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.)

Why is it called monkey patching?

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).

What is monkey patching in Ruby?

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.


1 Answers

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.

like image 66
Rex Kerr Avatar answered Nov 03 '22 00:11

Rex Kerr