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.
Approach 2. Specialized type.
This week I had made two errors in my code; in one I had mixed
Approach 3. Name variables right. If it is an identifier of a claim pdf, call it
So, approach 4. Phantom types they are called, are not they?
Introduce parameters in these types:
Other solutions?
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?
Entry tags:
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?...
Entry tags:
everybody knew it, but...
scala> "my number is 100 15 90" filter (_.isDigit) res5: String = 1001590
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 }
Entry tags:
ничо себе задачи попадаются
Есть коллекция множеств, надо проверить, не пересекаются ли какие-нибудь из них.
Маленькая коллекция, маленькие множества. Просто смешная задача. Взять декартово, мапнуть на пересечения, искать непустое.
Да, это в парсерах.
Маленькая коллекция, маленькие множества. Просто смешная задача. Взять декартово, мапнуть на пересечения, искать непустое.
Да, это в парсерах.
Entry tags:
case class - just figured out
This one works as hoped:
QED.
Which means, we can have a factory.
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.
Entry tags:
one more segmenter
Given a
So this line:
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))
.
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:
"
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).
"
Entry tags:
list grouping, take 3
Now two versions:
1. With tail recursion, via
lomeo
2. With fold (corrected thrice)
More critique?
1. With tail recursion, via
![[livejournal.com profile]](https://www.dreamwidth.org/img/external/lj-userinfo.gif)
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?
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]](https://www.dreamwidth.org/img/external/lj-userinfo.gif)
![[livejournal.com profile]](https://www.dreamwidth.org/img/external/lj-userinfo.gif)
![[livejournal.com profile]](https://www.dreamwidth.org/img/external/lj-userinfo.gif)
![[livejournal.com profile]](https://www.dreamwidth.org/img/external/lj-userinfo.gif)
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)
This function groups a list into segments where values of a function are the same.
I've been using it for a while.
A test:
Any questions?
(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?
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? :)
Kind of inverts your perception of what controls what, but who cares. It's just an FSM.
Is not it a nice exercise? :)
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.
- 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
- 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.
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.
Entry tags:
found in my tests
Good("huilo") filter ((s:String) => s.startsWith("he"), "oi vei") must_== Result.error("oi vei")
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.
Entry tags:
Entry tags:
a style/monads question
I have this code:
Something does not look nice here.
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.