Intellij code style to align single-line comments - scala

Right now IntelliJ's autoformat changes this:
val reduceFn = (left: U, right: U) => {
left ++ right // comment 1
.myFuncA( _._1 ) // comment 2
.myFuncABC { // comment 3
g => { // comment 4
g.myFun
._2
.myFunBBB( 0 )( _ + _ )
}
}
}: U // comment 5
to this:
val reduceFn = (left: U, right: U) => {
left ++ right // comment 1
.myFuncA( _._1 ) // comment 2
.myFuncABC {
// comment 3
g => {
// comment 4
g.myFun
._2
.myFunBBB( 0 )( _ + _ )
}
}
}: U // comment 5
Is there a way I can tell IntelliJ to produce, or, at the very least, not clobber the former style? I don't see comments as an option in Code Style in Editor > Code Style > Scala:

Unfortunately, I don't think this is supported at the moment. There's a ticket for it (SCL-4269), but as of writing there has not been any real activity on it.
You can completely disable the formatter for certain lines by using the formatter control option (cf. Code Style preference page). But that's obviously not a good solution.

Related

Is there a way to use map-like syntax for setting variables in non-map code blocks in Scala? [duplicate]

This question already has answers here:
Chaining operations on values without naming intermediate values
(2 answers)
Closed 2 years ago.
I am often writing code where I want to evaluate an expression and then pass the result of that expression down to the next block of code as a variable using syntax similar to that used with a map or fold expression.
The sort of code that I want to write would look something like we do with an Option or Future:
Some("foo") map { upper => s"works with $upper"}
but without objects that support map.
A good example (but not the only one) is doing replacement of Json elements in with the spray libraries. Something like:
JsObject(upper.fields +
("obj" -> JsObject(
upper.fields("obj").asJsObject { lower: JsObject => lower.fields +
("data" -> JsObject(lower.fields("data")))
}
))
)
Is there a way to accomplish this without resorting to nesting matches?
Answer 1: Here is an example using the mouse library with Scala 2.12:
def withMouse(upper: JsObject): JsObject = {
upper
.|> { upper => println(upper.compactPrint); upper.fields; }
.|> { upper => upper + ("obj" ->
upper("obj").asJsObject.fields
.|> { lower => JsObject(lower + ("data" ->
lower("data")
))}
)}
.|> { newmsg => JsObject(newmsg) }
}
Answer 2: Here is the same example using the ChainingOps library's .pipe method with Scala 2.13
def withPipe(upper: JsObject): JsObject = {
upper
.pipe { upper => println(upper.compactPrint); upper.fields; }
.pipe { upper => upper + ("obj" ->
upper("obj").asJsObject.fields
.pipe { lower => JsObject(lower + ("data" ->
lower("data")
))}
)}
.pipe { newmsg => JsObject(newmsg) }
}
It sounds like you want pipe().
From the ScalaDocs page:
import scala.util.chaining._
val times6 = (_: Int) * 6
//times6: Int => Int = $$Lambda$2023/975629453#17143b3b
val i = (1 - 2 - 3).pipe(times6).pipe(scala.math.abs)
//i: Int = 24
If not on Scala 2.13, there exists mouse which provides similar chaining operators, for example,
input
.<| { println }
.<| { preconditions }
.thrush { program }
.<| { postconditions }
.<| { println }
where
import mouse.all._
import scala.io.StdIn
case class User(name: String, age: Int, previous: Option[User] = None) {
def changeName(newName: String): User =
this.copy(name = newName, previous = Some(this))
}
def preconditions(user: User): Unit = {
assert(user.name.nonEmpty, "User should have a name")
assert(user.age >= 0, "User's age should not be negative")
}
def postconditions(`new`: User): Unit = {
assert(
`new`.previous.exists(_.name != `new`.name),
"User should have changed their name details"
)
}
def program(user: User): User = {
println(s"Please enter new name for $user")
val newName = StdIn.readLine()
user.changeName(newName)
}
val input = User("Picard", 75)
Note how <| just executes side-effect, whilst thrush may transform.

what do `^^^` and `~>` mean in sbt

I'm read the sbt documentation on Commands, and wondering what do ^^^ and ~> mean?
I tried to google but nothing found, these chars are escaped by google I guess...Thanks a lot
// Demonstration of a custom parser.
// The command changes the foreground or background terminal color
// according to the input.
lazy val change = Space ~> (reset | setColor)
lazy val reset = token("reset" ^^^ "\033[0m")
lazy val color = token( Space ~> ("blue" ^^^ "4" | "green" ^^^ "2") )
lazy val select = token( "fg" ^^^ "3" | "bg" ^^^ "4" )
lazy val setColor = (select ~ color) map { case (g, c) => "\033[" + g + c + "m" }
def changeColor = Command("color")(_ => change) { (state, ansicode) =>
print(ansicode)
state
}
The full code is as example project/CommandExample.scala at http://www.scala-sbt.org/0.13/docs/Commands.html
Those are methods on the RichParser class.
See http://www.scala-sbt.org/0.13/api/#sbt.complete.RichParser
Hint. If you look for symbolic methods click the '#' on the upper left corner of the api doc page.
^^^[B](value: B): Parser[B]: Apply the original Parser, but provide value as the result if it succeeds.
~>[B](b: Parser[B]): Parser[B]: Produces a Parser that applies the original Parser and then applies next (in order), discarding the result of the original parser.

How To Detect Keyboard Shortcuts like CTRL+S in Scala

I would like to detect keyboard shortcuts like CTRL+S in Scala. It is easy if only one key is pressed, but it seems to be difficult if two or more keys are pressed. Is there any better solution than the following?
reactions += {
case c # KeyReleased(_, Key.S, _, _) =>
if (c.peer.isControlDown())
// CTRL+S pressed
}
It feels somehow semantically incorrect since it checks if the CTRL button is pressed after the S button is released (and I think it is not really better when you use KeyPressed or KeyTyped).
Here is a SSCE:
import scala.swing._
import scala.swing.event._
object SSCCE extends SimpleSwingApplication {
def top = new MainFrame {
val textArea = new TextArea(3, 30)
contents = new FlowPanel {
contents += textArea
}
listenTo(textArea.keys)
reactions += {
case c # KeyReleased(_, Key.S, _, _) =>
if (c.peer.isControlDown())
Dialog.showMessage(null, "Message", "CTRL+S pressed")
}
}
}
You can check within the pattern match by testing the modifiers:
case c # KeyReleased(_, Key.S, mods, _) if (1 == (1 & mods>>7)) =>
Dialog.showMessage(null, "Message", "CTRL+S pressed")
When Ctrl is down, the bit at index 7 is set.
However, I think your original code is easier to understand.
Adding a helper function would help, of course:
def ctrlDown(mods:Int) = (1 == (1 & mods>>7))
...
case c # KeyReleased(_, Key.S, mods, _) if ctrlDown(mods) =>
Dialog.showMessage(null, "Message", "CTRL+S pressed")

Making code more functionally readable

I am looking at following snippet. When map-getOrElse and nested patten matching increases in the code it doesn't look so elegant. What better options do you suggest?
case MyMessage =>
val image = (request \ "image").asOpt[String]
image.map { im =>
val conf = (request \ "confirmation").asOpt[String]
conf.map { cf =>
//code to retrieve ride
ride match {
case Some(r) =>
if (booleanCondition) sender ! SuccessCommand(JsBoolean(true), command)
else sender ! FailureCommand("Problem updating", command)
case None => sender ! FailureCommand("Ride empty", command)
}
} getOrElse (sender ! FailureCommand("Missing number", command))
} getOrElse (sender ! FailureCommand("Missing image", command))
Whenever you are mapping over an Option with a function that produces an Option, you should consider whether you should be using flatMap:
def f(x: Int): Option[Int] = Some(x + 1)
f(1).flatMap(x => f(x)).flatMap(y => f(y)) // Some(4)
f(1).flatMap(x => f(x)).flatMap(y => f(y)).getOrElse(0) // 4
You can also use for-comprehensions for this, which is really nice for having clean code when you have long chains of these:
(for(x <- f(1); y <- f(x); z <- f(y)) yield z).getOrElse(0)
Another way to tackle this is to return Either[Command,String] from various helper functions, rather than Option. This would then allow you to use a for comprehension, something like the following:
val result = for {
i <- getImage().right
c <- getConf().right
r <- getRide().right
z <- check(r).right
} yield z
// extract either left or right, whichever is occupied
sender ! result.fold(identity, _ => success())
This has the desired property that we stop as soon as we encounter an error, and capture that specific error - or proceed to a successful conclusion.
I think you should be able to collapse a lot of this into Option.fold(), roughly as follows:
case MyMessage =>
sender !
getImage().fold(fail("Missing image")) { im =>
getConf().fold(fail("Missing number")) { conf => // conf isn't used
getRide().fold(fail("Ride empty")) { r =>
if (booleanCondition) succeed(true)
else fail("Problem updating")
}
}
}
This turns out a bit more concise than flatMap and orElse in this situation (see below)
Option.fold(ifEmpty){f} returns ifEmpty (evaluated lazily) if the option was empty, or evaluates the function f if the option was full.
The above code assumes you create helper functions for getting the various Options (or you could inline the relevant code). It also assumes you pull out the creation of commands into a helper function or two, to avoid all the duplicate references to command.
For comparison, a solution using flatMap looks something like:
case MyMessage =>
sender !
getImage().flatMap { im =>
getConf().flatMap { conf =>
getRide().flatMap { r =>
if (booleanCondition) Some(succeed(true))
else Some(fail("Problem updating"))
}.orElse(Some(fail("Ride Empty")))
}.orElse(Some(fail("Missing number")))
}.getOrElse(fail("Missing image"))
which you could shorten very slightly by having variants of your helper methods (fail and succeed) that return Some[Command] rather than Command

How to check if a character is contained in string?

I want to check if the string contains the character. I am writing a hangman code.
For example, here is the word to guess: "scala", but it looks like "_ _ _ _ _" tho the user. Let's assume that user inputs letter 'a', then it must look like "_ _ a _ a".
def checkGuess(){
if (result.contains(user_input)) {
val comp = result.toCharArray
for (i <- comp){
if (user_input != comp(i))
comp(i) = '_'
comp(i)
}
val str = comp.toString
}
}
Is this right?
Thank you in advance.
I don't think this is homework, so I'll probably regret answering if it is...
case class HangmanGame(goal: String, guesses: Set[Char] = Set.empty[Char]) {
override def toString = goal map {c => if (guesses contains c) c else '_'} mkString " "
val isComplete = goal forall { guesses.contains }
def withGuess(c: Char) = copy(guesses = guesses + c)
}
Then
val h = HangmanGame("scala")
h: HangmanGame = _ _ _ _ _
scala> val h1 = h.withGuess('a')
h1: HangmanGame = _ _ a _ a
scala> val h2 = h1.withGuess('l')
h2: HangmanGame = _ _ a l a
scala> val h3 = h2.withGuess('s')
h3: HangmanGame = s _ a l a
scala> val h4 = h3.withGuess('c')
h4: HangmanGame = s c a l a
scala> h4.isComplete
res5: Boolean = true
UPDATE
Okay, so it does look like homework. I guess the genie's out of the bottle now, but unless you get up to speed on Scala very quickly you're going to have a really hard time explaining how it works.
How about:
scala> def checkGuess(str: String, c: Char) = str.replaceAll("[^"+c+"]","_")
checkGuess: (str: String,c: Char)java.lang.String
scala> checkGuess("scala",'a')
res1: java.lang.String = __a_a
scala> def checkGuess2(str: String, C: Char) = str map { case C => C; case _ => '_'}
checkGuess2: (str: String,C: Char)String
scala> checkGuess2("scala",'a')
res2: String = __a_a
Here are some comments about how you wrote this. When using this syntax, def checkGuess() { ... }, the function will not return any value, it will return Unit instead.
This means that you're using it for its side effect only (such as setting some var outside the code block or printing some values). The issue is that you are not setting any value or printing anything inside the function (no printing, no assignment).
What you don't show in your code snippet is where you store the string to guess, the user input and the feedback to print. You can pass the first two as arguments and the last one as a returned value. This make the input and output self contained in the function and does not presume where you render the feedback.
def feedback(target:String, guesses:String): String = {
// target is the string to guess like "scala"
// guesses are the letters that have been provided so far, like "ac"
// last expression should be the feedback to print for instance "_ca_a"
}
Then you can think about the function as transforming each letter in target with _ or with itself depending on whether it is contained in guesses. For this the target map { c => expr } would work pretty well if you figure out how to make expr return c if c is in guesses and '_' otherwise.
Staying as close as possible to the main question ( How to check if a character is contained in string? ) what I did was changing the approach, i.e.:
Inside a for loop, I wanted to do something like some_chr == 't'
and I did the following some_chr.toString == "t" and it worked just fine.