Sieve of Eratosthenes - Try 4 - DSL
2
esumerfd
Generate prime numbers below some limit. This snippet incorporates some DSL like keywords to describe the prime algorithm.
package simulation.sieve.try5;
/*
* Super DSLize the algorithm.
* 1) Convert all algorithm constructs into domain words
*/
class Sieve5
{
def eratosthenes(a_limit)
{
def primes
use (IntegerCategory,ListCategory)
{
primes = a_limit.seive() {
ifANumberHasAFactor
{
thisIsNotAPrime()
}
elseIfTheNumberIsTheSameAsTheFactor
{
thisIsAPrime()
}
}
}
primes
}
}
/*
* Add prime related methods to Integer.
*/
class IntegerCategory
{
def static seive(Integer a_limit, Closure a_closure)
{
def possiblePrimes = a_limit.toList()
def grammar = PrimeGrammar.newInstance()
grammar.findPrimes(possiblePrimes, a_closure)
}
/*
* Generate a list of numbers with this value as the upper bound
*/
def static toList(Integer a_limit)
{
def list = []
a_limit.times { number ->
list << number
}
list
}
/*
* Determine if this number is divisible by the factor. If eliminate
* the number if it is less than the factor or zero then it can not
* be prime. Then check for prime by not equal self and not divisible
* by factor.
*/
def static hasPrimeFactor(Integer a_number, Integer a_factor)
{
(a_number > a_factor
&& a_number.value != 0
&& a_number != a_factor
&& a_number % a_factor == 0)
}
}
class ListCategory
{
def static eachFactor(ArrayList a_list, Closure a_closure)
{
(2..a_list.size()).each a_closure
}
def static eachPossiblePrime(ArrayList a_list, Closure a_closure)
{
def removals = []
a_list.each { number ->
// Since this method is in a list now perhaps we should
// not filter out other types in the list
if (number instanceof Integer)
{
a_closure(number)
}
}
/*
* This is a little ugly. A nasty dependency between the
* grammar and this list injected method.
*/
def grammar = a_closure.delegate
grammar.eachRemoval { removal ->
a_list.remove((Object)removal)
}
}
}
class PrimeGrammar
{
def primes = []
def currentFactor
def currentNumber
def removals = []
def findPrimes(a_possiblePrimes, a_closure)
{
a_closure.delegate = this
a_possiblePrimes.eachFactor { factor ->
a_possiblePrimes.eachPossiblePrime() { number ->
currentFactor = factor
currentNumber = number
a_closure()
}
}
primes
}
def ifANumberHasAFactor(a_closure)
{
if (currentNumber.hasPrimeFactor(currentFactor))
{
a_closure()
}
}
def elseIfTheNumberIsTheSameAsTheFactor(a_closure)
{
if (!currentNumber.hasPrimeFactor(currentFactor)
&& currentNumber == currentFactor)
{
a_closure()
}
}
def thisIsNotAPrime()
{
removals << currentNumber
}
def thisIsAPrime(a_closure)
{
primes << currentFactor
}
def eachRemoval(a_closure)
{
removals.each { removal ->
a_closure(removal)
}
}
}
...
/*
* Super DSLize the algorithm.
* 1) Convert all algorithm constructs into domain words
*/
class Sieve5
{
def eratosthenes(a_limit)
{
def primes
use (IntegerCategory,ListCategory)
{
primes = a_limit.seive() {
ifANumberHasAFactor
{
thisIsNotAPrime()
}
elseIfTheNumberIsTheSameAsTheFactor
{
thisIsAPrime()
}
}
}
primes
}
}
/*
* Add prime related methods to Integer.
*/
class IntegerCategory
{
def static seive(Integer a_limit, Closure a_closure)
{
def possiblePrimes = a_limit.toList()
def grammar = PrimeGrammar.newInstance()
grammar.findPrimes(possiblePrimes, a_closure)
}
/*
* Generate a list of numbers with this value as the upper bound
*/
def static toList(Integer a_limit)
{
def list = []
a_limit.times { number ->
list << number
}
list
}
/*
* Determine if this number is divisible by the factor. If eliminate
* the number if it is less than the factor or zero then it can not
* be prime. Then check for prime by not equal self and not divisible
* by factor.
*/
def static hasPrimeFactor(Integer a_number, Integer a_factor)
{
(a_number > a_factor
&& a_number.value != 0
&& a_number != a_factor
&& a_number % a_factor == 0)
}
}
class ListCategory
{
def static eachFactor(ArrayList a_list, Closure a_closure)
{
(2..a_list.size()).each a_closure
}
def static eachPossiblePrime(ArrayList a_list, Closure a_closure)
{
def removals = []
a_list.each { number ->
// Since this method is in a list now perhaps we should
// not filter out other types in the list
if (number instanceof Integer)
{
a_closure(number)
}
}
/*
* This is a little ugly. A nasty dependency between the
* grammar and this list injected method.
*/
def grammar = a_closure.delegate
grammar.eachRemoval { removal ->
a_list.remove((Object)removal)
}
}
}
class PrimeGrammar
{
def primes = []
def currentFactor
def currentNumber
def removals = []
def findPrimes(a_possiblePrimes, a_closure)
{
a_closure.delegate = this
a_possiblePrimes.eachFactor { factor ->
a_possiblePrimes.eachPossiblePrime() { number ->
currentFactor = factor
currentNumber = number
a_closure()
}
}
primes
}
def ifANumberHasAFactor(a_closure)
{
if (currentNumber.hasPrimeFactor(currentFactor))
{
a_closure()
}
}
def elseIfTheNumberIsTheSameAsTheFactor(a_closure)
{
if (!currentNumber.hasPrimeFactor(currentFactor)
&& currentNumber == currentFactor)
{
a_closure()
}
}
def thisIsNotAPrime()
{
removals << currentNumber
}
def thisIsAPrime(a_closure)
{
primes << currentFactor
}
def eachRemoval(a_closure)
{
removals.each { removal ->
a_closure(removal)
}
}
}
...






There are currently no comments for this snippet.