functional programming - How to best declare a val being a Seq of previously declared vals in the block in Scala? -


a quite typical use case: object (or class) declares several public vals of related types, , declare accessor returning collection containing of them:

case class ball(dia :int) object balls {     val tennis = ball(7)     val football = ball(22)     val basketball = ball(24)     val balls = seq(tennis, football, basketball) } 

this example violates dry , error prone. can quite solved using mutable state (such adding implicit builder[ball, seq[ball]] parameter ball constructor. solution isn't without issues, either. particularily once try generalize solution and/or have class hierarchy every class declares values, moment when should switch mutable partial summary final immutable value not clear.

more intellectual exercise , out of curiosity trying come purely functional variant, without success. best came is

object balls {     import shapeless.{::, hnil}      val (balls @             tennis ::football::basketball::hnil         ) =             ball(7)::ball(22)::ball(24)::hnil } 

which quite neat, becomes unmanagable once number of balls or initializers aren't tiny. working alternative change hmap, try avoid shapeless dependencies in public api. seems perhaps doable scala continuations, have no idea how make declarations non-local reset block.

edit: haven't stressed before, , reason why scala.enumeration doesn't job me, in real case objects aren't identical, in fact composite structures, constructors take several lines or more. so, while final type may same (or @ least i'm not interested in details), isn't simple enumeration, , readability reasons important name of declared member/key can tied visually definition. shapeless solution here, shapelessless seq-based proposed, susceptible off-by-one errors, modification made wrong value, mistaking real identifier.

of course, real case implemented scala.enumeration, maintaining sequence of values produced inherited constructor method. suffers problems enumeration does, , amplifies probability of errors calling constructor outside of actual object balls initializer, or discarding value in conditional block. besides, quite interested how solved in purely functional languages.

any ideas how have cake , eat it?

not sure for, per tried using shapeless, believe can achieve without it, , quite similar of did:

case class ball(dia :int) object balls {     val balls@seq( tennis, football, basketball ): seq[ball] = ball(7)::ball(22)::ball(24)::nil } 

on other side, answered kind of of enumeration, use here.

edit

have considered model data in more descriptive way. let´s see:

sealed trait balls {     def dia: int } case object football { val dia: int = 22 } case object tennis { val dia: int = 7 } case object basketball { val dia: int = 24 }  object balls {     val values: seq[ball] = football :: tennis :: basketball :: nil } 

advantages of approach this, use of pattern matching, still pattern matched ball extract diameter while being able refine pattern matching subtypes.

def kickball( in: ball ): boolean = {     in match {         case f: football =>              true         case b: basketball =>             // shouldn't             false         case _ =>             // else             false     } } 

using sealed force define types on same file , compiler let know when forget cases on pattern matching.

still having boilerplate, typical approach model solutions in functional way.


Comments

Popular posts from this blog

javascript - Thinglink image not visible until browser resize -

firebird - Error "invalid transaction handle (expecting explicit transaction start)" executing script from Delphi -

mongodb - How to keep track of users making Stripe Payments -