|
Re: emulating Smalltalk syntax in Scala: snippet: msg#00470lang.scala
Hi Adriaan. I'm also a huge fan of Smalltalk syntax. I think positional parameters are an enemy of immutable objects, because calling a constructor with a long sequence of arguments is clumsy and brittle, which sometimes leads programmers to prefer explicitly calling setter methods. In Java I tend to use builder objects to overcame this problem. An example of this technique in Scala: class Image(val uri:String , val size:long, val height:long, val width:long) {} //Not constructed by clients directly class ImageBuilder { //mutable builder var uri:String = _ var size:long = _ var height:long = _ var width:long = _
def withURI(u :String ) : ImageBuilder = {this. uri = u; this} def withSize(sz :long) : ImageBuilder = {this.size = sz ; this} def withHeight(h :long) : ImageBuilder = {this.height = h; this} def withWidth(w :long) : ImageBuilder = {this.width = w; this}
def build: Image = new Image( uri, size , height, width) }
object Image { def make = new ImageBuilder (); }
object Client { val x = Image .make withURI "someUri" withSize 1024 withHeight 480 withWidth 640 build //This has to be on a single line to please the parser } It is possible to make the builder immutable, but it would be even more verbose. Another alternative is to create a case class for each parameter:case class uri(v:String ) case class fileSize(v:long) case class height(v:long) case class width(v:long) class Image(val u:uri, val sz:fileSize, val h:height, val w:width) { val uri = u.v val fileSize = sz.v val height = h.v val width = w.v } object Client { val x = new Image(uri("someUri" ), fileSize(1024), height(480), width(640)) }
As always, ideas for improvement are very welcome. Cheers On 1/28/07, Adriaan Moors <adriaan.moors@xxxxxxxxxxxxxx> wrote: > Hi, > > I just wanted to generate some more noise on the mailing list with a neat > trick I (re-)discovered [1] today ;-) > > I noticed my code had this recurring pattern of > > val r=result > doSomethingForEffectOnly > r > > at the end of a method, in order to return result, but first performing some > effect (which does not affect result). > > So, I wrote this little contraption: > trait After[t]{def after(block: =>unit):t} // gotta love Smalltalk syntax > ;-) > def return_[t](result: t): After[t] = new After[t]{val r=result; def > after(block: =>unit):t = {block; r}} > > > > > Now you can write (to give you a more concrete example than > doSomethingForEffectOnly -- everything but genId is just for context): > > > > > trait Binders { > private object _Binder { > private var currentId = 0 > private[Binders] def genId = return_(currentId) after > {currentId=currentId+1} > } > // ... > } > > instead of: def genId = {val r=currentId; currentId=currentId+1; r} > > I'm not entirely happy with the name "after" as you might mis-interpret > genId as returning currentId+1, > but for now I haven't been able to think of a better name... > > Anyway, I thought this might interest someone; it certainly is a tribute to > Scala's flexible syntax! > > regards, > adriaan > > > [1] This trick also used to be in scala.collection.mutable.Map (it's now > deprecated) > def +=(key: A): MapTo = new MapTo(key) > > class MapTo(key: A) { > def ->(value: B): Unit = update(key, value) > } > Disclaimer: > http://www.kuleuven.be/cwis/email_disclaimer.htm for more > information. > -- Rafael de F. Ferreira. http://www.rafaelferreira.net/ |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | Prioritizing message handling in actors: 00470, David Pollak |
|---|---|
| Next by Date: | Re: Implicit type conversion: 00470, Burak Emir |
| Previous by Thread: | emulating Smalltalk syntax in Scala: snippeti: 00470, Adriaan Moors |
| Next by Thread: | Views: 00470, Tony Morris |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |