<commit_before>h1. rewrite

h1. &#x2192; 'rewrite'


h2. What

Rewrite adds sexp-rewriting metaprogramming to Ruby. Or in plain English, Rewrite is a collection of features for Ruby programming like an implementation of "andand":http://andand.rubyforge.org. What makes Rewrite's versions of these features different and possibly useful is that they are implemented by rewriting your Ruby code rather than by opening up classes like Kernel, Object, Nil, or Symbol.


h2. Installing

<pre syntax="ruby">sudo gem install rewrite</pre>

h2. The basics

In your environment.rb file (Rails) or at the top of your source code file, include @Rewrite::With@ and @Rewrite::Prelude@:

<pre syntax="ruby">
include Rewrite::With
include Rewrite::Prelude
</pre>This makes the @with@ method available to your souce code, so you can write:

<pre syntax="ruby">
with(andand) do
	...
	first_name = Person.find_by_last_name('Braithwaite').andand.first_name
	...
end
</pre>The special magic here is that instead of opening up the Object and Nil classes to add _#andand_, Rewrite rewrites the ruby code inside the do/end block so that it looks roughly like this:

<pre syntax="ruby">
with(andand) do
	...
	first_name = lambda { |__1234567__|
		if __1234567__.nil?
			nil
		else
			__1234567__.first_name
		end
	}.call(Person.find_by_last_name('Braithwaite'))
	...
end
</pre>That's a big win because you can use the metaprogramming features you want without worrying that you are breaking anybody else's code. If you use an implementation of #andand that relies on opening the Object and Nil classes, how do you know you aren't (a) breaking some other code somewhere else, or (b) exposing your code to being broken if something else changes the #andand methods?

h2. What problem does rewrite solve?

Recall that when you use the “standard” implementation of things like "andand":http://andand.rubyforge.org/ or "try":http://ozmm.org/posts/try.html, you are openly modifying core classes like Object.

Therefore, you are reaching out and touching every line of code in your project. You probably aren’t breaking everything, but even if the chance of introducing a bug by adopting something like “try” is infinitesimal for each source code file in your project, the chance grows greater and greater as your application grows.

The problem is that you are introducing a change on Object, and everything depends on object. This is very different than introducing a change in your code. In that case, only the other bits of code that directly depend on your code are at risk.

Also, imagine if you introduce try and are careful not to break anything. Now somebody else wakes up one day and decides they need a method that works like Prototype’s "Try.these":http://www.prototypejs.org/api/utility/try-these. They call it “try.” They just broke your code, dude! Not only are you making everything dependant upon your version of try, but your code is dependent upon everyone else not breaking try as well. It’s a train-wreck waiting to happen.

Rewrite restricts things like andand or try to your code and your code alone. Sure, if you introduce a bug in your code, you may break things that directly depend on your code. But if you introduce “try” using rewrite instead of modifying Object, you will not reach out across your project and break something entirely unrelated that happens to have defined its own version of try in a completely different way.

h2. called_by_name

See "Macros, Hygiene, and Call By Name in Ruby":http://github.com/raganwald/rewrite/tree/master/called_by_name.markdown for details, more docs to come presently...

h2. Unhygienic rewriting

A new feature every much like a new human being: Vulnerable, disruptive, and a complete mess:

<pre syntax="ruby">
include Rewrite::With

andand = Rewrite::ByExample::Unhygienic.
  from(:receiver, :message, [:parameters]) {
    receiver.andand.message(parameters)
  }.to {
    lambda { |andand_temp|
      andand_temp.message(parameters) if andand_temp
    }.call(receiver)
  }

with (andand) do
	# ...
	foo.andand.bar(:bash, blitz(5))
	# ...
end
</pre>
<commit_msg>link to the new post in my homoiconic unblog<commit_after>h1. rewrite

h1. &#x2192; 'rewrite'


h2. What

Rewrite adds sexp-rewriting metaprogramming to Ruby. Or in plain English, Rewrite is a collection of features for Ruby programming like an implementation of "andand":http://andand.rubyforge.org. What makes Rewrite's versions of these features different and possibly useful is that they are implemented by rewriting your Ruby code rather than by opening up classes like Kernel, Object, Nil, or Symbol.


h2. Installing

<pre syntax="ruby">sudo gem install rewrite</pre>

h2. The basics

In your environment.rb file (Rails) or at the top of your source code file, include @Rewrite::With@ and @Rewrite::Prelude@:

<pre syntax="ruby">
include Rewrite::With
include Rewrite::Prelude
</pre>This makes the @with@ method available to your souce code, so you can write:

<pre syntax="ruby">
with(andand) do
	...
	first_name = Person.find_by_last_name('Braithwaite').andand.first_name
	...
end
</pre>The special magic here is that instead of opening up the Object and Nil classes to add _#andand_, Rewrite rewrites the ruby code inside the do/end block so that it looks roughly like this:

<pre syntax="ruby">
with(andand) do
	...
	first_name = lambda { |__1234567__|
		if __1234567__.nil?
			nil
		else
			__1234567__.first_name
		end
	}.call(Person.find_by_last_name('Braithwaite'))
	...
end
</pre>That's a big win because you can use the metaprogramming features you want without worrying that you are breaking anybody else's code. If you use an implementation of #andand that relies on opening the Object and Nil classes, how do you know you aren't (a) breaking some other code somewhere else, or (b) exposing your code to being broken if something else changes the #andand methods?

h2. What problem does rewrite solve?

Recall that when you use the “standard” implementation of things like "andand":http://andand.rubyforge.org/ or "try":http://ozmm.org/posts/try.html, you are openly modifying core classes like Object.

Therefore, you are reaching out and touching every line of code in your project. You probably aren’t breaking everything, but even if the chance of introducing a bug by adopting something like “try” is infinitesimal for each source code file in your project, the chance grows greater and greater as your application grows.

The problem is that you are introducing a change on Object, and everything depends on object. This is very different than introducing a change in your code. In that case, only the other bits of code that directly depend on your code are at risk.

Also, imagine if you introduce try and are careful not to break anything. Now somebody else wakes up one day and decides they need a method that works like Prototype’s "Try.these":http://www.prototypejs.org/api/utility/try-these. They call it “try.” They just broke your code, dude! Not only are you making everything dependant upon your version of try, but your code is dependent upon everyone else not breaking try as well. It’s a train-wreck waiting to happen.

Rewrite restricts things like andand or try to your code and your code alone. Sure, if you introduce a bug in your code, you may break things that directly depend on your code. But if you introduce “try” using rewrite instead of modifying Object, you will not reach out across your project and break something entirely unrelated that happens to have defined its own version of try in a completely different way.

h2. called_by_name

See "Macros, Hygiene, and Call By Name in Ruby":http://github.com/raganwald/rewrite/tree/master/called_by_name.markdown and "With, Unhygienic, and Call-by-Name Semantics in Rewrite":http://github.com/raganwald/homoiconic/tree/master/2008-11-03/with_unhygienic_and_call-by-name_semantics_in_rewrite.markdown.

h2. Unhygienic rewriting

A new feature every much like a new human being: Vulnerable, disruptive, and a complete mess:

<pre syntax="ruby">
include Rewrite::With

andand = Rewrite::ByExample::Unhygienic.
  from(:receiver, :message, [:parameters]) {
    receiver.andand.message(parameters)
  }.to {
    lambda { |andand_temp|
      andand_temp.message(parameters) if andand_temp
    }.call(receiver)
  }

with (andand) do
	# ...
	foo.andand.bar(:bash, blitz(5))
	# ...
end
</pre>

{'fraction_non_alphanumeric': 0.07380469774651247, 'fraction_numerical': 0.009061643018957911, 'mean_word_length': 4.4609375, 'pattern_counts': {'":': 11, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '710867', 'n_tokens_mistral': 2506, 'n_tokens_neox': 2316, 'n_words': 1139}