Is there a way to import all classes from a package and rename them all by prepending some text? A construct
import packages.{_ => Abc_}
compiles but seems not to be doing that thing.
It's not exactly what you're after, but if you can put up with an extra . character, you could write
import com.{packages=>Abc}
val x:Abc.Whatever = new Abc.Whatever(...)
No, no way to do such a thing.
"Programming in Scala, 2nd Edition" 13.3, which is 2.9 based, defines the rules. I don't recall anything in the changes for 2.10 that alters the import mechanism.
Given import package.{selector}, selector may be one of:
x, a simple name
x => y, renaming x to y
x -> _, hiding x - excludes from names imported
_, the catch-all - import all names.
That's it. Your variant looks interesting, but isn't in that list. It is interesting that {_ => ...} compiles for various values of ..., but it's not clear that the effect is any different than _ for the few trials I ran.
Related
Consider the following PureScript code, a slightly modified version of an example from the handbook:
module ArrayRecursion where
import Prelude (discard, Unit)
import Data.Array (null, tail)
import Data.Maybe (fromMaybe)
length :: forall a. Array a => Int
length arr =
if null arr then
0
else
1 + ( length $ fromMaybe [] $ tail arr)
Compiling this code produces the following error
Unknown type class Array
So the code won't compile.
The questions:
From where is the type class Array imported? It does not seem to be imported from Prelude or Data.Array.
How does one go about finding where to import PureScript type classes? In this case, searching Pursuit for "Array" yields hundreds of results, creating a needle-in-haystack problem.
Array is not a type class, but a type.
You accidentally put a fat arrow after Array a instead of a thin arrow, making it look like you were declaring a value of type Int with a constraint Array a rather than a function that takes an Array a as a parameter and returns an Int. This is how it should look:
length :: forall a. Array a -> Int
Normally you don't import the Array type. It's in the module called Prim, which is always implicitly imported.
As for finding out - yes, search on Pursuit. If you carefully look at the search results, you will notice that only one of them (the first one) is actually a type. All the other ones are either functions or ADT cases.
Another way to search for things (especially things in the standard libraries) is your IDE integration. These days I almost never actually have to manually add an import at the top of my files. I just start typing the name of whatever it is I need, and the IDE support offers me some options, waits for me to choose, and automatically adds an import. 10/10 recommend.
Given:
def convert[T](list: List[Either[String, T]]): Validated[NonEmptyList[String], NonEmptyList[T]] =
NonEmptyList.fromList(list)
.toRight("list is empty")
.flatMap(...
How do I flat map the NonEmptyList[Either[String, T]] so ultimately I end up with my Validated return value?
Is there anything in the cats library to account for this scenario? Or do I need to do this manually following something like: Best way to turn a Lists of Eithers into an Either of Lists?
I'd write this as follows:
import cats.data.{ NonEmptyList, Validated, ValidatedNel }
import cats.instances.list._, cats.syntax.list._
import cats.syntax.either._
import cats.syntax.option._
import cats.syntax.traverse._
def convert[T](list: List[Either[String, T]]): ValidatedNel[String, NonEmptyList[T]] =
list.traverse(_.toValidatedNel).andThen(_.toNel.toValidNel("list is empty"))
First we flip the whole thing inside out while transforming the Eithers to Validateds (with traverse and toValidatedNel), to get a ValidatedNel[String, List[T]], and then we handle the case where the result is empty (with andThen and toNel).
The andThen is probably one of the pieces you're missing—it's essentially flatMap for Validated (but without the implications and syntactic sugar baggage that flatMap brings). If you wanted you could probably pretty easily change my version to do the empty list check first, as in your sketch, but the way I've written it feels a little more natural to me.
Footnote: I have no idea why the enrichment method for Option is named toValidNel while the one for Either is toValidatedNel—I hadn't noticed this before, probably because I hadn't used them in the same line before. This seems unfortunate, especially since we're stuck with it for a while now that Cats 1.0 is out.
Another footnote: note that you'll need the -Ypartial-unification compiler option enabled for traverse to work without type parameters if you're on 2.11.
I am new to scala. Currently I am trying to develop a calculator as scala project.
But while trying to find the sum I am getting problem. The following code doesn't compile.
def add [T](values :List[T]) : Option[T]={
if (values.isInstanceOf[String]) {
None
}
else if(values.isInstanceOf[Int] || values.isInstanceOf[Long] || values.isInstanceOf[Double]) {
Some(values.sum)
}
}
When you're new to a language, it is important to start slow and discover the abstractions rather than impose them right away without the experience to make it work. I also think it is a bad idea to just rely on standard library functions (unless you are in a hurry) like sum or to look at third-party libraries until you fully understand what the standard library offers.
So in other words, first let's look at ways to solve the problem just for Int:
def add(values: List[Int]) = values.reduce((a, b) => a + b)
The reduce function works because the type of the result matches the type of what is in the list. The contents are Ints, and the sum is an Int. You will also find this can be simplified with some syntactic sugar:
def add(values: List[Int]) = values.reduce(_ + _)
Wait until you see all the ways underscores get used in Scala.
As you keep studying, you will find that in order to accumulate a value that is a different type than what's in the list, you can use one of the fold* methods. But they can work here too, so for example you could also do this:
def add(values: List[Int]) = values.foldLeft(0)(_ + _)
Now try to define the same function for Long, Double, or even String. You will find the implementations will be almost identical.
It's only when you see implementations that look really similar if not identical that you should even think about abstractions. One option to solve this problem is with type classes. They aren't easy for beginners though. Daniel Westheide wrote a great post on the topic, and frankly you would do well to read the whole series as you learn Scala.
I've really simplified things and glossed over a lot of topics (like why foldLeft has two parameter lists with the first one being 0 or what those crazy implicit things are in Daniel's type classes post), but my advice is to be patient and move slowly. Scala isn't easy, but you'll get it.
(But if you are in a hurry and you are a beginner, I think you are better off just using sum and then writing separate functions for each type. This would be an example of what agile author Kenny Rubin would call "necessary" or "unavoidable" technical debt, and that's to be expected from beginners. Just refactor later.)
Or more generic (example with amm):
# import $ivy.`org.typelevel:cats_2.12:0.8.1`
import $ivy.$
# import cats._, cats.implicits._
import cats._, cats.implicits._
# List(1, 2, 3).combineAll
res2: Int = 6
# List("1", "2", "3").combineAll
res3: String = "123"
# List(List(1, 2), List(), List(3)).combineAll
res5: List[Int] = List(1, 2, 3)
Or via fiddle. It works by using the Monoid and Traversable typeclass.
I have found several questions on the subject of the Scala compiler warning:
postfix operator xxx should be enabled by making the implicit value
scala.language.postfixOps visible. This can be achieved by adding the
import clause 'import scala.language.postfixOps' or by setting the
compiler option -language:postfixOps. See the Scala docs for value
scala.language.postfixOps for a discussion why the feature should be
explicitly enabled.
Here's an example of where this warning shows up:
val m1 = List(1->"a",2->"b") toMap
None really answered what I wanted to know when I first came across this problem: how do I fix this problem without involving the import or the compiler option. My first thought was this: if it doesn't like postfix ops, then make the method/op call explicit by replacing the space with a dot. For example:
val m1 = List(1->"a",2->"b").toMap
Unfortunately, when I first tried that fix, the code that I happened to be working on at the time looked something like this:
val m2 = List(1->"a",2->"b") map {case (k,v) => (k.toString,v)} toMap
When I added the dot, this resulted in yet another obscure compiler error:
val m2 = List(1->"a",2->"b") map {case (k,v) => (k.toString,v)}.toMap
missing parameter type for expanded function The argument types of an
anonymous function must be fully known. (SLS 8.5) Expected type was: ?
which related to the k and v identifiers.
Back then, I just gave up and added the import statement and all was well. However, a student recently asked me about this issue and I thought I'd better go back and investigate. See my answer to the problem which, now that I think about it, is rather obvious. Yet I hope to save some others the time that it takes to wade through all of the other discussions of this subject.
What I usually do in this situation, I'll add a dot to the first call:
val m2 = List(1->"a",2->"b").map {case (k,v) => (k.toString,v)}.toMap
Personally, I prefer this to having extra parenthesis.
The answer has to do with the associativity of the operators ("." binds more tightly than map). The answer of course is to override the binding with parentheses:
val m2 = (List(1->"a",2->"b") map {case (k,v) => (k.toString,v)}).toMap
I am new to scala. I am looking through some code and came up with a code that imports com.infinite.usermanagement.controllers.{ SecurityService => BaseSecurityService } package. I was wondering what does => sign means in an import.
This line means you import the class SecurityService and rename it to BaseSecurityService. You can use this to prevent name conflicts, etc. You can use this class by using BaseSecurityService instead of the original class name.
A very common example is the following (to prevent mixing up Scala and Java classes):
import java.util.{Map => JMap, List => JList}
As others have mentioned, it's an import rename. There is however one further feature that proves astoundingly-useful on occasion that I would like to highlight: If you "rename" to _, the symbol is no longer imported.
This is useful in a few cases. The simplest is that you'd like to do a wildcard import from two packages, but there's a name that's defined in both and you're only interested in one of them:
import java.io.{ File=>_, _ }
import somelibrary._
Now when you reference File, it will unambiguously use the somelibrary.File without having to fully-qualify it.
In that case, you could have also renamed java.io.File to another name to get it out of the way, but sometimes you really do not want a name visible at all. This is the case for packages that contain implicits. If you do not want a particular implicit conversion (e.g. if you'd rather have a compile error) then you have to delete its name completely:
import somelibrary.{RichFile => _, _}
// Files now won't become surprise RichFiles