juan_gandhi: (VP)
2014-08-28 03:56 pm
Entry tags:

just got rid of nulls

In the code I'm working with.
juan_gandhi: (VP)
2014-08-28 03:40 pm
Entry tags:

handling a pointer in Scala code

A pointer can be an ID of something (people like ids), or a Url, whatever.

Approach 1. Native type. String for url, Long for id. So, you become just a number; your id can be multiplied by 0 or by 7; and a reference to a page has method like substring() or replaceAll(), or +. We can add a url and user id, and it will be okay in this world. Typeless!

Approach 2. Specialized type. case class ID(private val value: Long), class Url(private val text: String); this makes our code more sane. We only compare urls with urls and ids with ids; and we can stash them in sets or maps, using as keys (ok, need hashCode and equals).

This week I had made two errors in my code; in one I had mixed ID of a company and ID of a "connector table entry" that would point to a company; in another I had mixed Url of the main page and Url of a pdf file; in the latter case I just used an identifier, url, and it was a wrong identifier.

Approach 3. Name variables right. If it is an identifier of a claim pdf, call it urlOfClaimPdf. Makes sense; but not always: we can have some method that does not care if it is a corn pdf or a porn pdf. It only needs to be a pdf.

So, approach 4. Phantom types they are called, are not they?
Introduce parameters in these types: IDof[User], IDof[Pdf], or UrlOf[ClaimPdf] where ClaimPdf <: Pdf, and UrlOf[+T] is covariant. On many occasions it will be just a compiler warning, but well, it's way better to have a warning than to go blind, right?

Other solutions?
juan_gandhi: (VP)
2014-08-11 06:06 pm
Entry tags:

another code sample

  def parameters(href): Map[String, String] = href split("\\?",2) toList match {
    case url::params::Nil => params.split("&") map (_ split "=" toList) collect {
      case k::v::Nil => k->v
    } toMap

    case otherwise => Map.empty  
  }


Or?...
juan_gandhi: (VP)
2014-08-11 11:27 am
Entry tags:

everybody knew it, but...

scala> "my number is 100 15 90" filter (_.isDigit)
res5: String = 1001590
juan_gandhi: (VP)
2014-08-08 05:14 pm
Entry tags:

reflection, no big deal

I have a mock db, I want to insert a row in a table; the thing is, id were recently converted from var to val (it was an ancient idea of having variable id, something very weird). Now I had to use reflection, so I did.

         override def insert(o: T): T = {
            val fields = fieldsOf(o.getClass)
            val idField = fields("id")
            idField.set(o, globalID)
            globalID += 1
            update(o)
            o
          }
        }

        private def fieldsOf(clasz: Class[_]):Map[String, Field] = {
          def listFields(c: Class[_]): List[Field] =
            if (c==null) Nil else
              c.getDeclaredFields .filter (!_.getName.contains("$") ) .toList ++ listFields(c.getSuperclass)

          val fields = listFields(clasz)
          fields foreach (_.setAccessible(true))
          fields map (f => f.getName -> f) toMap
        }
juan_gandhi: (VP)
2014-08-08 01:05 pm
Entry tags:

ничо себе задачи попадаются

Есть коллекция множеств, надо проверить, не пересекаются ли какие-нибудь из них.

Маленькая коллекция, маленькие множества. Просто смешная задача. Взять декартово, мапнуть на пересечения, искать непустое.

Да, это в парсерах.
juan_gandhi: (VP)
2014-08-01 10:38 am
Entry tags:

case class - just figured out

This one works as hoped:
scala> case class MyCase(name: String, value:Int)
defined class MyCase

scala> val factory = MyCase
factory: MyCase.type = MyCase

scala> factory("cool", 42)
res0: MyCase = MyCase(cool,42)

QED.

Which means, we can have a factory.
juan_gandhi: (VP)
2014-07-31 12:27 am
Entry tags:

one more segmenter

Given a Seq[T], and two predicates, p0:T=>Bool, p1:T=>Bool, extract segments of the sequence that start with elements satisfying p0 and end with elements satisfying p1.

def extractChunks[T](src:Seq[T], p0:T=>Boolean,p1:T=>Boolean) = {
  val found:(List[T], List[List[T]]) = ((Nil:List[T], Nil:List[List[T]])/:src)
  {
    case ((Nil, out), x) => if (p0(x)) (List(x),       out) else (Nil,    out)
    case ((seg, out), x) => if (p1(x)) (Nil, (x::seg)::out) else (x::seg, out)
  }
  found._2 map (_.reverse) reverse
}


So this line:

println(extractChunks[Char]("abracadabra", 'b'==, 'a'==))


Will print List(List(b, r, a), List(b, r, a)).
juan_gandhi: (VP)
2014-07-29 10:16 am
Entry tags:

great roadmap for scala

http://scala-lang.org/news/roadmap-next

I especially liked this:

"
Simple foundations: This continues the strive for simplicity on the type systems side. We will identify formerly disparate features as specific instances of a small set of concepts. This will help in understanding the individual features and how they hang together. It will also reduce unwanted feature interactions. In particular:

  • A single fundamental concept - type members - can give a precise meaning to generics, existential types, wildcards, and higher-kinded types.

  • Intersection and union types make member selection more regular and avoid blow-ups when computing tight upper and lower bounds of sets of types.

  • Tuples can be decomposed recursively, overcoming current limits to tuple size, and leading to simpler, streamlined native support for abstractions like HLists or HMaps which are currently implemented in some form or other in various libraries.

  • The type system will have theoretical foundations that are given by a minimal core calculus (DOT).


"
juan_gandhi: (VP)
2014-07-25 11:20 am
Entry tags:

list grouping, take 3

Now two versions:

1. With tail recursion, via [livejournal.com profile] lomeo
  def groupByRelationship[T](xs: List[T])(p: (T,T) => Boolean) = {
    def go(xs: List[T], accum: List[List[T]]): List[List[T]] = (xs, accum) match {
      case (Nil, _) => accum.reverse map (_.reverse)
      case (x::xs, Nil) => go(xs, List(List(x)))
      case (x::xs, ((ys@(y::_))::rest)) => go(xs, if (p(y, x)) (x::ys)::rest else
        List(x)::ys::rest)
    }
    go(xs, Nil)
  }


2. With fold (corrected thrice)
  def groupByRelationship[T](p: (T,T) => Boolean)(xs: List[T]) = {
    val (seg,acc) = ((List[T](),List[List[T]]()) /: xs) {
      case ((y::ys, a), x) if p(y,x) => (x ::y ::ys, a)
      case (   (ys, a), x)           => (x::Nil, ys.reverse::a)
    }
    (seg.reverse::acc).reverse drop 1
  }


More critique?
juan_gandhi: (VP)
2014-07-24 10:00 pm
Entry tags:

new version of grouping function

  def groupByRelationship[T](p: ((T,T) => Boolean)) = {
    new (List[T] => List[List[T]]) { group =>

      def apply(xs: List[T]): List[List[T]] =
        xs match {
          case Nil => Nil
          case x::Nil => (x::Nil)::Nil
          case x::y::tail if x == y || p(x,y) =>
            val (h::t) = group(y::tail)
            (x::h)::t
          case x::ys => (x::Nil)::group(ys)
        }
    }
  }


or, alternatively,
  def groupByRelationship[T](p: ((T,T) => Boolean)) = {
    new (List[T] => List[List[T]]) { group =>

      def apply(xs: List[T]): List[List[T]] =
        xs match {
          case Nil    => Nil
          case x::Nil => (x::Nil)::Nil
          case x::ys  =>
            val tail = group(ys)
            if (x == ys.head || p(x, ys.head)) (x::tail.head)::tail.tail
            else                               (x::Nil)::tail
        }
    }
  }



Like in Haskell.
Thanks [livejournal.com profile] lomeo, [livejournal.com profile] huzhepidarasa, [livejournal.com profile] cousin_it, [livejournal.com profile] sassa_nf for their critique.
juan_gandhi: (VP)
2014-07-23 03:51 pm
Entry tags:

group by relationship

I have a list, and a binary relationship, and I want to group the list, joining the neighbors that satisfy the relationship. It being equivalence relationship is kind of nice to have, but not necessary. Can be an order actually, so we group monotone sequences. Etc.

(here's version 3, ugly)

  def groupByRelationship[T](p: ((T,T) => Boolean)) = {
    new (List[T] => List[List[T]]) { self =>

      def apply(xs: List[T]): List[List[T]] =
        xs match {
          case List() => List()
          case (x:T) :: _ =>
            val pairs:Iterator[Seq[T]] = xs.sliding(2)
            val (ps1, ps2) = pairs.span(_.toList match {
              case a::b::Nil => a==b || p(a, b)
              case _         => false
            })

            val chain:List[T] = x::(ps1 map (_(1))).toList
            val tail = ps2.toList collect {case a::b::Nil => b}
            chain :: self(tail)
        }
    }
  }


This function groups a list into segments where values of a function are the same.
I've been using it for a while.
  def groupListBy[T,U](xs: List[T])(f: T => U): List[List[T]] = groupListByRelationship[T](xs)((x,y) => f(x)==f(y))


A test:
      val g1 = groupByRelationship[Int](_ < _)(List(1,2,4,2))
      g1 must_== List(List(1,2,4), List(2))
      val g2 = groupByRelationship[Int](_ > _)(List(1,2,4,2))
      g2 must_== List(List(1),List(2), List(4,2))


Any questions?
juan_gandhi: (VP)
2014-07-11 06:29 pm
Entry tags:

an exercise

so, can you write in Scala a web server using state monad, without any variable? :)
Kind of inverts your perception of what controls what, but who cares. It's just an FSM.

Is not it a nice exercise? :)
juan_gandhi: (VP)
2014-06-27 10:07 pm
Entry tags:

scala type classes, twittered

- what are they?
Classes of types, not formally declared as classes, as they usually do in Java/Scala.
- why?
To provide common, context-based ad-hoc operations, not provided by the types (since we don't want to). E.g. you have a traditional Java array, and you want it to be smarter.

- where do I declare additional operations?
Declare a parameterized trait e.g. NewOps[T] that describes the type class with functionality applicable to T.

- where do I define additional operations?
In an implicit witness object implementing the trait.

- how do I use it?
(Using pimp pattern) define an implicit function that takes an instance of T returning an instance having additional operations. Define a witness in this function implicitly - compiler will find it. Call witness object to do the job inside this new instance.

- how come the right functionality is involved?
Compiler finds the right witness object based on the parameter type. Make sure there's exactly one visible for your type.

==========
P.S. correct me if I am wrong.
juan_gandhi: (VP)
2014-06-27 10:57 am
Entry tags:

found in my tests

       Good("huilo") filter ((s:String) => s.startsWith("he"), "oi vei") must_== Result.error("oi vei")
juan_gandhi: (VP)
2014-06-18 03:59 pm
Entry tags:

learned something new again

  override def getEOBs: Outcome = {
    import JavaScript._
    val outcome =
    for (_ ← clickElementHavingText("a", "My Stuff") onError suspiciousError;
         _ ← waitSelector("input#continue");
         _ ← clickElementHavingText("input[name=dateRangeSelection]", "past year");
         _ ← findElement("input[name=selectedMembers]");
         _ ← js(s"$foundElement.checked = true");
         _ ← clickElementHavingText("input#continue", "");
         _ ← clickElementHavingText("a", "INTERNET.com");
         _ ← findElementContainingText("*", "Processed");
         _ ← clickElementHavingText("a", "More");
         _ ← clickElementHavingText("input", "View All");
         (contents, source) <- pageContents.toResultKeepingSource) yield {
         println(contents.toFormattedString)
         jsREPL("So?")
    }
    debug(s"Got $outcome"); OK
  }


What happens here: we do these operations, monadically, since each one depends on the success of the previous one; errors are stored in negative result. If everything went well, I grab page contents and convert it to Result[Props], so the props contain all the information I managed to extract from the page.

On failure the error is logged; what can we do, it requires human interference.

All this amounts to flatMap on my Result class.
Yes, it does remind checked exception handling, but well, we are not in denial here; and we could do applicative join if needed.
juan_gandhi: (VP)
2014-05-30 03:05 pm
Entry tags:

a style/monads question

I have this code:

  lazy val eobOpt: Result[EOB] = ...
  ...

  def items: Result[Traversable[EOB_item]] = {
    val listOfParsedItems: Traversable[Result[EOB_item]] =
      itemsData map {
        item => {
          eobOpt flatMap (buildItem(_)(item))
        }
      }
    Result.traverse(listOfParsedItems).map(_.toList)
  }


Something does not look nice here. flatMap, should not have an alias name, like =>> or something? I can juggle things around, but what I'm looking for is simple beauty, or beautiful simplicity, same thing.