<commit_before>== Decorators ==

Golo feature Python-like decorators.

=== Presentation ===

Decorators are similar in syntax and purpose to Java annotations.
However, the concepts behind them are very different. Indeed, whereas Java
annotations are compiler or VM directives, decorators are actually plain
functions, more precisely higher order functions. 

NOTE: Higher order functions are functions that process functions, i.e. that take a
function as parameter, and may return a new function.

A decorator is thus a function that take the function to decorate as parameter,
and return a new function, generally a wrapper that do some stuffs before or
after calling the original function.

To be the most generic, a decorator should be a variable arity function, and
thus call the decorated function with `invokeWithArguments`.

The name can remind the well known 
http://en.wikipedia.org/wiki/Decorator_pattern[GoF pattern], with good reason.
This pattern describe a design that allow an object to be augmented by wrapping
it in an other object with the same interface, delegating operations to the
wrapped object. This is exactly what a decorator does here, the interface
being "function".


=== Principles and Syntax ===

As in Python, and similarly to Java annotations, a decorator is used with a
`@` prefix before the function definition. As an example, the decorator
`deco1` only prints its name before returning the result unchanged

[source,golo]
----
function deco1 = |fun| {
  return |args...| {
    print("deco1 + ")
    return fun: invokeWithArguments(args)
  }
}
----

It can be used as:

[source,golo]
----
@deco1
function foo = |a| {
  return "foo: " + a
}
----

Here, calling `println(foo(1))` will print `deco1 + foo: 1`.

As illustrated, the decorator is just a wrapper (closure) around the decorated
function. The `@` syntax is just syntactic sugar. Indeed, it can also be used
as such:

[source,golo]
----
function bar = |a| -> "bar: " + a

function main = |args| {
  println(deco1(^bar)(1))

  let decobar = deco1(^bar)
  println(decobar(1))

  println(deco1(|a| -> "bar: "+a)(1))
}
----

prints all `deco1 + bar: 1`.

Decorator can also be stacked. For instance:

[source,golo]
----
function deco2 = |fun| {
  return |args...| {
    print("deco2 + ")
    return fun: invokeWithArguments(args)
  }
}

@deco2
@deco1
function baz = |a| -> "baz: " + a
----

`println(baz(1))` will print `deco2 + deco1 + baz: 1`


Moreover, since decorator are just higher order functions, they can be closure
on a first argument, as illustrated in the following listing:

[source,golo]
----
module testdeco

function log = |msg| {
  return |fun| {
    return |args...| {
      println(msg)
      return fun: invokeWithArguments(args)
    }
  }
}

@log("calling foo")
function foo = |a| {
  println("foo got a " + a)
}

@log("I'am a bar")
function bar = |a| -> 2*a

function main = |args| {
  foo("bar")
  println(bar(21))
}
----

will print 

----
calling foo
foo got a bar
I'am a bar
42
----

Here, `log` create a closure on the message, and return the decorator function.
Thus, `log("hello")` is a function that take a function as parameter, and
return a new function printing the message (`hello`) before delegating to the
inner function.


=== Use Cases and Examples ===

==== Aspect oriented programming ====

==== Pre/post conditions checking ====

==== Memoization ====

==== Logging ====

==== Locking ====

[source,golo]
----
import java.util.concurrent.locks

function withLock = |lock| {
  return |fun| {
    return |args...| {
      lock: lock()
      try { 
        return fun: invokeWithArguments(args) 
      } finally { 
        lock: unlock() 
      }
    }
  }
}

let myLock = ReentrantLock()

@withLock(myLock)
function foo = |a, b| {
    return a + b
}
----

==== Generic context ====

Decorators can be used to define a generic wrapper around a function. This
functionality is provided by the `gololang.Decorators.withContext` standard decorator. This
decorator take a context, such as the one returned by
`gololang.Decorators.defaultContext` function.

A context is an object with 4 defined methods:

* `entry`, that takes and returns the function arguments. 
         This method can be used to check arguments or apply transformation to them;
* `exit`, that takes and returns the result of the function. 
          This method can be used to check conditions or transform the result;
* `catcher`, that deal with exceptions that occurs during function execution. It
         takes the exception as parameter;
* `finallizer`, that is called in a `finally` clause after function execution.

The context returned by `gololang.Decorators.withContext` is a void one, that
is `entry` and `exit` return their parameters unchanged,
`catcher` rethrow the exception and `finallizer` does nothing.

The workflow of this decorator is as follow:

. the context `entry` method is called on the function arguments;
. the decorated function is called with arguments returned by `entry`;
  .. if an exception is raised, `catcher` is called with it as parameter;
  .. else the result is passed to `exit` and the returned value is returned
. the `finallizer` method is called.

Any of theses methods can modify the context internal state.

Here is an usage example:

[source,golo]
----
module testcontext

import gololang.Decorators

let myContext = defaultContext():
  define("entry", |this, args| {
    println("hello")
    return args
  }):
  define("exit", |this, result| { 
    require(result >= 3, "wrong value")
    println("goobye")
    return result
  }):
  define("catcher", |this, e| {
    println("Caught " + e)
    throw e
  }):
  define("finallizer", |this| {println("do some cleanup")})


@withContext(myContext)
function foo = |a, b| {
  println("Hard computation")
  return a + b
}

function main = |args| {
  println(foo(1,2))
  println("====")
  println(decorators.withContext(myContext)(|a| -> 2*a)(3))
  println("====")
  try {
    println(foo(1, 1))
  } catch (e) { }
}
----

which prints

----
hello
Hard computation
goobye
do some cleanup
3
====
hello
goobye
do some cleanup
6
====
hello
Hard computation
Caught java.lang.AssertionError: wrong value
do some cleanup
----


=== Under the hood ===

(Implementation) Useful? If so, TBD by @artpej


=== Performance issues ===

<commit_msg>notes on parametrized decorators<commit_after>== Decorators ==

Golo feature Python-like decorators.

=== Presentation ===

Decorators are similar in syntax and purpose to Java annotations.
However, the concepts behind them are very different. Indeed, whereas Java
annotations are compiler or VM directives, decorators are actually plain
functions, more precisely higher order functions. 

NOTE: Higher order functions are functions that process functions, i.e. that take a
function as parameter, and may return a new function.

A decorator is thus a function that take the function to decorate as parameter,
and return a new function, generally a wrapper that do some stuffs before or
after calling the original function.

To be the most generic, a decorator should be a variable arity function, and
thus call the decorated function with `invokeWithArguments`.

The name can remind the well known 
http://en.wikipedia.org/wiki/Decorator_pattern[GoF pattern], with good reason.
This pattern describe a design that allow an object to be augmented by wrapping
it in an other object with the same interface, delegating operations to the
wrapped object. This is exactly what a decorator does here, the interface
being "function".


=== Principles and Syntax ===

As in Python, and similarly to Java annotations, a decorator is used with a
`@` prefix before the function definition. As an example, the decorator
`deco1` only prints its name before returning the result unchanged

[source,golo]
----
function deco1 = |fun| {
  return |args...| {
    print("deco1 + ")
    return fun: invokeWithArguments(args)
  }
}
----

It can be used as:

[source,golo]
----
@deco1
function foo = |a| {
  return "foo: " + a
}
----

Here, calling `println(foo(1))` will print `deco1 + foo: 1`.

As illustrated, the decorator is just a wrapper (closure) around the decorated
function. The `@` syntax is just syntactic sugar. Indeed, it can also be used
as such:

[source,golo]
----
function bar = |a| -> "bar: " + a

function main = |args| {
  println(deco1(^bar)(1))

  let decobar = deco1(^bar)
  println(decobar(1))

  println(deco1(|a| -> "bar: "+a)(1))
}
----

prints all `deco1 + bar: 1`.

Decorator can also be stacked. For instance:

[source,golo]
----
function deco2 = |fun| {
  return |args...| {
    print("deco2 + ")
    return fun: invokeWithArguments(args)
  }
}

@deco2
@deco1
function baz = |a| -> "baz: " + a
----

`println(baz(1))` will print `deco2 + deco1 + baz: 1`


Moreover, since decorator are just higher order functions, they can be closure
on a first argument, i.e. parametrized decorators, as illustrated in the following listing:

[source,golo]
----
module testdeco

function log = |msg| {
  return |fun| {
    return |args...| {
      println(msg)
      return fun: invokeWithArguments(args)
    }
  }
}

@log("calling foo")
function foo = |a| {
  println("foo got a " + a)
}

@log("I'am a bar")
function bar = |a| -> 2*a

function main = |args| {
  foo("bar")
  println(bar(21))
}
----

will print 

----
calling foo
foo got a bar
I'am a bar
42
----

Here, `log` create a closure on the message, and return the decorator function.
Thus, `log("hello")` is a function that take a function as parameter, and
return a new function printing the message (`hello`) before delegating to the
inner function.

Again, since all of this are just functions, you can create shortcuts:

[source,golo]
----
let sayHello = log("Hello")

@sayHello
function baz = -> "Goodbye"
----

A call to `println(baz())` will print 

----
Hello
Goodbye
----


=== Use Cases and Examples ===

==== Aspect oriented programming ====

==== Pre/post conditions checking ====

==== Memoization ====

==== Logging ====

==== Locking ====

[source,golo]
----
import java.util.concurrent.locks

function withLock = |lock| {
  return |fun| {
    return |args...| {
      lock: lock()
      try { 
        return fun: invokeWithArguments(args) 
      } finally { 
        lock: unlock() 
      }
    }
  }
}

let myLock = ReentrantLock()

@withLock(myLock)
function foo = |a, b| {
    return a + b
}
----

==== Generic context ====

Decorators can be used to define a generic wrapper around a function. This
functionality is provided by the `gololang.Decorators.withContext` standard decorator. This
decorator take a context, such as the one returned by
`gololang.Decorators.defaultContext` function.

A context is an object with 4 defined methods:

* `entry`, that takes and returns the function arguments. 
         This method can be used to check arguments or apply transformation to them;
* `exit`, that takes and returns the result of the function. 
          This method can be used to check conditions or transform the result;
* `catcher`, that deal with exceptions that occurs during function execution. It
         takes the exception as parameter;
* `finallizer`, that is called in a `finally` clause after function execution.

The context returned by `gololang.Decorators.withContext` is a void one, that
is `entry` and `exit` return their parameters unchanged,
`catcher` rethrow the exception and `finallizer` does nothing.

The workflow of this decorator is as follow:

. the context `entry` method is called on the function arguments;
. the decorated function is called with arguments returned by `entry`;
  .. if an exception is raised, `catcher` is called with it as parameter;
  .. else the result is passed to `exit` and the returned value is returned
. the `finallizer` method is called.

Any of theses methods can modify the context internal state.

Here is an usage example:

[source,golo]
----
module testcontext

import gololang.Decorators

let myContext = defaultContext():
  define("entry", |this, args| {
    println("hello")
    return args
  }):
  define("exit", |this, result| { 
    require(result >= 3, "wrong value")
    println("goobye")
    return result
  }):
  define("catcher", |this, e| {
    println("Caught " + e)
    throw e
  }):
  define("finallizer", |this| {println("do some cleanup")})


@withContext(myContext)
function foo = |a, b| {
  println("Hard computation")
  return a + b
}

function main = |args| {
  println(foo(1,2))
  println("====")
  println(decorators.withContext(myContext)(|a| -> 2*a)(3))
  println("====")
  try {
    println(foo(1, 1))
  } catch (e) { }
}
----

which prints

----
hello
Hard computation
goobye
do some cleanup
3
====
hello
goobye
do some cleanup
6
====
hello
Hard computation
Caught java.lang.AssertionError: wrong value
do some cleanup
----


=== Under the hood ===

(Implementation) Useful? If so, TBD by @artpej


=== Performance issues ===


{'fraction_non_alphanumeric': 0.11659956642923505, 'fraction_numerical': 0.005884174667079591, 'mean_word_length': 3.611567297393788, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7355431', 'n_tokens_mistral': 4014, 'n_tokens_neox': 3860, 'n_words': 1600}