logo       

Re: emulating Smalltalk syntax in Scala: snippet: msg#00470

lang.scala

Subject: Re: emulating Smalltalk syntax in Scala: snippet

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))

}


The invocation is not as pretty, but this involves much less work to define the constructor. One thing that concerns me is the possibility for namespace clashing if this trick ever becomes popular.

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>
Google Custom Search

News | FAQ | advertise