So for a very small formula interpretter someone asked me to code-golf, I wanted to do something like
val ops = Map("plus" -> + , "minus"-> -, "times"-> *, "div" -> / )
to allow quick conversion between keywords and the functions they describe. Not only did this syntax not parse, but none of the other shorthand syntaxes I tried ( _ + _, _:Int.+_)parsed. Is there a way of doing this as a function shorthand, or am I doomed to writing out the lambdas fully, ruining my golf score.
Edit: The problem in question was integers only. I understand that overloading would make this vastly more difficult otherwise.
Not sure how your score is impacted by defining an additional function. You could lift the operators, using something like this:
def lift(f:(Int,Int)=>Int) = f
val ops = Map("plus" -> lift(_+_), "minus" -> lift(_-_), "times"-> lift(_*_), "div" -> lift(_/_))
And if you want to shave some chars:
def ↑(f:(Int,Int)=>Int) = f
val ops = Map("plus" -> ↑(_+_), "minus" -> ↑(_-_), "times"-> ↑(_*_), "div" -> ↑(_/_))
And as om-nom-nom comments, this explicit lifting can be done by the compiler as well by providing the type signature to coerse the lifting:
val ops: Map[String, (Int,Int) => Int] = Map("plus" -> (_+_), "minus" -> (_-_), "times"->(_*_), "div" -> (_/_))
Related
I am learning scala, and I am not able to understand following thing.
why following works?
val colNames = List("salary_new", "age_new", "loc_new")
val colRenameMap = colNames.map(_ -> "a").toMap
but following doesn't ? is it, that I can use _ as first argument only? how does this _ works?
val colRenameMap = colNames.map(_ -> _.split("")).toMap
Luis answered the question already, so let's convert it to a proper answer.
val colRenameMap = colNames.map(_ -> _.split("")).toMap
translates to
val colRenameMap = colNames.map((a,b) => a -> b.split("")).toMap
Each time you use _, it refers to a different argument. Use it twice, and you get a function of two arguments, instead of the single-argument function map needs. In this case, you have to be explicit and name your unique argument to be able to use it twice
val colRenameMap = colNames.map(a => a -> a.split("")).toMap
It's because of in scala underscore in different cases means different sense.
first case:
val colNames = List("salary_new", "age_new", "loc_new")
val colRenameMap = colNames.map(_ -> "a").toMap
here you can rewrite line as follows:
val colRenameMap = colNames.map(x => x -> "a").toMap
if you are use argument in lambda expression once, you can concise expression by underscore _.
but when you try to use underscore _ twice - it can't be used for that.
here you are trying to use argument in lamda expression twice:
//first //second
val colRenameMap = colNames.map(x => x -> x.split("")).toMap
and you can't concise it using underscore _
I'm trying to return a map in scala. Here's my code:
val interestRegEx = """(\w+) Interests \((.+ Interest)\)""".r
val singleAttributes = Seq("Sport Interests (Some Interest):Running,Swimming","Something else:True")
val interests = singleAttributes.map { x =>
// e.g. ("Sport Interests (Some Interest)", "Running,Swimming") should
// result in ("Sport Running" -> "Some Interest", "Sport Swimming" -> "Some Interest")
val attVal = x.split(':')
attVal(0) match {
case interestRegEx(interestProduct, interestAmount) =>
Some(attVal(1).split(",").map { i =>
Map(s"$interestProduct $i" -> interestAmount)
}.reduce(_ ++ _))
case _ => None
}
}.fold(Map[String, String]())(_) //.reduce(_ + _)
The problem is trying to reduce the collection to a single Map[String, String]. I thought the fold might work, but since it doesn't perhaps I'd even need to add a reduce(_ + _) afterwards, but that doesn't work either.
The part I don't understand is that IntelliJ tells me that interests has type ((Equals, Equals) => Equals) => Equals. WTF? Where are these Equals coming from, and why isn't it just adding all of the Maps together to return a Map containing all keys & values?
If we simplify your example we will get:
val interests = Seq[String]().map { x =>
Option[Map[String, String]](Map("k" -> "v"))
}.fold(Map[String, String]())(_)
This means that we are trying to fold Seq[Option[Map[String, String]]] with initial value Map[String, String]():
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)
From fold definition we can see that compiler expects that Option[Map[String, String]] (each value in folding) and Map[String, String] (init value) should be of the same type.
If you inspect Option hierarchy you will see:
Option -> Product -> Equals
For Map we have the following:
Map -> GenMap -> GenMapLike -> Equals (traits hierarchy is complicated, may be another chains exist).
So we can see tha the nearest common type is Equals.
Second part of your puzzle is (_).
This is treated by compiler as an argument of lambda:
val interests = x => /*omited*/.fold(Map[String, String]())(x)
As we saw x is (A1, A1) => A1. And in our case it is:
(Equals, Equals) => Equals
The result of fold is A1 which is also Equals.
As a result lambda type is:
((Equals, Equals) => Equals) /*<< arg*/ => /*result >>*/ Equals
UPDATE:
To solve your problem I think you should use:
.flatten.reduce(_ ++ _)
When you get a trait like Product or Equals as the inferred type of a statement, you can usually bet you have a type mismatch in some higher order function. You typically don't get Any or AnyRef because those only happen if some set of types have nothing in common. One thing that sticks out to me is that your 2nd argument to fold only takes one parameter. Amazingly enough, that typechecks, but it's probably what's giving you the types you don't expect.
I think what you wanted to do is something more like:
val interestRegEx = """(\w+) Interests \((.+ Interest)\)""".r
val singleAttributes = Seq("Sport Interests (Some Interest):Running,Swimming","Something else:True")
val interests = singleAttributes.map { x =>
// e.g. ("Sport Interests (Some Interest)", "Running,Swimming") should
// result in ("Sport Running" -> "Some Interest", "Sport Swimming" -> "Some Interest")
val attVal = x.split(':')
attVal(0) match {
case interestRegEx(interestProduct, interestAmount) =>
attVal(1).split(",").map { i =>
Map(s"$interestProduct $i" -> interestAmount)
}.reduce(_ ++ _)
case _ => Map.empty
}
}.reduce(_ ++ _)
For this I got:
scala> interests
res0: scala.collection.immutable.Map[_ <: String, String] = Map(Sport Running -> Some Interest, Sport Swimming -> Some Interest)
I got rid of the Option wrapping the Maps in your regex match. Since you're planning on combining the maps, may as well use the empty map as your non-match case. Then I used reduce instead of fold for your final match, much as you had done in the inner map.
I know about couple of similar questions. They don't help me - code does not work if there is no existing key.
I need just some nice approach to append Map with value adding it to existing key (if it does exist) or putting as NEW key (if map does not contain appropriate key).
Following code works but I don't like it:
val a = collection.mutable.Map(("k1" -> 1), ("k2" -> 5))
val key = "k1"
val elem = a.get(key)
if (elem == None) {
a += ("k5" -> 200)
} else {
a.update(key, elem.get + 5)
}
Any point to better one?
Current Scala version is 2.10.4 and I cannot currently switch to 2.11.
Mutable map is not 100% limitation but preferred.
Here is, for example, similar question but I also need to account case of non-existing key which is not accounted there. At least we should understand a.get(key) could be None or add some better approach. Good idea was |+| but I'd like to keep basic Scala 2.10.x.
The shortest way to do that:
a += a.get(key).map(x => key -> (x + 5)).getOrElse("k5" -> 200)
In general:
a += a.get(k).map(f).map(k -> _).getOrElse(kv)
Same if your dictionary is immutable:
m + m.get(k).map(f).map(k -> _).getOrElse(kv)
so I don't see any reason to use mutable collection here.
If you don't like all these Option.map things:
m + (if (m.contains(k)) k -> f(m(k)) else kv)
Note, that there is a whole class of possible variations:
k1 -> f(m(k1)) else k2 -> v2 //original
k1 -> f(m(k1)) else k1 -> v2
k1 -> f(m(k2)) else k2 -> v2
k1 -> f(m(k2)) else k1 -> v2
k2 -> v2 else k1 -> f(m(k1))
k1 -> v2 else k1 -> f(m(k1))
k2 -> v2 else k1 -> f(m(k2))
k1 -> v2 else k1 -> f(m(k2))
... //v2 may also be a function from some key's value
So, Why it's not a standard function? IMO, because all variations still can be implemented as one-liners. If you want library with all functions, that can be implemented as one-liners, you know, it's Scalaz :).
P.S. If yu also wonder why there is no "update(d) if persist" function - see #Rex Kerr 's answer here
You can create you own function for that purpose:
def addOrUpdate[K, V](m: collection.mutable.Map[K, V], k: K, kv: (K, V),
f: V => V) {
m.get(k) match {
case Some(e) => m.update(k, f(e))
case None => m += kv
}
}
addOrUpdate(a, "k1", "k5" -> 200, (v: Int) => v + 5)
Scala 2.13 introduced updatedWith method which seems to be the most idiomatic way to update a map conditionally on the existence of the key.
val a = Map(("k1" -> 1), ("k2" -> 5))
val a1 = a.updatedWith("k1") {
case Some(v) => Some(v + 5)
case None => Some(200)
}
println(a1) // Map(k1 -> 6, k2 -> 5)
One may also remove values using it:
val a2 = a.updatedWith("k2") {
case Some(5) => None
case v => v
}
println(a2) // Map(k1 -> 1)
An excerpt from the Scala Standard Library reference:
def updatedWith[V1 >: V](key: K)(remappingFunction: (Option[V]) => Option[V1]): Map[K, V1]
Update a mapping for the specified key and its current optionally-mapped value (Some if there is current mapping, None if not).
If the remapping function returns Some(v), the mapping is updated with the new value v. If the remapping function returns None, the mapping is removed (or remains absent if initially absent). If the function itself throws an exception, the exception is rethrown, and the current mapping is left unchanged.
One somewhat clear way to do this:
val a = collection.mutable.Map[String, Int]() withDefault insertNewValue
def insertNewValue(key: String): Int =
a += key -> getValueForKey(key)
a(key)
}
def getValueForKey(key: String): Int = key.length
Still, I totally discourage the use of mutable collections. It's preferable to keep internal mutable state as variables holding immutable fields.
This is because of a simple rule, you shouldn't expose your internal state unless it's totally necessary, and if you do, you should diminish as much as possible the potential side effects that may produce.
If you expose a reference of a mutable state, any other actor can change it's values, thus losing referential transparency. It's not by chance that all references to mutable collections are quite long, and difficult to use. That's a developer's message for you
Not surprisingly, the code still remains the same, with some minimal changes at the map instantiation.
var a = Map[String, Int]() withDefault insertNewValue
def insertNewValue(key: String): Int = {
a += key -> getValueForKey(key)
a(key)
}
def getValueForKey(key: String): Int = key.length
For your mutable map, you can just do:
val a = collection.mutable.Map(("k1" -> 1), ("k2" -> 5))
val key = "k1"
a.update(key, a.getOrElse(key, 0) + 5)
a // val res1: scala.collection.mutable.Map[String,Int] = HashMap(k1 -> 6, k2 -> 5)
I'll give you the tl;dr up front
I'm trying to use the state monad transformer in Scalaz 7 to thread extra state through a parser, and I'm having trouble doing anything useful without writing a lot of t m a -> t m b versions of m a -> m b methods.
An example parsing problem
Suppose I have a string containing nested parentheses with digits inside them:
val input = "((617)((0)(32)))"
I also have a stream of fresh variable names (characters, in this case):
val names = Stream('a' to 'z': _*)
I want to pull a name off the top of the stream and assign it to each parenthetical
expression as I parse it, and then map that name to a string representing the
contents of the parentheses, with the nested parenthetical expressions (if any) replaced by their
names.
To make this more concrete, here's what I'd want the output to look like for the example input above:
val target = Map(
'a' -> "617",
'b' -> "0",
'c' -> "32",
'd' -> "bc",
'e' -> "ad"
)
There may be either a string of digits or arbitrarily many sub-expressions at a given level, but these two kinds of content won't be mixed in a single parenthetical expression.
To keep things simple, we'll assume that the stream of names will never
contain either duplicates or digits, and that it will always contain enough
names for our input.
Using parser combinators with a bit of mutable state
The example above is a slightly simplified version of the parsing problem in
this Stack Overflow question.
I answered that question with
a solution that looked roughly like this:
import scala.util.parsing.combinator._
class ParenParser(names: Iterator[Char]) extends RegexParsers {
def paren: Parser[List[(Char, String)]] = "(" ~> contents <~ ")" ^^ {
case (s, m) => (names.next -> s) :: m
}
def contents: Parser[(String, List[(Char, String)])] =
"\\d+".r ^^ (_ -> Nil) | rep1(paren) ^^ (
ps => ps.map(_.head._1).mkString -> ps.flatten
)
def parse(s: String) = parseAll(paren, s).map(_.toMap)
}
It's not too bad, but I'd prefer to avoid the mutable state.
What I want
Haskell's Parsec library makes
adding user state to a parser trivially easy:
import Control.Applicative ((*>), (<$>), (<*))
import Data.Map (fromList)
import Text.Parsec
paren = do
(s, m) <- char '(' *> contents <* char ')'
h : t <- getState
putState t
return $ (h, s) : m
where
contents
= flip (,) []
<$> many1 digit
<|> (\ps -> (map (fst . head) ps, concat ps))
<$> many1 paren
main = print $
runParser (fromList <$> paren) ['a'..'z'] "example" "((617)((0)(32)))"
This is a fairly straightforward translation of my Scala parser above, but without mutable state.
What I've tried
I'm trying to get as close to the Parsec solution as I can using Scalaz's state monad transformer, so instead of Parser[A] I'm working with StateT[Parser, Stream[Char], A].
I have a "solution" that allows me to write the following:
import scala.util.parsing.combinator._
import scalaz._, Scalaz._
object ParenParser extends ExtraStateParsers[Stream[Char]] with RegexParsers {
protected implicit def monadInstance = parserMonad(this)
def paren: ESP[List[(Char, String)]] =
(lift("(" ) ~> contents <~ lift(")")).flatMap {
case (s, m) => get.flatMap(
names => put(names.tail).map(_ => (names.head -> s) :: m)
)
}
def contents: ESP[(String, List[(Char, String)])] =
lift("\\d+".r ^^ (_ -> Nil)) | rep1(paren).map(
ps => ps.map(_.head._1).mkString -> ps.flatten
)
def parse(s: String, names: Stream[Char]) =
parseAll(paren.eval(names), s).map(_.toMap)
}
This works, and it's not that much less concise than either the mutable state version or the Parsec version.
But my ExtraStateParsers is ugly as sin—I don't want to try your patience more than I already have, so I won't include it here (although here's a link, if you really want it). I've had to write new versions of every Parser and Parsers method I use above
for my ExtraStateParsers and ESP types (rep1, ~>, <~, and |, in case you're counting). If I had needed to use other combinators, I'd have had to write new state transformer-level versions of them as well.
Is there a cleaner way to do this? I'd love to see an example of a Scalaz 7's state monad transformer being used to thread state through a parser, but Scalaz 6 or Haskell examples would also be useful and appreciated.
Probably the most general solution would be to rewrite Scala's parser library to accommodate monadic computations while parsing (like you partly did), but that would be quite a laborious task.
I suggest a solution using ScalaZ's State where each of our result isn't a value of type Parse[X], but a value of type Parse[State[Stream[Char],X]] (aliased as ParserS[X]). So the overall parsed result isn't a value, but a monadic state value, which is then run on some Stream[Char]. This is almost a monad transformer, but we have to do lifting/unlifting manually. It makes the code a bit uglier, as we need to lift values sometimes or use map/flatMap on several places, but I believe it's still reasonable.
import scala.util.parsing.combinator._
import scalaz._
import Scalaz._
import Traverse._
object ParenParser extends RegexParsers with States {
type S[X] = State[Stream[Char],X];
type ParserS[X] = Parser[S[X]];
// Haskell's `return` for States
def toState[S,X](x: X): State[S,X] = gets(_ => x)
// Haskell's `mapM` for State
def mapM[S,X](l: List[State[S,X]]): State[S,List[X]] =
l.traverse[({type L[Y] = State[S,Y]})#L,X](identity _);
// .................................................
// Read the next character from the stream inside the state
// and update the state to the stream's tail.
def next: S[Char] = state(s => (s.tail, s.head));
def paren: ParserS[List[(Char, String)]] =
"(" ~> contents <~ ")" ^^ (_ flatMap {
case (s, m) => next map (v => (v -> s) :: m)
})
def contents: ParserS[(String, List[(Char, String)])] = digits | parens;
def digits: ParserS[(String, List[(Char, String)])] =
"\\d+".r ^^ (_ -> Nil) ^^ (toState _)
def parens: ParserS[(String, List[(Char, String)])] =
rep1(paren) ^^ (mapM _) ^^ (_.map(
ps => ps.map(_.head._1).mkString -> ps.flatten
))
def parse(s: String): ParseResult[S[Map[Char,String]]] =
parseAll(paren, s).map(_.map(_.toMap))
def parse(s: String, names: Stream[Char]): ParseResult[Map[Char,String]] =
parse(s).map(_ ! names);
}
object ParenParserTest extends App {
{
println(ParenParser.parse("((617)((0)(32)))", Stream('a' to 'z': _*)));
}
}
Note: I believe that your approach with StateT[Parser, Stream[Char], _] isn't conceptually correct. The type says that we're constructing a parser given some state (a stream of names). So it would be possible that given different streams we get different parsers. This is not what we want to do. We only want that the result of parsing depends on the names, not the whole parser. In this way Parser[State[Stream[Char],_]] seems to be more appropriate (Haskell's Parsec takes a similar approach, the state/monad is inside the parser).
EDIT
Ok, #dhg discovered that dot-method syntax required if the code block to fold() is not bound to a val (why with reduce() in the same code block one can use space-method syntax, I don't know). At any rate, the end result is the nicely concise:
result.map { row =>
addLink( row.href, row.label )
}.fold(NodeSeq.Empty)(_++_)
Which negates to some degree the original question; i.e. in many cases one can higher-order away either/or scenarios and avoid "fat", repetitive if/else statements.
ORIGINAL
Trying to reduce if/else handling when working with possibly empty collections like List[T]
For example, let's say I need to grab the latest news articles to build up a NodeSeq of html news <li><a>links</a></li>:
val result = dao.getHeadlines // List[of model objects]
if(result.isEmpty) NodeSeq.Empty
else
result map { row =>
addLink( row.href, row.label ) // NodeSeq
} reduce(_ ++ _)
This is OK, pretty terse, but I find myself wanting to go ternary style to address these only-will-ever-be either/or cases:
result.isEmpty ? NodeSeq.Empty :
result map { row =>
addLink( row.href, row.label )
} reduce(_ ++ _)
I've seen some old postings on pimping ternary onto boolean, but curious to know what the alternatives are, if any, to streamline if/else?
match {...} is, IMO, a bit bloated for this scenario, and for {...} yield doesn't seem to help much either.
You don't need to check for emptiness at all. Just use fold instead of reduce since fold allows you to specify a default "empty" value:
scala> List(1,2,3,4).map(_ + 1).fold(0)(_+_)
res0: Int = 14
scala> List[Int]().map(_ + 1).fold(0)(_+_)
res1: Int = 0
Here's an example with a List of Seqs:
scala> List(1,2).map(Seq(_)).fold(Seq.empty)(_++_)
res14: Seq[Int] = List(1, 2)
scala> List[Int]().map(Seq(_)).fold(Seq.empty)(_++_)
res15: Seq[Int] = List()
EDIT: Looks like the problem in your sample has to do with the dropping of dot (.) characters between methods. If you keep them in, it all works:
scala> List(1,2,3).map(i => node).fold(NodeSeq.Empty)(_ ++ _)
res57: scala.xml.NodeSeq = NodeSeq(<li>Link</li>, <li>Link</li>, <li>Link</li>)