- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Control structure question
Sun, 2009-02-08, 04:21
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
Sun, 2009-02-08, 18:27
#2
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
Mon, 2009-02-09, 03:37
#3
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:
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
Mon, 2009-02-09, 16:07
#4
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
Mon, 2009-02-09, 20:27
#5
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
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