scala: preferred way of using map function - scala

I prefer to apply map on a list as:
items.map( myItem => ...)
But I also see many examples as:
items.map { case MyItem(...) => ... }
So which one is idiomatic?

Both are perfectly fine. The second one is just a convenient syntax sugar for
items.map { myItem =>
myItem match {
case MyItem(...) => ...
}
}
If you don't need to do a match on myItem, then the first syntax is what you'd generally use.

Related

Match an underscore instead of ident in macro

I'm creating a macro that matches two expressions and an identifier. I would like to be able to ignore the identifier if it's not needed, but the compiler seems to complain if I use _ there.
My macro:
macro_rules! if_some {
($x:expr, $id:ident, $expr:expr) => {
match $x {
None => None,
Some($id) => Some($expr),
}
};
}
What I'd like to do:
if_some!(obtain_an_option(), x, do_something_with(x))
and
if_some!(obtain_an_option(), _, do_something())
The second call fails.
I worked around it by defining a second macro if_some_! that doesn't receive an identifier (I could not use a second pattern either). I'm sure there's a way to say "here accept an identifier or just _.
Maybe there's already a macro/function for this (like Option::map now I think about it)... nevertheless it'd be nice to now.
The simplest way is to add a second arm that matches an underscore:
macro_rules! if_some {
($x:expr, _, $expr:expr) => {
match $x {
None => None,
Some(_) => Some($expr),
}
};
($x:expr, $id:ident, $expr:expr) => {
match $x {
None => None,
Some($id) => Some($expr),
}
};
}
And, yes, this sounds like you just want Option::map.
Option::map seems to be the best solution for this particular problem, but when you really need a macro which expect both idents and _ as a pattern, you can also use the $p:pat fragment. The fragment of course accepts a broader range of patterns like (ref x, y), but typically this will be acceptable.
macro_rules! if_some {
($x:expr, $p:pat, $expr:expr) => {
match $x {
None => None,
Some($p) => Some($expr),
}
};
}
fn main() {
println!("{:?}", if_some!(Some(12), x, x + 1)); // Some(13)
println!("{:?}", if_some!(Some(12), _, 1)); // Some(1)
}

Capture argument to partial function

I am trying to debug a Scala program (this is a build.sbt, but the question is not particular for sbt), where I need to give a partial function for a certain sbt setting. The value for the partial function looks like this
{
case Regex1(a,b,c) =>
case Regex2(d,e,f) =>
...
}
The partial function does not do what I want, so I wanted to debug it. Because I don't know exactly what is passed in, I want to capture the value that is passed into the partial function, but I don't know how to do that.
I could add a case a => println(a) at the beginning of the partial function, but this breaks the whole function.
You can do this:
val print: PartialFunction[InputType, InputType] = { case i => println(i); i }
print andThen {
case Regex1(a,b,c) => ...
case ...
}
I finally figured out how to do it. It is not very elegant, so if anyone knows of a better way, please add another answer!
The solution is to create the partial function explicitly as value:
val result = new PartialFunction[InputType,ResultType] {
def apply(value: InputType) = {
println("input is: " + value) // Yay, I captured the value
value match {
// Same as above
}
}
def isDefinedAt(value: InputType) = true
}
result
Another option would be to match all, and add another match that does the actual work:
{
case value => {
println(value)
value match {
// the original partial function
...
// you might need to add a catch-all that
// does nothing or returns a default value
case _ => None
}
}
}

Pattern matching using current object

I'm trying to match an Option, and test to see if it's a Some containing the object making the call. So the code I want to write looks like this:
methodReturningOption() match {
case Some(this) => doSomething()
case _ => doSomethingElse()
}
but that fails to compile, with the error
'.' expected but ')' found
I also tried using Some(`this`) which gives the error
not found: value this
I can make it work if I add a variable which refers to this
val This = this
methodReturningOption() match {
case Some(This) => doSomething()
case _ => doSomethingElse()
}
but that looks ugly and seems like an unpleasant workaround. Is there an easier way to pattern match with this as an argument?
I suppose you could try this:
methodReturningOption() match {
case Some(x) if x == this => doSomething()
case _ => doSomethingElse()
}
It looks like this is considered a special keyword and can't be used in that context.
Jack Leow's solution is probably the best - I'd recommend going with that since it's much more explicit. However as an alternative you can also create a variable point to 'this' using the following syntax. (Note the self => on the first line)
class Person { self =>
def bla() = methodReturningOption() match {
case Some(`self`) => ???
case _ => ???
}
}
This doesn't really answer the question, it's just a potential alternative syntax that may be useful to you.

How to map an Option case class

Say, there is a case class
case class MyCaseClass(a: Int, b: String)
and an Option[MyCaseClass] variable
val myOption: Option[MyCaseClass] = someFunctionReturnOption()
Now, I want to map this Option variable like this:
myOption map {
case MyCaseClass(a, b) => do some thing
}
It seems the compiler reports error like It needs Option[MyCaseClass], BUT I gave her MyCaseClass, bla bla... How to use pattern match in Optional case class ?
Consider extracting the Option value like this,
myOption map {
case Some(MyCaseClass(a, b)) => do some thing
case None => do something else
}
or else use collect for a partial function, like this
myOption collect {
case Some(MyCaseClass(a, b)) => do some thing
}
Update
Please note that as commented, the OP code is correct, this answer addresses strictly the last question How to use pattern match in Optional case class ?
MyOption match {
Some(class) => // do something
None => // do something.
}
Or
MyOption map (class =>//do something)

How to pipe the result of a transformation chain to a function?

I want to write a chain of transformations and finally have a block where I do something with the resulting collection, without using variables.
Is there a higher-order function on collections that just provides the collection on which it is called to the supplied function?
Query( ... )
.map { ... }
.filter { ... }
.combinations(2)
.pipeTo { col =>
...
consolidate(col)
}
Of course for a single function call one could do it like this:
consolidate(
Query()
.map { ... }
.filter { ... }
.combinations(2)
)
But the former reads more natural to me and allows e.g. for an easy injection of some conditionals.
A workaround I've been using is placing a match clause at the end:
Query()
.map { ... }
.filter { ... }
.combinations(2)
match { case lst =>
...
consolidate(lst)
}
But since this pattern occurs quite often I was wondering what is the idiomatic way to write this.
Perhaps the most idiomatic way would be to use the so called Pimp My Library Pattern, which allows one to add extension methods to any classes via implicit class conversions.
For example, to add a consolidate method to Lists, you could write:
object ListExtensions {
implicit class ConsolidatableList[T](val lst: List[T]) extends AnyVal {
def consolidate = ??? // Do whatever you want with the List lst
}
}
import ListExtensions._
List(1,2,3)
.map(x => x * x)
.consolidate
If you really want to be able to call arbitrary functions on arbitrary objects in a chain, you could even define an "pipeline" operator like in F#:
object Extensions {
implicit class PipelineExtension[T](val obj: T) extends AnyVal {
def |>[S](f: T => S): S = f(obj)
}
}
import Extensions._
List(1,2,3)
.map(x => x * x)
.|> (consolidate)
Query( ... )
.map { ... }
.filter { ... }
.combinations(2)
.|> { col =>
...
consolidate(col)
}
The |> operator behaves like the pipeTo method you have defined.
Basically, this works by creating an implicit conversion from your type to the type with the various extension methods that you define. The AnyVal makes the extension class an value class, so its use will have little to no runtime cost.