Skip to content

okomok/mada

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 

Repository files navigation

Mada 1.0.0-SNAPSHOT

Mada is a general purpose library for Scala. The current status is pre-alpha: being updated day by day.

Setup Dependencies for sbt

Append this in your project definition:

val mada = "com.github.okomok" %% "mada" % "1.0.0-SNAPSHOT"
val okomokSnapshots = "okomok snapshots" at "http://okomok.github.com/maven-repo/snapshots"

When you use arm or reactive package, setup the continuations plugin following this.

scaladoc

See mada API.

Package Overview

Mada contains the following packages:

  • arm

    Automatic resource management facility

  • peg

    Lightweight PEG parser combinators

  • sequence

    Yet another collection library

arm

arm provides deterministic resource management within a block:

import com.github.okomok.mada.arm.{scope, use}
import java.nio.channels
import java.nio.channels.Channels

class DocTezt { // extends org.scalatest.junit.JUnit3Suite {
    def testTrivial {
        scope {
            val source = use(Channels.newChannel(System.in))
            val dest = use(Channels.newChannel(System.out))
            channelCopy(source, dest)
        }
    }

    def channelCopy(src: channels.ReadableByteChannel, dest: channels.WritableByteChannel) {
        // exercise.
    }
}

dest.close and source.close are automatically invoked in order.

References:

peg

peg package provides "pure" PEG parser combinators:

import com.github.okomok.mada
import mada.peg._
import mada.peg.Compatibles._

class AbcTest extends org.scalatest.junit.JUnit3Suite {
    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 {
        assert(S matches "abc")
        assert(S matches "aabbcc")
        assert(S matches "aaabbbccc")
        assert(!(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.from may be needed to bust ambiguity.
  • No scanners.
  • peg.Rule is used to represent recursive grammars. (lazy val isn't used.)
  • Semantic Action is passed using {...}. ((...) too can be used.)

sequence

sequence provides four sequence types:

  1. Reactive, reactive sequence
  2. Iterative, iterable sequence
  3. List, recursive sequence
  4. Vector, random-access sequence

These construct a loosely arranged hierarchy (like Scala-2.7 collections): List and Vector is compatible to Iterative, which is compatible to Reactive.

Reactive

Reactive sequence is a logical base trait for all kinds of mada sequences. This is built upon (possibly) asynchronous foreach:

reactive.block { * =>
    val mouse = reactive.Swing.Mouse(jl)
    for (p <- *(mouse.Pressed)) {
        println("pressed at: " + (p.getX, p.getY))
        for (d <- *(mouse.Dragged.stepTime(100).takeUntil(mouse.Released))) {
            println("dragging at: " + (d.getX, d.getY))
        }
        println("released")
    }
}

Reactive summary:

  • foreach may be asynchronous; a function passed to foreach may be called later.
  • block can be used to build a sugared for-comprehension with the help of continuations plugin.
  • Synchronous algorithms(isEmpty, head etc) are not supplied.

References:

Iterative

Iterative is yet another Iterable: any method is built 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.
  • filter and map is 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 com.github.okomok.mada.sequence._

class FibonacciTest extends org.scalatest.junit.JUnit3Suite {
    def testTrivial {
        lazy val fibs: List[Int] = 0 :: 1 :: fibs.zip(fibs.tail).map2(_ + _)
        expect(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.

Note scala.Stream.foldRight is not lazy.

List summary:

  • Sealed. Conversion from "iterable" sequence is heavyweight.
  • Backtrackable to any "tail" sequence.
  • map and filter is 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 com.github.okomok.mada.sequence._

class ParTest extends org.scalatest.junit.JUnit3Suite {
    def testTrivial {
        val v = Vector(0,1,2,3,4).par
        v.map(_ + 10).seek(_ == 13) match {
            case Some(e) => expect(13)(e)
            case None => fail("doh")
        }

        val i = new java.util.concurrent.atomic.AtomicInteger(0)
        v.each {
            _ => i.incrementAndGet
        }
        expect(5)(i.get)
    }
}

Vector summary:

  • Random access to any subsequence.
  • map is lightweight, but filter is not available. (mutatingFilter is provided instead.)
  • Parallel algorithm support. (fold, seek, and sort etc.)
  • Recursive sequence is infeasible.

Links

Shunsuke Sogame <okomok@gmail.com>

About

A General Purpose Library for Scala (Deprecated)

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages