juan_gandhi: (VP)
In the code I'm working with.
juan_gandhi: (VP)
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)
  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)
scala> "my number is 100 15 90" filter (_.isDigit)
res5: String = 1001590
juan_gandhi: (VP)
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)
Есть коллекция множеств, надо проверить, не пересекаются ли какие-нибудь из них.

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

Да, это в парсерах.
juan_gandhi: (VP)
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)
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)
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)
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)
  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)
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)
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)
- 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)
       Good("huilo") filter ((s:String) => s.startsWith("he"), "oi vei") must_== Result.error("oi vei")
juan_gandhi: (VP)
  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)
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.

Profile

juan_gandhi: (Default)
Juan-Carlos Gandhi

September 2025

S M T W T F S
 1 2345 6
78 9 10 111213
14 151617 181920
212223 24252627
282930    

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 25th, 2025 12:27 pm
Powered by Dreamwidth Studios