Every repository with this icon (
Every repository with this icon (
| name | age | message | |
|---|---|---|---|
| |
.gitignore | Thu Oct 08 07:08:11 -0700 2009 | |
| |
README.md | ||
| |
pom.xml | ||
| |
scalac.args | Tue Jun 30 15:20:35 -0700 2009 | |
| |
src/ |
Mada 1.0-SNAPSHOT
Mada is a set of packages for Scala:
blendBlending meta into runtime
metaMetaprogramming toys
pegLightweight PEG parser combinators
sequenceYet another collection library
blend
blend contains heterogeneous-list implementation originally written in Metascala.
import mada.meta.nat.Literal._
import mada.blend._
import junit.framework.Assert._
class DocTest {
def testTrivial: Unit = {
type l = String :: Boolean :: Char :: Int :: Nil
val l: l = "hetero" :: true :: 'L' :: 7 :: Nil
val i: l#nth[_3N] = l.nth[_3N]
assertEquals(10, i + 3)
}
}
While scala.List contains elements of the same type, blend.List can contain
elements of different types.
meta
The following example contrasts the non-meta versus meta programming in Scala:
class DocTest {
// boolean value
assert(true)
// method
def increment(n: Int) = n + 1
// trait (cut-n-pasted from scala.Product1)
trait Product1[+T1] {
def _1: T1 // abstract method
}
// value
val p = new Product1[Int] {
override def _1 = 7 // implements method.
}
// another method
def getAndInc(x: Product1[Int]) = x._1 + 1
assert(getAndInc(p) == 8)
// converts method to function(value).
val inc = increment(_: Int)
// function invocation
assert(inc.apply(3) == 4)
def testTrivial: Unit = ()
}
class metaDocTest {
import mada.meta._
// meta boolean value
assert[`true`]
// metamethod
type increment[n <: Nat] = n#increment // metamethod invocation by `#`
// metatrait
trait Product1 {
type _1 // abstract metamethod
}
// metavalue
trait p extends Product1 {
override type _1 = _7N // implements metamethod.
}
// another metamethod
type getAndInc[x <: Product1 { type _1 <: Nat }] = x#_1#increment
assert[getAndInc[p] == _8N]
// converts metamethod to metafunction(metavalue).
type inc = quote1[increment, Nat, Nat]
// metafunction invocation
assert[inc#apply1[_3N] == _4N]
def testTrivial: Unit = ()
}
Scala metaprogramming seems to put several restrictions:
- Requires -"Yrecursion 50" flag.
- No metamethod overloading.
- Meta-eq is infeasible.
- Generic metamethod can't be overridden. (As a result, meta-if is infeasible.)
peg
peg package provides "pure" PEG parser combinators:
import mada.peg._
import mada.peg.compatibles._
import junit.framework.Assert._
class DocTest {
val S, A, B = new Rule[Char]
S ::= ~(A >> !"b") >> from("a").+ >> B >> !("a"|"b"|"c")
A ::= "a" >> A.? >> "b"
B ::= ("b" >> B.? >> "c"){ println(_) }
def testTrivial: Unit = {
assertTrue(S matches "abc")
assertTrue(S matches "aabbcc")
assertTrue(S matches "aaabbbccc")
assertFalse(S matches "aaabbccc")
}
}
You might notice that:
- Sequence is represented by
>>, because Scala doesn't have "blank" operator. - And-predicate is represented by
~, because Scala doesn't have unary&operator. peg.frommay be needed to bust ambiguity.- No scanners.
peg.Ruleis used to represent recursive grammars. (lazy valisn't used.)- Semantic Action is passed using
{...}. ((...)too can be used.)
sequence
sequence provides four sequence types:
Iterative, single-pass sequenceList, recursive sequenceVector, random-access sequenceReactive, reactive sequence
These construct a loosely arranged hierarchy:
List and Vector isn't subtype of Iterative but implicitly-convertible to it.
Iterative
Iterative is yet another Iterable: any method is build upon the iterator abstraction.
Unlike the scala library, Iterative is projection (a.k.a. view) by default.
When you need strictly-evaluated one, apply method strict.
Iterative summary:
- Conversion from "iterable" sequence is lightweight.
- Optionally backtrackable only to the whole sequence by using method
begin. filterandmapis lightweight.- Recursive sequence can't be built. (See below.)
List
List emulates lazily-evaluated list like haskell's one,
which is useful to build recursive sequences:
import mada.sequence._
import junit.framework.Assert._
class DocTest {
def testTrivial: Unit = {
lazy val fibs: List[Int] = 0 :: 1 :: fibs.zipBy(fibs.tail)(_ + _)
assertEquals(832040, fibs.nth(30))
}
}
In fact, you could build recursive sequences using only iterator abstraction, but number of iterator instances would be exponential-growth in a recursive sequence like above.
List summary:
- Sealed. Conversion from "iterable" sequence is heavyweight.
- Backtrackable to any "tail" sequence.
mapandfilteris middleweight.- Good at recursive sequence.
Vector
Vector represents (optionally writable) random access sequence, that is, "array".
It supports also parallel algorithms. Parallelization is explicit but transparent:
import mada.sequence._
import junit.framework.Assert._
class DocTest {
def testTrivial: Unit = {
val v = Vector(0,1,2,3,4).parallelize
v.map(_ + 10).seek(_ == 13) match {
case Some(e) => assertEquals(13, e)
case None => fail("doh")
}
val i = new java.util.concurrent.atomic.AtomicInteger(0)
v.each {
_ => i.incrementAndGet
}
assertEquals(5, i.get)
}
}
Vector summary:
- Random access to any subsequence.
mapis lightweight, butfilteris not available. (mutatingFilteris provided instead.)- Parallel algorithm support. (
fold,seek, andsortetc.) - Recursive sequence is infeasible.
Reactive
Reactive sequence is a coarse-grained scala.Responder for sequences,
or you could say a sequence-specific, thread-less and trivial scala.Actor.
Reactive summary:
- TODO.
Links
Shunsuke Sogame <okomok@gmail.com>








