scala.js - is js.Dictionary the right type for a "Map" - scala.js

I am using the Twilio Video javascript API with scala.js, for example, the conversations API: https://media.twiliocdn.com/sdk/js/conversations/releases/0.13.9/docs/Conversation.html
The API makes use of javascript "Map" objects (it creates them with javascript code like new Map().)
The only way I've been able to get this to work in my scala.js object is with a js.Dictionary, something like:
#js.native
class TwilioConversation extends js.Object {
var participants: js.Dictionary[TwilioParticipant] = js.native
Is that the right type to model a "Map", or is there a better one?
When I tried using scala Map/mutable.Map, it failed with a class cast exception.

It is not exactly the right type. The right type would be js.Map, but at the moment it does not exist yet. It still lives in a work-in-progress PR at https://github.com/scala-js/scala-js/pull/2110/files#diff-4937cb9b8e89d2f21babe311012e63a1
Before it makes it into Scala.js proper, you have two options:
Use js.Dictionary as you do, which will work as long as all you need to do is use String keys, and get/set values (because the public API for those operations is the same for a dictionary and a map).
Define a JSMap in your codebase, like this: (inspired from the above-linked PR but without references to the Iterable and Iterator parts):
import scala.scalajs.js
import js.annotation._
#js.native
#JSName("Map")
class JSMap[K, V] extends js.Object {
def size: Int = js.native
def clear(): Unit = js.native
def has(key: K): Boolean = js.native
def get(key: K): js.UndefOr[V] = js.native
def set(key: K, value: V): this.type = js.native
def delete(key: K): Boolean = js.native
}

Related

Bounds on constructors?

NOTE: if someone can come up with a better title for what I am trying to ask - please mention or edit.
Given a wrap method:
trait MyWrapperBound {
val message: String
}
def wrap[T <: MyWrapperBound](message: String): T
I am looking for a way to describe that all all implementations of MyWrapperBound should have a constructor that takes a message: String so I can construct and return it from my wrap method.
I can think of a couple of ways to do this:
Method 1 - using an implicit:
def wrap[T <: MyWrapperBound](message: String)(implicit factory: String => T): T
This would mean that any MyWrapperBound impl. would also have to create the implicit:
case class SimpleBound(message: String) extends MyWrapperBound
object SimpleBound {
implicit def factory(message: String): SimpleBound = SimpleBound(message)
}
This would result in a fair amount of boilerplate - which I'd like to avoid.
Method 2 - macro:
def wrap[T <: MyWrapperBound](message: String): T = macro ...
The macro would take the type, assert there is a valid constructor, constructing the type if its there and throw a nice compile error if not present for the developer to go and fix (by adding a valid constructor)
My question is - being fairly new to scala, is there a simpler option that I am missing? or another option that makes more sense?
If you're amenable to typeclasses there is a slightly simpler answer involving implicits. You can accomplish what you're trying to do rather easily by adding a type parameter to MyWrapperBound and enumerating the types of messages you'd like to support using the Show typeclass. For instance, if you knew everything that you were attempting to wrap supported a map A => String, you could supply a Show[A] implicit to your wrap method like so:
trait Show[A] {
def show(a: A): String
}
trait MyWrapperBound[A] {
val message: String
}
object MyWrapperBound {
def wrap[A](a: => A)(implicit ev: Show[A]): MyWrapperBound[A] =
new MyWrapperBound[A] {
override val message: String = ev.show(a)
}
}
object ShowInstances {
case class MyDS(someInformation: List[String])
implicit val simpleShow: Show[String] = new Show[String] {
override def show(a: String): String = a
}
implicit val slightlyMoreComplexShow: Show[MyDS] = new Show[MyDS] {
override def show(a: MyDS): String = a.someInformation.mkString("[", ",", "]")
}
}
As always, the code compiles and produces the desired output. Adding more support is as easy as adding more instances to ShowInstances. This allows you to decouple the map A => String from the wrapper logic itself, so that wrap becomes a simple constructor for MyWrapperBound.
If you don't like the idea of parametrizing your MyWrapperBound with a type parameter, it's not even necessary if you're not planning to have instances of it indexed by some message type.

Implement a final def within some trait where type parameters may or may not be the same

Some setup before my question:
/* roughly equivalent to a union type */
sealed trait NewType
object NewType {
final case class Boolean(record: Boolean) extends NewType
final case class Long(record: Long) extends NewType
final case class String(record: String) extends NewType
}
/* Try to convert a record of type T to a NewType */
sealed trait NewTypeConverter[T] { def apply(record: T): Option[NewType] }
object NewTypeConverter {
trait BooleanConverter[T] extends NewTypeConverter[T] {
override def apply(record: T): Option[NewType.Boolean]
}
trait LongConverter[T] extends NewTypeConverter[T] {
override def apply(record: T): Option[NewType.Long]
}
trait StringConverter[T] extends NewTypeConverter[T] {
override def apply(record: T): Option[NewType.String]
}
}
I want to define a trait Data like the following:
trait Data[T] {
def name: String
def converter: NewTypeConverter[_]
final def value(record: T): Option[NewType] = ??? // calls converter
}
How can I implement this final def value(record: T): Option[NewType]?
A few things to note:
The return type from the apply method of converter must be the same return type as value. So, if you happen to have a BooleanConverter, then value must return an Option[NewValue.Boolean].
Input type T to the Data trait does not have to be the same as the input type _ to the converter. If they happen to be the same type, then the implementation could just be final def value(record: T): Option[NewType] = converter(record). The trickier case is in when the input types differ. Let's say the input type to Data was a String, but the input type to converter was a Long. How would that be handled?
It looks like you are 90% through implementing the Type Class pattern, so I'll try to solve your issue by completing it. Here is a nice reading about it. In short, what you miss is a signature that states that, if one (and only one) implementation of the converter can be found in the implicit scope, use it to run the conversion (or anything else defined by the trait).
The signature is the following:
final def value(record: T)(implicit c: NewTypeConverter[T]): Option[NewType]
Given such a strict signature also makes the implementation quite straightforward:
final def value(record: T)(implicit c: NewTypeConverter[T]): Option[NewType] =
c(record) // literally only applies `c`, the converter
Now, whenever you have your converter instance in the implicit scope, for example the following:
implicit val converter: NewTypeConverter[Boolean] =
new StringConverter[Boolean] {
override def apply(record: Boolean): Option[NewType.String] =
if (record) Some(NewType.String("TRUE"))
else Some(NewType.String("FALSE"))
}
you can instance your trait (simplified in the example):
trait Data[T] {
def name: String
final def value(record: T)(implicit c: NewTypeConverter[T]): Option[NewType] =
c(record)
}
final case class BooleanData(name: String) extends Data[Boolean]
val bool = BooleanData(name = "foo")
And use it:
println(bool.value(true)) // prints Some(String(TRUE))
println(bool.value(false)) // prints Some(String(FALSE))
If you try to invoke the value method from a place where you have no access to the implicit instance you'll get an error:
error: could not find implicit value for parameter converter: NewTypeConverter[Boolean]
Bonus
Providing evidence for a known capability of an object via implicits is so common that Scala has some syntactic sugar you can use if you need to provide such evidence (for example, you have a method that calls your value method) but you do not have to use it directly. It's expressed as follows, with the : right after the generic type:
def methodThatCallsValue[T: Data](convertee: T): Option[NewType] =
data.value(convertee)
it's called context bound and is equivalent to the following (which was done explicitly in the example):
def methodThatCallsValue(convertee: T)(implicit $ev: Data[T]): Option[NewType] =
data.value(convertee)

scala type parameter as object type

How can I achieve this:
final case class ChairId(id: String)
trait GeneratorLike[TO, TC <: AbstractId] {
val prefix: String
def generate(): TC = TO.apply(prefix + "-" + UUID.randomUUID())
}
implicit object ChairIdGenerator extends GeneratorLike[ChairId.type, ChairId] {
val prefix: String = "CHAIR"
}
implicit def IdFn[TO, TC <: AbstractId](x: TO)(implicit ev: GeneratorLike[TO, TC]): GeneratorLike[TO, TC] = ev
//right now I can call:
ChairId.generate()
I don't want to define companion object for that situation and I wondered if there is a chance to extend object with use of implicits?
When I do (I use TO as TypeObject and TC as TypeClass naming) idFn[TO, TC] I want TO to be object that implements def apply(id: String): TC can I enforce that? And how would I get to use this function? It feels totally impossible to call function on type parameter :/
It is impossible to call a method on a type parameter, because it represents a type and not an object. You can call a method on an object, because it is something that exists, but a type is an abstract concept. I don't know what your motivation is for wanting to implicitly add generate() to companion objects, because it actually requires just as much code to define an implicit GeneratorLike than it does to define the companion for ChairId.
If you force GeneratorLike to have an apply method (which can be implemented by case class apply), and remove the first type parameter, this will work.
trait GeneratorLike[TC <: AbstractId] { this: Singleton =>
val prefix: String
def apply(id: String): TC
def generate(): TC = apply(prefix + "-" + UUID.randomUUID())
}
abstract class AbstractId
final case class ChairId(id: String) extends AbstractId
object ChairId extends GeneratorLike[ChairId] {
val prefix = "CHAIR"
}
scala> ChairId.generate()
res0: ChairId = ChairId(CHAIR-60bb01c7-af95-46c7-af45-0b3fa78b3080)
Structural typing is not a particularly good idea on the JVM, so always try to avoid the def test(x: {def apply(s: String)}): TC type stuff because it is implemented using reflection which can be a dog performance wise.
Second, you should probably avoid using val inside a trait. Read here.
The approach you have considered is actually the right one, and namely type classes.
trait HasGenerator[T] {
def apply(uuid: String): T
def generate[T : Generator] = apply(Generator[T].generate)
}
final case class ChairId(id: String)
object ChairId extends HasGenerator[ChairId]
trait Generator[TO] {
def prefix: String
def generate(): String = prefix + "-" + UUID.randomUUID()
def apply(): String = generate
}
object Generator {
def apply[T : Generator] = implicitly[Generator[T]]
}
// Notice .type is not necessary
implicit object ChairIdGenerator extends Generator[ChairId] {
override def prefix = "CHAIR"
}
Why not just use:
ChairId(Generator[ChairId])
This all seems like overkill though so you can quite easily somehow. It's worth fleshing out your requirements a bit more because type classes don't really seem super necessary just yet. You could just do with:
Update
If you use something like the HasGenerator that I have added above in conjunction with the companion object, you can now successfully call ChairId.generate()

facade for a method that returns Promise in ScalaJS

I am writing facade for PouchDB Put Method
here is my facde
#JSName("PouchDB")
class PouchDB extends js.Object {
type CALLBACK = js.Function2[js.UndefOr[js.Dynamic], js.UndefOr[js.Dynamic], Unit]
def this(name: js.UndefOr[String] = js.undefined, options: js.UndefOr[PouchDBOptions] = js.undefined) = this()
def put(doc: js.Object, docId: js.UndefOr[String] = js.undefined, docRev: js.UndefOr[String] = js.undefined, options: js.UndefOr[js.Object] = js.undefined, callback: CALLBACK = ???): Unit = js.native
...
put API takes a callback and also returns Promise , how can i define facade for put API which return promise..
You will need a type for your Promises, just as for everything else. A promise is nothing magical, it's just an object with an interface, which you can type. You will need to know what's the API of PouchDB's promises, but it most likely is something (very) close to Promises/A+. In that case, it would look something like this:
import scala.scalajs.js
import js.annotation.JSName
trait Promise[+A] extends js.Object {
#JSName("then")
def andThen[B](onFulfilled: js.Function1[A, B],
onRejected: js.Function1[Any, B]): Promise[B] = js.native
#JSName("then")
def andThen[B](onFulfilled: js.Function1[A, B]): Promise[B] = js.native
#JSName("then")
def andThen[B >: A](onFulfilled: Unit = (),
onRejected: js.Function1[A, B] = ???)): Promise[B] = js.native
}
It's a bit convoluted because the an unspecified handler means that the promise returned by then can contain the same type of value as this promise if the onFulfilled handler is not specified. But I believe it should work like this.
Then you can declare put as returning a Promise[A] for some appropriate type A.
Update a couple of years later ;-)
Scalajs contains a build-in type for a JS Promise, just use js.Promise[_].
See: https://www.scala-js.org/doc/interoperability/types.html

Is it possible to define a function return type based on a defined mapping from the type of a function argument?

Ideally I'd like to be able to do the following in Scala:
import Builders._
val myBuilder = builder[TypeToBuild] // Returns instance of TypeToBuildBuilder
val obj = myBuilder.methodOnTypeToBuildBuilder(...).build()
In principle the goal is simply to be able to 'map' TypeToBuild to TypeToBuildBuilder using external mapping definitions (i.e. assume no ability to change these classes) and leverage this in type inferencing.
I got the following working with AnyRef types:
import Builders._
val myBuilder = builder(TypeToBuild)
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[TypeToBuild.type, TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
Note that the type is passed as a function argument rather than a type argument.
I'd be supremely happy just to find out how to get the above working with Any types, rather than just AnyRef types. It seems this limitation comes since Singleton types are only supported for AnyRefs (i.e. my use of TypeToBuild.type).
That being said, an answer that solves the original 'ideal' scenario (using a type argument instead of a function argument) would be fantastic!
EDIT
A possible solution that requires classOf[_] (would really love not needing to use classOf!):
import Builders._
val myBuilder = builder(classOf[TypeToBuild])
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[classOf[TypeToBuild], TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
Being able to just use builder(TypeToBuild) is really just a win in elegance/brevity. Being able to use builder[TypeToBuild] would be cool as perhaps this could one day work (with type inference advancements in Scala):
val obj: TypeToBuild = builder.methodOnTypeToBuildBuilder(...).build();
Here is a complete, working example using classOf: http://ideone.com/94rat3
Yes, Scala supports return types based on the parameters types. An example of this would be methods in the collections API like map that use the CanBuildFrom typeclass to return the desired type.
I'm not sure what you are trying to do with your example code, but maybe you want something like:
trait Builder[-A, +B] {
def create(x: A): B
}
object Builders {
implicit val int2StringBuilder = new Builder[Int, String] {
def create(x: Int) = "a" * x
}
def buildFrom[A, B](x: A)(implicit ev: Builder[A, B]): B = ev.create(x)
}
import Builders._
buildFrom(5)
The magic with newInstance only works for concrete classes that have a constructor that takes no parameters, so it probably isn't generic enough to be useful.
If you're not afraid of implicit conversions, you could do something like this:
import scala.language.implicitConversions
trait BuilderMapping[TypeToBuild, BuilderType] {
def create: BuilderType
}
case class BuilderSpec[TypeToBuild]()
def builder[TypeToBuild] = BuilderSpec[TypeToBuild]
implicit def builderSpecToBuilder[TypeToBuild, BuilderType]
(spec: BuilderSpec[TypeToBuild])
(implicit ev: BuilderMapping[TypeToBuild, BuilderType]) = ev.create
case class Foo(count: Int)
case class FooBuilder() {
def translate(f: Foo) = "a" * f.count
}
implicit val FooToFooBuilder = new BuilderMapping[Foo, FooBuilder] {
def create = FooBuilder()
}
val b = builder[Foo]
println(b.translate(Foo(3)))
The implicit conversions aren't too bad, since they're constrained to these builder-oriented types. The conversion is needed to make b.translate valid.
It looked like wingedsubmariner's answer was most of what you wanted, but you didn't want to specify both TypeToBuild and BuilderType (and you didn't necessarily want to pass a value). To achieve that, we needed to break up that single generic signature into two parts, which is why the BuilderSpec type exists.
It might also be possible to use something like partial generic application (see the answers to a question that I asked earlier), though I can't put the pieces together in my head at the moment.
I'll resort to answering my own question since a Redditor ended up giving me the answer I was looking for and they appear to have chosen not to respond here.
trait Buildable[T] {
type Result
def newBuilder: Result
}
object Buildable {
implicit object ABuildable extends Buildable[A] {
type Result = ABuilder
override def newBuilder = new ABuilder
}
implicit object BBuildable extends Buildable[B] {
type Result = BBuilder
override def newBuilder = new BBuilder
}
}
def builder[T](implicit B: Buildable[T]): B.Result = B.newBuilder
class ABuilder {
def method1() = println("Call from ABuilder")
}
class BBuilder {
def method2() = println("Call from BBuilder")
}
Then you will get:
scala> builder[A].method1()
Call from ABuilder
scala> builder[B].method2()
Call from BBuilder
You can see the reddit post here: http://www.reddit.com/r/scala/comments/2542x8/is_it_possible_to_define_a_function_return_type/
And a full working version here: http://ideone.com/oPI7Az