This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Control structure question

5 replies
Samuel Robert Reid
Joined: 2008-12-17,
User offline. Last seen 1 year 22 weeks ago.

Scala Community,

I find myself using this idiom in several places:

model.addListenerByName(updateSelf())
model2.addListenerByName(updateSelf())
updateSelf //synchronize view with model immediately
def updateSelf() = {...}

Is there an elegant way to get rid of the call to updateSelf (perhaps
wrap it into a control structure)? Maybe the client code could look
something like this:

val updateSelf = defineAndInvoke{...}
model.addListenerByName(updateSelf)
model2.addListenerByName(updateSelf)

I'm not sure how defineAndInvoke would look, and I'm not sure how
updateSelf (in the latter example) would be converted to a callable method.

Thanks,
Sam Reid

Samuel Robert Reid
Joined: 2008-12-17,
User offline. Last seen 1 year 22 weeks ago.
Re: Control structure question

Somehow I dropped a newline in my first snippet; it should read:

model.addListenerByName(updateSelf())
model2.addListenerByName(updateSelf())
updateSelf //synchronize view with model immediately
def updateSelf() = {...}

Thanks,
Sam Reid

Samuel Robert Reid wrote:
> Scala Community,
>
> I find myself using this idiom in several places:
>
> model.addListenerByName(updateSelf())
> model2.addListenerByName(updateSelf()) updateSelf
> //synchronize view with model immediately
> def updateSelf() = {...}
>
> Is there an elegant way to get rid of the call to updateSelf (perhaps
> wrap it into a control structure)? Maybe the client code could look
> something like this:
>
> val updateSelf = defineAndInvoke{...}
> model.addListenerByName(updateSelf)
> model2.addListenerByName(updateSelf)
> I'm not sure how defineAndInvoke would look, and I'm not sure how
> updateSelf (in the latter example) would be converted to a callable
> method.
>
> Thanks,
> Sam Reid

Jon Pretty
Joined: 2009-02-02,
User offline. Last seen 42 years 45 weeks ago.
Re: Control structure question

Hi Sam,

Samuel Robert Reid wrote:
>> Is there an elegant way to get rid of the call to updateSelf (perhaps
>> wrap it into a control structure)?

I'm not sure I understand the context, but does the following help?

def updateStuff(block : => Foo) = {
model.addListenerByName(block)
model2.addListenerByName(block)
block
}

and we can then call:

updateStuff {
...
}

Though, I'd be interested to learn a bit more about the return type and
definition of your updateSelf() method...

Cheers,
Jon

Samuel Robert Reid
Joined: 2008-12-17,
User offline. Last seen 1 year 22 weeks ago.
Re: Control structure question
After looking into this a bit more, it seems like a reasonable solution is to evaluate the block and return a partially applied function like this:

object TestBlock {
    def main(args: Array[String]) = {

        val block = defineAndInvoke{
            println("evaluated block")
        }

        block()
        block()
    }

    def defineAndInvoke(block: => Unit): () => Unit = {
        block
        block _
    }
}

This correctly prints "evaluated block" 3 times.  Is there a way to remove the parens from the last 2 block() calls in main?  When I do so, it doesn't evaluate, since the block is a partial function.

Sam Reid

Jon Pretty wrote:
498F13EF [dot] 5010703 [at] sygneca [dot] com" type="cite">
Hi Sam,

Samuel Robert Reid wrote:
  
Is there an elegant way to get rid of the call to updateSelf (perhaps
wrap it into a control structure)?
      
I'm not sure I understand the context, but does the following help?

   def updateStuff(block : => Foo) = {
     model.addListenerByName(block)
     model2.addListenerByName(block)
     block
   }

and we can then call:

   updateStuff {
     ...
   }

Though, I'd be interested to learn a bit more about the return type and
definition of your updateSelf() method...

Cheers,
Jon

  
Jon Pretty
Joined: 2009-02-02,
User offline. Last seen 42 years 45 weeks ago.
Re: Control structure question

Hi Sam,

Samuel Robert Reid wrote:
> Is there a way to
> remove the parens from the last 2 block() calls in main? When I do so,
> it doesn't evaluate, since the block is a partial function.

I have a feeling I'm skirting around the point here, but does the
following do what you want it to?

object TestBlock {
def main(args : Array[String]) = {
def block = {
println("evaluated block")
}
block
block
}
}

Having said that, if 'block' has side-effects, such as printing
something to stdout (I'm presuming it does, as it returns Unit), I'd
recommend following the convention of putting parentheses after it to
indicate this, i.e.,

object TestBlock {
def main(args : Array[String]) = {
def block() = {
println("evaluated block")
}
block()
block()
}
}

You could also do the following:

trait DefineAndInvoke {
private var definition : (() => Unit) = () => ()
def define(block : => Unit) = definition = {
block
block _
}
def invoke() : Unit = definition()
}

object TestBlock extends DefineAndInvoke {
define {
println("evaluated block")
}
invoke()
invoke()
}

Whilst this is quite neat at the low-level, in the grander scheme of
whatever your project does, there's almost certainly a better solution...

Hope this helps anyway,
Jon

Samuel Robert Reid
Joined: 2008-12-17,
User offline. Last seen 1 year 22 weeks ago.
Re: Control structure question
I have a feeling I'm skirting around the point here, but does the
following do what you want it to?

   object TestBlock {
     def main(args : Array[String]) = {
       def block = {
         println("evaluated block")
       }
       block
       block
     }
   }

This is not quite what I had in mind, my idea was to be able to define a block, obtain a reference to it and invoke it with one call.  Your example requires 2 lines to declare and invoke the block.

I did show in a follow-up email how this can be done with partially applied functions; thanks for pointing out the convention that blocks with side-effects should use parens; this solution should work well.

Thanks again for your feedback,
Sam Reid

Jon Pretty wrote:
4990458B [dot] 9040006 [at] sygneca [dot] com" type="cite">
Hi Sam,

Samuel Robert Reid wrote:
  
Is there a way to
remove the parens from the last 2 block() calls in main?  When I do so,
it doesn't evaluate, since the block is a partial function.
    
I have a feeling I'm skirting around the point here, but does the
following do what you want it to?

   object TestBlock {
     def main(args : Array[String]) = {
       def block = {
         println("evaluated block")
       }
       block
       block
     }
   }

Having said that, if 'block' has side-effects, such as printing
something to stdout (I'm presuming it does, as it returns Unit), I'd
recommend following the convention of putting parentheses after it to
indicate this, i.e.,

   object TestBlock {
     def main(args : Array[String]) = {
       def block() = {
         println("evaluated block")
       }
       block()
       block()
     }
   }


You could also do the following:

   trait DefineAndInvoke {
     private var definition : (() => Unit) = () => ()
     def define(block : => Unit) = definition = {
       block
       block _
     }
     def invoke() : Unit = definition()
   }

   object TestBlock extends DefineAndInvoke {
     define {
       println("evaluated block")
     }
     invoke()
     invoke()
   }

Whilst this is quite neat at the low-level, in the grander scheme of
whatever your project does, there's almost certainly a better solution...

Hope this helps anyway,
Jon

  

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland