I have this scala3 code:
val times4 = List.fill(4)
val oranges = times4("orange")
println(oranges)
Output is:
List(orange, orange, orange, orange)
But, is this correct behaviour? Because intellij tells me times4 is:
Nothing => List[Nothing]
But it is able to accept String type, while String is not a Nothing
I have a structure of nested case classes that I create with default values:
case class Alpha(text: String = "content")
case class Beta(alpha: Alpha = Alpha())
case class Gamma(beta: Option[Beta] = None)
I would like to create the whole thing with default values and then modify the elements in particular that need to be non-default using Monocle.
With isos is easy. I can specify the navigation with composition and then use set to modify the inner element:
object Beta {
val alphaI: Iso[Beta, Alpha] = GenIso[Beta, Alpha]
}
object Alpha {
val textI: Iso[Alpha, String] = GenIso[Alpha, String]
}
(Beta.alphaI composeIso Alpha.textI).set("foo")(Beta()) shouldBe Beta(Alpha("foo"))
Unfortunately with prims it doesn't seem that elegant, as set/modify will only modify the inner element if all the options during the navigation are defined (Some(...))
object Gamma {
val betaI: Iso[Gamma, Option[Beta]] = GenIso[Gamma, Option[Beta]]
val betaP: Prism[Gamma, Beta] = Prism[Gamma, Beta](_.beta)(a => Gamma(Some(a)))
}
val navigateToText: Prism[Gamma, String] = Gamma.betaP composeIso Beta.alphaI composeIso Alpha.textI
navigateToText.set("foo")(Gamma(None)) shouldBe Gamma(None)
navigateToText.set("foo")(Gamma(Some(Beta()))) shouldBe Gamma(Some(Beta(Alpha("foo"))))
The best thing I've come up with so far is using a composed optic to set to a Some() each optional element of the path and then the composed optic all the way down to set the element we were interested in to begin with.
(Gamma.betaI.set(Some(Beta())) andThen navigateToText.set("foo")) (Gamma()) shouldBe Gamma(Some(Beta(Alpha("foo"))))
Ideally I'd like each building block of the composition to set the optional values to Some(defaultValue) if they are originally None. Obviously the building block would need to be defined including the appropriate default value for the step of the path.
Any suggestions?
Full code including imports: https://github.com/jcaraballo/navigating-fixtures-with-monocle/blob/master/src/test/scala/pr/NavigateIntoOptionSpec.scala
You could use below from Prism such as the types match in the optics composition:
import monocle.macros.GenIso
import scalaz.std.option._
case class Alpha(text: String = "content")
case class Beta(alpha: Alpha = Alpha())
case class Gamma(beta: Option[Beta] = None)
val navigateToText = GenIso[Gamma, Option[Beta]] composePrism
GenIso[Beta, Alpha].asPrism.below[Option] composePrism
GenIso[Alpha, String].asPrism.below[Option]
navigateToText.set(Some("foo"))(Gamma(None)) // Gamma(Some(Beta(Alpha(foo))))
navigateToText.set(Some("foo"))(Gamma(Some(Beta(Alpha("bar"))))) // Gamma(Some(Beta(Alpha(foo))))
I am trying to get the concrete type in a scala macro for a scala.Enumeration.
For example, given
def applyImpl[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[String] = ???
Then for
object Colours extends Enumeration {
val Red, Amber, Green = Value
}
I would like the output to be com.package.Colours (or even just Colours).
I have tried multiple things, but all I can get is a handle to the Enumeration#Value class, and from there I cannot see to work backwards into the real type. Is it even available?
I have an enum like this:
object Animals extends Enumeration {
type Animals = Value
val Monkey = Value("Monkey")
val Lion = Value("Lion")
val Dog = Value("Dog")
val Cat = Value("Cat")
}
and I need to pick at random an element from this enumeration. How can i efficiently do this in scala?
Less than a minute with the documentation shows
final def maxId: Int
The one higher than the highest integer amongst those used to identify values in this enumeration.
and
final def apply(x: Int): Value
The value of this enumeration with given id x
So
Animals(scala.util.Random.nextInt(Animals.maxId))
//> res0: recursion.recursion.Animals.Value = Monkey
(assuming all values are used, and you didn't pass in an initial value to the constructor)
Or you could enumerate the values with Animals.values and then refer to this question
Any idea how I can avoid these repeated class parameters?
abstract class XClass( var x: Int, var y: Int, var w: Int, var h: Int) {...}
abstract class MXClass( var xS: Int, var yS: Int, var wS: Int, var hS: Int)
extends XClass (xS, yS, wS, hS)
class PXClass( var xP: Int = 0, var yP: Int = 0, var wP: Int = 0, var hP: Int = 0)
extends MXClass (xP, yP, wP, hP)
def draw(g: Graphics2D) {
g fillRect (x, y, w, h)
}
then I have something like this in a GUI:
g setColor black
val cc = new PXClass(200, 300, 10, 10)
cc.draw(g)
So I am giving those parameters as they are needed in the GUI!
Thanks
According to what you said:
the XClass is a Piece class and MXClass is a MovablePiece then PXClass is RectanglePiece class. Then I need Piece class to extend by StationaryPiece, thus I am trying to have some movable and statinary pieces in a BoardPanel of different shapes. – Val 18 mins ago
Let's just start out by defining them one by one — let's not use any inheritance because it's not immediately obvious it's even needed; you can come back to inheritance (or some other type of polymorphism) when needed but trust me it's never actually needed:
sealed trait Shape
case object Rectangle extends Shape
case object Square extends Shape
case object Circle extends Shape
case class Dimensions(x: Int, y: Int, w: Int, h: Int)
case class Piece(shape: Shape, dim: Dimensions, isMovable: Boolean = true)
val squarePiece = Piece(Square, Dimensions(x = 100, y =. 200, w = 20, h = 20))
val circularPiece = Piece(Circular, Dimensions(x = 0, y = -100, w = 40, h = 40))
val immovableRectPiece = Piece(Rectangle, Dimensions(...), isMovable = false)
and then you can define a function to take any piece and draw it:
def draw(piece: Piece) = piece.shape match {
case Rectangle => ...
case Square => ...
case Circle => ...
}
...and methods for binary functions:
case class Piece(...) {
def collidesWith(other: Piece) = ...
def overlapsWith(other: Piece) = ...
}
then:
draw(immovablePiece)
if (piece1 collidesWith piece2) ...
if (piece1 overlapsWith piece2) ...
You're free to make draw a method of Piece as well, but it doesn't really matter — if you manage to avoid inheritance, all methods become equivalent to plain functions anyway.
There is no need to use inheritance (i.e. subtype polymorphism); it's always best to start out with mathematically purer concepts and avoid extends altogether. If you consider the code I've demonstrated, you'll realise that it gives you a way to compose bits and pieces instead of providing monolithic types; it also allows you to convert one type of piece to another by providing an alternative value for an attribute — this is not possible with inheritance; it's not possible to change the type of an object once created.
val immovableCirclePiece = circularPiece.copy(isMovable = false)
Note that the Shape inheritance tree starting with that sealed trait is not the same as regular inheritance — what it does it defines an Algebraic Data Type, which in this case resembles quite closely what would be an enum in Java.
Furthermore, you could try to extract the data that is relevant to drawing/rendering and put it all in a, say, Representation class that holds both the Point as well as a rendering function to draw specific shapes. Feel free to ask for clarification — there's a lot to say and I'm only trying to get you started with designing your programs in a more sophisticated manner :)
Just write:
class PXClass extends MXClass (0, 0, 0, 0)