Private names

View: New views
5 Messages — Rating Filter:   Alert me  

Private names

by Janne Savukoski :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message

Hello,

This feels a little stupid, and I'm sure there's something
fundamentally n00b in this, but anyways... I've been experimenting
with this kind of structure (note the pipe, '|', on 2nd line):

<clip>
1: sw.sendMessage {
2:   new Message | { m =>
3:     m.setDisplayName(somename)
4:     m.setContent(format("Hello, %s! %s!", displayName, somecontent))
5:   }
6: }
</clip>

which is similar to

1: val m = new Message
2: m.setDisplayName(somename)
3: m.setContent(format("Hello, %s! %s!", displayName, somecontent))
4: sw.sendMessage(m)

and

1: sw.sendMessage {
2:   val m = new Message
3:   m.setDisplayName(somename)
4:   m.setContent(format("Hello, %s! %s!", displayName, somecontent))
5:   m
6: }


The last one was my favorite before the pipe, but it suffers from the
explicit return. The second I don't like a bit as it exposes the name
'm' that is relevant only in the context of the 'sendMessage'
invocation.

In the first case the pipe—which returns the object itself—replaces an
ad-hoc-initialization-block-using-anonymous-subclass. More generally,
with pipe I can write a block with a 'private' reference to the
context object. (or something...)

The pipe is defined simply as

implicit def pipe4Any[a](any: a) = new AnyRef { def |(f:a => Unit): a
= { f(any); any } }

Another nice use case was with logging:

1: rs.report(WARNING, root, format("Resource not found: %s",
f.getAbsolutePath) | (warn(_)))

where the message "Resource n..." is logged ('warn', shortcut to
commons logging) while passed on to the report method. (No
ad-hoc-initialization-block-using-anonymous-subclass here.)

So, this is just such a trivial use case that I'm sure there's some
standard way to do this. Please, feel free to show me the light. :)


-janne

Re: Private names

by Rafael de F. Ferreira-2 :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message

Hi Janne.

I was under the impression that the
ad-hoc-initialization-block-using-anonymous-subclass trick was the
"standard way" to do this kind of thing in Scala. In your example, I
infer that Message is a Java class, but if it was written in Scala,
one idiom for initialization would be to declare abstract vals, like
this:

abstract class Message {
  val displayName:String
  val content:String
}

sw sendMessage (new Message {
   val displayName = somename
   val content = format("Hello, %s! %s!", displayName, somecontent)
})


Anyway, I really liked your second example, using the pipe and the
underscore closure shorthand together looks like a cool technique.

On Oct 30, 2007 8:29 AM, Janne Savukoski <janne@...> wrote:

> Hello,
>
> This feels a little stupid, and I'm sure there's something
> fundamentally n00b in this, but anyways... I've been experimenting
> with this kind of structure (note the pipe, '|', on 2nd line):
>
> <clip>
> 1: sw.sendMessage {
> 2:   new Message | { m =>
> 3:     m.setDisplayName(somename)
> 4:     m.setContent(format("Hello, %s! %s!", displayName, somecontent))
> 5:   }
> 6: }
> </clip>
>
> which is similar to
>
> 1: val m = new Message
> 2: m.setDisplayName(somename)
> 3: m.setContent(format("Hello, %s! %s!", displayName, somecontent))
> 4: sw.sendMessage(m)
>
> and
>
> 1: sw.sendMessage {
> 2:   val m = new Message
> 3:   m.setDisplayName(somename)
> 4:   m.setContent(format("Hello, %s! %s!", displayName, somecontent))
> 5:   m
> 6: }
>
>
> The last one was my favorite before the pipe, but it suffers from the
> explicit return. The second I don't like a bit as it exposes the name
> 'm' that is relevant only in the context of the 'sendMessage'
> invocation.
>
> In the first case the pipe—which returns the object itself—replaces an
> ad-hoc-initialization-block-using-anonymous-subclass. More generally,
> with pipe I can write a block with a 'private' reference to the
> context object. (or something...)
>
> The pipe is defined simply as
>
> implicit def pipe4Any[a](any: a) = new AnyRef { def |(f:a => Unit): a
> = { f(any); any } }
>
> Another nice use case was with logging:
>
> 1: rs.report(WARNING, root, format("Resource not found: %s",
> f.getAbsolutePath) | (warn(_)))
>
> where the message "Resource n..." is logged ('warn', shortcut to
> commons logging) while passed on to the report method. (No
> ad-hoc-initialization-block-using-anonymous-subclass here.)
>
> So, this is just such a trivial use case that I'm sure there's some
> standard way to do this. Please, feel free to show me the light. :)
>
>
> -janne
>



--
Rafael de F. Ferreira.
http://www.rafaelferreira.net/

Re: Private names

by Janne Savukoski :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message

Hi Rafael!

On 10/30/07, Rafael de F. Ferreira <rafael@...> wrote:

> Hi Janne.
>
> I was under the impression that the
> ad-hoc-initialization-block-using-anonymous-subclass trick was the
> "standard way" to do this kind of thing in Scala. In your example, I
> infer that Message is a Java class, but if it was written in Scala,
> one idiom for initialization would be to declare abstract vals, like
> this:
>
> abstract class Message {
>   val displayName:String
>   val content:String
> }
>
> sw sendMessage (new Message {
>    val displayName = somename
>    val content = format("Hello, %s! %s!", displayName, somecontent)
> })

Thanks for confirming that, I had no idea if it was a popular
technique with Scala. I myself try to avoid it, as it feels a little
intrusive and, well, 'blunt'. :) But it certainly is a smooth way.


> Anyway, I really liked your second example, using the pipe and the
> underscore closure shorthand together looks like a cool technique.

Nice :) . Btw., if the method 'warn' wasn't overloaded, the syntax
could be reduced into just '"foo" | warn'. Although, I'm thinking the
name '|' may be a little confusing as it doesn't transform the
source.. (Instead, if we named map+filter to pipe, it would be shell
scripts all over again. :)

But anyways, it's funny that there hasn't been more suggestions about
some standard ways for replacing this proprietary hack. I'm just a
Scala newbie still and I'm sure there's a lot of constructs and
syntactic tricks I'm not aware of.

-janne

>
> On Oct 30, 2007 8:29 AM, Janne Savukoski <janne@...> wrote:
> > Hello,
> >
> > This feels a little stupid, and I'm sure there's something
> > fundamentally n00b in this, but anyways... I've been experimenting
> > with this kind of structure (note the pipe, '|', on 2nd line):
> >
> > <clip>
> > 1: sw.sendMessage {
> > 2:   new Message | { m =>
> > 3:     m.setDisplayName(somename)
> > 4:     m.setContent(format("Hello, %s! %s!", displayName, somecontent))
> > 5:   }
> > 6: }
> > </clip>
> >
> > which is similar to
> >
> > 1: val m = new Message
> > 2: m.setDisplayName(somename)
> > 3: m.setContent(format("Hello, %s! %s!", displayName, somecontent))
> > 4: sw.sendMessage(m)
> >
> > and
> >
> > 1: sw.sendMessage {
> > 2:   val m = new Message
> > 3:   m.setDisplayName(somename)
> > 4:   m.setContent(format("Hello, %s! %s!", displayName, somecontent))
> > 5:   m
> > 6: }
> >
> >
> > The last one was my favorite before the pipe, but it suffers from the
> > explicit return. The second I don't like a bit as it exposes the name
> > 'm' that is relevant only in the context of the 'sendMessage'
> > invocation.
> >
> > In the first case the pipe—which returns the object itself—replaces an
> > ad-hoc-initialization-block-using-anonymous-subclass. More generally,
> > with pipe I can write a block with a 'private' reference to the
> > context object. (or something...)
> >
> > The pipe is defined simply as
> >
> > implicit def pipe4Any[a](any: a) = new AnyRef { def |(f:a => Unit): a
> > = { f(any); any } }
> >
> > Another nice use case was with logging:
> >
> > 1: rs.report(WARNING, root, format("Resource not found: %s",
> > f.getAbsolutePath) | (warn(_)))
> >
> > where the message "Resource n..." is logged ('warn', shortcut to
> > commons logging) while passed on to the report method. (No
> > ad-hoc-initialization-block-using-anonymous-subclass here.)
> >
> > So, this is just such a trivial use case that I'm sure there's some
> > standard way to do this. Please, feel free to show me the light. :)
> >
> >
> > -janne
> >
>
>
>
> --
> Rafael de F. Ferreira.
> http://www.rafaelferreira.net/
>


--
Janne Savukoski
Internet programmer
email/im: janne@...
mobile: +358 (40) 568 4246
blog: http://zimboe.wordpress.com/

Re: Private names

by Robin Message :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message

Okay, I'm only getting started with Scala, but how about:

1: sw.sendMessage { m =>
2:     m.setDisplayName(somename)
3:     m.setContent(format("Hello, %s! %s!", displayName, somecontent))
4: }

With sendMessage defined as:
def sendMessage(setter:Message=>unit) {
        var msg=new Message()
        setter(msg)
        //..do something with msg
}

If you want to send subclasses of message, then the code ought to look
like:

1: sw.sendMessage[SubMessage] { m =>
2:     m.setDisplayName(somename)
3:     m.setContent(format("Hello, %s! %s!", displayName, somecontent))
4: }

With sendMessage defined as:
def sendMessage[T <: Message](setter:T=>unit) {
        var msg=new T()
        setter(msg)
        //..do something with msg
}

Alas, that doesn't compile. Any guru want o suggest how that
could/should be done?

Cheers,

Robin Message

On Wed, 2007-10-31 at 17:29 +0200, Janne Savukoski wrote:

> Hi Rafael!
>
> On 10/30/07, Rafael de F. Ferreira <rafael@...> wrote:
> > Hi Janne.
> >
> > I was under the impression that the
> > ad-hoc-initialization-block-using-anonymous-subclass trick was the
> > "standard way" to do this kind of thing in Scala. In your example, I
> > infer that Message is a Java class, but if it was written in Scala,
> > one idiom for initialization would be to declare abstract vals, like
> > this:
> >
> > abstract class Message {
> >   val displayName:String
> >   val content:String
> > }
> >
> > sw sendMessage (new Message {
> >    val displayName = somename
> >    val content = format("Hello, %s! %s!", displayName, somecontent)
> > })
>
> Thanks for confirming that, I had no idea if it was a popular
> technique with Scala. I myself try to avoid it, as it feels a little
> intrusive and, well, 'blunt'. :) But it certainly is a smooth way.
>
>
> > Anyway, I really liked your second example, using the pipe and the
> > underscore closure shorthand together looks like a cool technique.
>
> Nice :) . Btw., if the method 'warn' wasn't overloaded, the syntax
> could be reduced into just '"foo" | warn'. Although, I'm thinking the
> name '|' may be a little confusing as it doesn't transform the
> source.. (Instead, if we named map+filter to pipe, it would be shell
> scripts all over again. :)
>
> But anyways, it's funny that there hasn't been more suggestions about
> some standard ways for replacing this proprietary hack. I'm just a
> Scala newbie still and I'm sure there's a lot of constructs and
> syntactic tricks I'm not aware of.
>
> -janne


Re: Private names

by Robin Message :: Rate this Message:

Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message

I've found a solution using one factory object per Message subtype.

abstract class MessageFactory[M] {
        def make(): M
}

class Message{
        var name:String=""
        def setName(newname:String) {name=newname}
        def send()=println(name)
}
implicit object MessageMessageFactory extends MessageFactory[Message] {
        def make()=new Message()
}

class SubMessage extends Message {
        var t:String=""
        def setType(newtype:String) {t=newtype}
        override def send()=println(name+" ("+t+")")
}
implicit object SubMessageMessageFactory extends
MessageFactory[SubMessage] {
        def make()=new SubMessage()
}

def sendMessage[T <: Message](setter:T=>unit)(implicit factory:
MessageFactory[T]) {
        var msg:T=factory.make()
        setter(msg)
        msg.send()
}

sendMessage[Message] { m =>
        m.setName("foo")
        m.setName("bar")
}
sendMessage[SubMessage] { m =>
        m.setType("count")
        m.setName("Update")
}

I'd say you couldn't do it with less syntax, it's safe and it's very
readable. However, each message needs a factory method attaching to it
which is a little annoying, but very workable.

What do you think?

Also, a note to Scala writers - would it be possible to compile "new
T()", where T is a type variable, into a factory method like I've done
here?

One other thing: The technique you described below is not very safe,
since if you mistype the name of one of the parameters, the compiler
will give no error, but your code will not work (suppose you wrote "val
displaYYYName = somename", displayName will still equal null)

Robin

> > > I was under the impression that the
> > > ad-hoc-initialization-block-using-anonymous-subclass trick was the
> > > "standard way" to do this kind of thing in Scala. In your example, I
> > > infer that Message is a Java class, but if it was written in Scala,
> > > one idiom for initialization would be to declare abstract vals, like
> > > this:
> > >
> > > abstract class Message {
> > >   val displayName:String
> > >   val content:String
> > > }
> > >
> > > sw sendMessage (new Message {
> > >    val displayName = somename
> > >    val content = format("Hello, %s! %s!", displayName, somecontent)
> > > })
> >
> > Thanks for confirming that, I had no idea if it was a popular
> > technique with Scala. I myself try to avoid it, as it feels a little
> > intrusive and, well, 'blunt'. :) But it certainly is a smooth way.
> >
> >
> > > Anyway, I really liked your second example, using the pipe and the
> > > underscore closure shorthand together looks like a cool technique.
> >
> > Nice :) . Btw., if the method 'warn' wasn't overloaded, the syntax
> > could be reduced into just '"foo" | warn'. Although, I'm thinking the
> > name '|' may be a little confusing as it doesn't transform the
> > source.. (Instead, if we named map+filter to pipe, it would be shell
> > scripts all over again. :)
> >
> > But anyways, it's funny that there hasn't been more suggestions about
> > some standard ways for replacing this proprietary hack. I'm just a
> > Scala newbie still and I'm sure there's a lot of constructs and
> > syntactic tricks I'm not aware of.