I really like Tie::File, which allows you to tie an array to a file's lines. You can modify the array in any way, and when you're done with it, you untie it, and the file's content modifies accordingly.
I'd like to reimplement such behaviour in Scala, and this is what I have so far:
class TiedBuffer(val file:File) extends ArrayBuffer[String] {
tieFile
def untie = {
val writer = new PrintStream(new FileOutputStream(file))
this.foreach(e => writer.println(e))
writer.close
this
}
private def tieFile = this ++= scala.io.Source.fromFile(file).getLines()
}
However, the "operators" defined on the ArrayBuffer return various classes, different than my own, for example:
println((new TiedBuffer(somefile) +: "line0").getClass)
gives me a immutable.Vector. I could limit the class to a very small set of predefined methods, but I thought it would be nice if I could offer all of them ( foreach/map/... ).
What should I inherit from, or how should I approach this problem so that I have a fluid array-like interface, which allows me to modify a file's contents?
BOUNTY: to win the bounty, can you show a working example that makes use of CanBuildFrom to accomplish this task?
The methods ending with colon are right associative so in your example you are calling +: of String with a TiedBuffer as parameter. If you want to test +: from ArrayBuffer you can do:
println((new TiedBuffer(somefile).+:("line0")).getClass)
or
println(("line0" +: new TiedBuffer(somefile)).getClass)
EDIT
I missed the point in your question, see John's answer to return TiedBuffer objects instead of ArrayBuffer.
EDIT2
Here is an example with CanBuildFrom. You will have to call tie manually though to prevent the file to be tied every time the builder create a new TiedBuffer instance. There is still a lot of room for improvement, for instance ++ will not work but it should get you started.
import collection.generic.CanBuildFrom
import collection.mutable._
import java.io.{PrintStream, FileOutputStream, File}
class TiedBuffer(val file: File) extends ArrayBuffer[String]
with BufferLike[String, TiedBuffer]
with IndexedSeqOptimized[String, TiedBuffer] {
def tie = {
clear
this ++= scala.io.Source.fromFile(file).getLines()
}
def untie = {
val writer = new PrintStream(new FileOutputStream(file))
this.foreach(e => writer.println(e))
writer.close
this
}
override def newBuilder: Builder[String, TiedBuffer] =
new ArrayBuffer mapResult {
x: Seq[String] => (new TiedBuffer(file) ++= x)
}
}
object TiedBuffer {
implicit def canBuildFrom: CanBuildFrom[TiedBuffer, String, TiedBuffer] =
new CanBuildFrom[TiedBuffer, String, TiedBuffer] {
def apply(): Builder[String, TiedBuffer] =
throw new RuntimeException("Cannot create a new TiedBuffer from scratch")
def apply(from: TiedBuffer): Builder[String, TiedBuffer] = from.newBuilder
}
}
Extending existing collection requires defining a builder in a companion object such as
object TiedBuffer {
implict def canBuildFrom[T] = new CanBuildFrom[TiedBuffer[T],T,TiedBuffer[T]] { ... }
}
This is fully explained here:
http://www.scala-lang.org/docu/files/collections-api/collections-impl.html
As noted by Marx Jayxcela, the reason you are getting a Vector is that you are using a right associative operators, otherwise an implicit builder would be selected and you would get an ArrayBuffer
Related
I have to create a file loader object and I would like the file to be loaded only once at object creation.
What I did until now is create a trait with a method read that will read file and output a list of String.
trait Loader {
protected val readSource: List[String] = {
Source
.fromInputStream(getClass.getResourceAsStream("filename"), "UTF-8")
.getLines()
.toList
}
def transform(delimeter: String): Vector[C] = {
val lines = readSource
// process the lines
}
}
The trait is implemented by several object, and the transform method can be called multiple times in the client code.
I would like to avoid re reading the file each time the transform method is called and my first solution was to extract the val lines = readSource from the transform method and make a function of it def loadFile = readSource and to create a apply method in my objects to call loadFile like so :
object MyLoader extends Loader {
def apply: List[String] = {
loadFile
}
}
I am wondering if this is the right way to do it. Thank you for your advices.
If you want the resource read once for all, then you should do that in a singleton object, which will be initialized once lazily.
Clients should use that object. "Prefer composition over inheritance" is the mantra.
If you want a mix-in that makes it easy to use the object, you can use "self-types" to constrain clients:
trait HasResource { val resource: R = TheResource }
trait Client { self: HasResource => def getR: R = resource }
This is the "cake pattern" way of making stuff available.
I have a requirement to be able to count number of times AtomicReference[V].get is called in a class that has as field an array of wildcarded atomic references.
To that end, first, I've extended java's AtomicReference[V]:
import java.util.concurrent.atomic.{AtomicInteger => AInt, AtomicReference => ARef}
class MyAtomicReference[V] extends ARef[V]{
private val getCounter: AInt = new AInt(0)
def getAndListen(): V = {
getCounter.getAndIncrement()
super.get()
}
def counter(): Int = getCounter.get()
def resetCounter(): Unit = getCounter.set(0)
}
Then I've added trait AtomicRefCounter which declares the method that I would wish to invoke:
import simulacrum.typeclass
#typeclass trait AtomicRefCounter [R[_], T] {
def countGets(container: R[T]): Int
}
Lastly, I've defined a default AtomicArrayRefCounter in the object DefaultAtomicRefCounters:
object DefaultAtomicRefCounters {
implicit val arrayOfAtomicsTraverser = new AtomicRefCounter[Array, MyAtomicReference[_]] {
override def countGets(container: Array[MyAtomicReference[_]]): Int = container map(_.counter()) sum
}
}
Despite that when I try to call the traverseAtomics() on a corresponding array in a test, I do not see it (I am using Intellij IDEA):
behavior of "removeO1"
"method" should "remove an element from the pool with time O(1)" in new IntPoolBuilder {
import org.learningconcurrency.traditional_concurrency.helpers.DefaultAtomicRefCounters._
pool.buckets.countGet
}
A piece of advice on what I am missing would really help. Usage of simulacrum is not mandatory - if you feel you know how to solve this without it, I would love to hear that.
update:
This is how the buckets are implemented:
class Pool[T] {
type TimeStampedList = (List[T], Long)
val parallelism: Int = Runtime.getRuntime.availableProcessors * 32
val buckets = new Array[MyAtomicReference[TimeStampedList]](parallelism)
...
I think, you might have gotten wrong how implicits work.
If I read everything correctly, then in your code
implicitly[AtomicRefCounter[Array, MyAtomicReference[_]]].countGets(pool.buckets)
should work.
I you wanted to call countGets on the Array you should use the EnrichMyLibrary pattern.
object DefaultAtomicRefCounters {
implicit class RichArray(private underlying: Array[MyAtomicReference[_]] extends AnyVal {
def countGets: Int = underlying.map(_.counter()).sum
}
}
As disappointing as it is, I couldn't make it work with simulacrum annotation, so I've followed Sascha's advise. I just modified slightly his second example (I couldn't get it to work with implictly) so it compiles and works:
object TraditionalConcurrencyHelpers {
implicit class CountArrayAtomicGetsOps(wrapper: Array[MyAtomicReference[(List[Int], Long)]]) {
def countGets()(implicit atomicRefCounter: AtomicRefCounter[Array, MyAtomicReference[(List[Int], Long)]]): Int = atomicRefCounter.countGets(wrapper)
}
}
With this I have no problem calling countGets on the array:
behavior of "removeO1"
"method" should "remove an element from the pool with time O(1)" in new IntPoolBuilder {
import TraditionalConcurrencyHelpers._
import org.learningconcurrency.traditional_concurrency.helpers.DefaultAtomicRefCounters._
//call pool.removeO1 (not implemented yet)
pool.buckets.countGets() shouldEqual 1
}
This is essentially my question, but the accepted answer stops at returning their symbols rather than the case objects themselves.
In theory, this should be easy:
def getCaseObjects(enumType: Type) = {
val m = ru.runtimeMirror(getClass.getClassLoader)
enumType.typeSymbol.asClass.knownDirectSubclasses map { subclass =>
val enumObjMirror = m.reflectClass(subclass.asClass.toType.typeSymbol.asClass)
enumObjMirror.reflectConstructor(subclass.asClass.toType.decl(ru.termNames.CONSTRUCTOR).asMethod)()
}
}
And this works!
...Except that they are entirely new instances compared to the ones contained in their Parent sealed trait; hooray, I've busted the "case objects are singleton" assumption!
I could override equals and hashCode in my Parent sealed trait and be done with it, but I'd prefer a way to get those particular case objects rather than ones that happen to look like them. Is this possible? I'm on 2.11 if that makes any difference.
Assuming you use the sealedDescendants method in the post you reference, I believe you should be able to get the underlying objects like:
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{ universe => ru }
val m = ru.runtimeMirror(getClass.getClassLoader)
val descendants = sealedDescendants[Parent] getOrElse Set.empty
val objects = descendants.map({ desc =>
val mod = m.staticModule(desc.asClass.name.decoded)
m.reflectModule(mod).instance
})
class OpenNLPAnnotator extends ThreadLocal[OpenNLPAnnotatorInstance] {
override def initialValue = new OpenNLPAnnotatorInstance
}
object OpenNLPAnnotator {
private lazy val ann_ = new OpenNLPAnnotator
private def ann = ann_
def apply = ann.get()
}
Is there any way for me to get the TLV by doing OpenNLPAnnotator.someMethodOnTheTLV ? I have to write OpenNLPAnnotator.apply.someMethodOnTheTLV
edit
Based on the answers below i'm thinking something like this would be nicest
object OpenNLPAnnotator {
private lazy val ann_ = new OpenNLPAnnotator
private def ann = ann_
def apply() = ann.get()
def annotator = ann.get
}
Then I could just do annotator.whatever.
That would require an import of course, so unless I put it in a package object it's swings and round-a-bouts. Though I haven't used package objects yet and do not understand the ins and outs.
The only way to call apply method implicitly is to add parentheses after object name like this:
OpenNLPAnnotator().someMethodOnTheTLV
But you have to change apply method declaration (add parentheses):
def apply() = ann.get()
Nasty hack
You could create an implicit conversion from OpenNLPAnnotator.type to OpenNLPAnnotator like this:
implicit def nastyHack(o: OpenNLPAnnotator.type): OpenNLPAnnotator = o.apply
So you could call all methods of OpenNLPAnnotator on companion object.
OpenNLPAnnotator.someMethodOnTheTLV will be converted to this:
nastyHack(OpenNLPAnnotator).someMethodOnTheTLV
Note (in response to your edit):
You could rename apply method while importing it:
import OpenNLPAnnotator.{apply => annotator}
You have two options:
Wait for me to rewrite autoproxy using macros (it'll be done around the same time that scala 2.11.0-RC1 is released)
Use a different pattern!
Did you know that singletons can inherit from their companions?
class OpenNLPAnnotator extends ThreadLocal[OpenNLPAnnotatorInstance] {
override def initialValue = new OpenNLPAnnotatorInstance
}
object OpenNLPAnnotator extends OpenNLPAnnotator {
def apply = this.get()
}
I have a bunch of auto-generated java code that I will be calling in scala. Currently all of the objects were generated with void setters instead of returning this which makes it really annoying when you need to set a bunch of values (I'm not going to use the constructor by initializing everything since there's like 50 fields). For example:
val o = new Obj()
o.setA("a")
o.setB("b")
o.setC("c")
It would be really cool if I could do something like this
val o = with(new Obj()) {
_.setA("a")
_.setB("b")
_.setC("c")
}
I can't use andThen with anon functions since they require objects to be returned. Am I stuck with the current way I'm doing things or is there some magic I'm not aware of.
Sure, you can use tap (the Kestrel combinator), which you presently have to define yourself:
implicit class Tapper[A](val a: A) extends AnyVal {
def tap[B](f: A => B): A = { f(a); a }
def taps[B](fs: A => B*): A = { fs.map(_(a)); a }
}
It works like so:
scala> "salmon".taps(
| println,
| println
| )
salmon
salmon
res2: String = salmon
Note also
val myFavoriteObject = {
val x = new Obj
x.setA("a")
}
will allow you to use a short name to do all the setting while assigning to a more meaningful name for longer-term use.
You can use an implicit converter from/to a wrapper class that allows chaining.
Something like:
case class ObjWrapper(o: Obj) {
def setA(a: String) = { o.setA(a); this }
def setB(b: String) = { o.setB(b); this }
def setC(c: String) = { o.setC(c); this }
}
implicit def wrapped2Obj(ow: ObjWrapper): Obj = ow.o
ObjWrapper(myObj).setA("a").setB("b").setC("c")
Actually you don't even need the implicit converter since those method have been called on myObj.
Take a look at Scalaxy/Beans. Note however that it's using macros, so it should be considered experimental.