Duck Typing and automated Conversions

Hi all,

conversion of method parameters seems to be a quite common scenario,
example:

def silly_example(str, count)
  str = str.to_str
  count = count.to_int

  s = ""
  count.times { s << str }
  s
end

Usually these conversions are documented as requirements for method
parameters. We could make them a bit more explicit without changing much
especially not the power of Duck Typing. Here's an idea:

def silly_example(str.to_str, count.to_int)
  # str and count are converted like in the example above
  s = ""
  count.times { s << str }
  s
end

Basically this is just a way to save typing. Error reporting will be the
same. RDoc could evaluate this info and generate comments for this
automagically.

Of course, any method could be invoked like this, maybe even with
parameters. I haven't thouroughly thought about implications of that fact
yet.

Thoughs?

    robert

Robert Klemme schrieb:

def silly_example(str.to_str, count.to_int)
  # str and count are converted like in the example above
  s = ""
  count.times { s << str }
  s
end

Basically this is just a way to save typing. Error reporting will be the
same. RDoc could evaluate this info and generate comments for this
automagically.

Of course, any method could be invoked like this, maybe even with
parameters. I haven't thouroughly thought about implications of that fact
yet.

Thoughs?

Interesting idea. I think it's very readable.

Regards,
Pit

Hi --

Hi all,

conversion of method parameters seems to be a quite common scenario,
example:

def silly_example(str, count)
str = str.to_str
count = count.to_int

s = ""
count.times { s << str }
s
end

Usually these conversions are documented as requirements for method
parameters. We could make them a bit more explicit without changing much
especially not the power of Duck Typing. Here's an idea:

def silly_example(str.to_str, count.to_int)
# str and count are converted like in the example above
s = ""
count.times { s << str }
s
end

Basically this is just a way to save typing. Error reporting will be the
same. RDoc could evaluate this info and generate comments for this
automagically.

Of course, any method could be invoked like this, maybe even with
parameters. I haven't thouroughly thought about implications of that fact
yet.

Thoughs?

I personally don't like the '.' notation used for anything other than
method calls (and floats :slight_smile: I just think it's too important and
central a notation to be borrowed for something else, even something
that is somewhat kindred to a method call (but isn't one).

There's also the question of the interaction of this with duck typing.
Of course that's always a programmer's choice, but I could imagine
cases where the caller would expect a duck-typing treatment and not
get it. For example:

   obj = Object.new
   def obj.times; 10; end
   str = silly_example("hello", obj)

Here you have an object that responds to 'times', so it's capable of
being treated in a duck-typing way by simply being sent the message
'times' -- but if you intercept the object and do a to_int on it,
there's trouble.

(Of course you could document your method by saying that it requires
an object that responds to to_int, but that seems a bit roundabout
compared to just saying you want an object that responds to times.)

David

···

On Fri, 14 Jan 2005, Robert Klemme wrote:

--
David A. Black
dblack@wobblini.net

Hi,

···

On 14.1.2005, at 12:16, Robert Klemme wrote:

def silly_example(str.to_str, count.to_int)
  # str and count are converted like in the example above
  s = ""
  count.times { s << str }
  s
end

Not to argue against possible syntatic sugar, but you can already do this in the method signature:

def silly_example(ostr, ocount, str=ostr.to_str, count=ocount.to_int)

Robert Klemme ha scritto:

Basically this is just a way to save typing. Error reporting will be the
same. RDoc could evaluate this info and generate comments for this
automagically.

Of course, any method could be invoked like this, maybe even with
parameters. I haven't thouroughly thought about implications of that fact
yet.

Thoughs?

Yes, one. See RCR 280, add this, and you get quite far in replicating what mr van rossum is advocating as optional typing for python :slight_smile: [1]
With pre/post method hook as supposed to be in Ruby2, you get even further.

[1]only the last post, the "stop flames" one would recall this, ignore the other two.

I like this, and believe it can be generalized to be quite broadly useful.

I believe your signature tells a caller the following:
    silly_example takes 2 params, x and y
        (str and count, if you prefer; but see * below)
        x must support #to_str, y must support #to_int
    silly_example will use them as follows:
        str = x.to_str
        count = y.to_int
    silly_example will not have other access to x, y
    (*: since you did: str=str.to_str; count=count.to_int)

There are 3 main properties about this signature:
1. it reveals the duck-type of x, y as required methods
2. it reveals how those methods of x, y are used in the body
    str = x.to_str
    count = y.to_int
3. it saves typing: in particular, it has "no extra cost", since it
automatically binds str and count and this does not have to be repeated
within the body of f().

What do you think about the following generalization of your idea? It will
be a bit of a jump, so *please* consider it carefully:

    Allow a method signature to optionally indicate both
    the duck type of a parameter (what methods it should
    respond_to), as well as named variable bindings that
    indicate the usage of those respond_to methods within
    the method body.

In your:
    def silly_example (str.to_s, count.to_int)
"to_s" and "to_int" indicate duck-types, and str and count are the named
variables being bound for the method body.

Without suggesting the actual syntax, suppose /*type_pattern_with_vars*/
generalized this.
i.e. /*...*/ is some syntax for a pattern that binds some named variables
(like /.../ for regex) and that has optional type information (like c++
comments, hence optional :slight_smile:

Then, in the hypothetical example below:
def heat (x /*type_pattern_with_vars*/ )
if the /*...*/ somehow
    - referred to methods #min, #max, #cool, #explode
    - binds variables lo, hi, onHot, tooHot
Then type_pattern_with_vars *could* convey, via not-yet-determined syntax,
the following information:
- arg x must support #min, #max (#cool,#explode see below)
- x.min is used as the *lo* var in #heat
- x.max is used as the *hi* var in #heat
- x.cool is callable VIA the *onHot* var in #heat
- x.explode is callable VIA the *tooHot* var in #heat
[optionally: x itself is not otherwise directly accessible in #heat]

The signature is very informative, and it has all 3 properties of your
proposal:
1. it reveals the duck-type of x: #min,#max,#cool,#explode
2. it reveals how duck-type methods of x are used in the method
    lo = x.min;
    hi = x.max;
    onHot = x.method(:cool)
    tooHot = x.method(:explode)
3. it saves typing: in particular, it has "no extra cost", since it binds
the above variables automatically, and this does not have to be repeated
within the body of #heat. If RDoc understood this, you'd have to write that
much less narrative explanation for your methods.

It is all still based on duck-ish respond_to? semantics rather than on
classes. It would *not* duplicate any work since the implementer of #heat
would *not* have to do any of the following:
    lo = x.min
    hi = x.max
    onHot = x.method(:cool)
    tooHot = x.method(:explode)
in #heat's body, as these variable bindings would be done by Ruby itself
just before the body of #heat. In fact, if the variable 'x' was somehow
ommitted, then these other variables would be the *only* handles on the
argument available within #heat i.e. a caller would know for sure that
x.cool could *only* be called via *onHot*. All I could do within the body of
#heat would be things like:
def heat (x /*...*/ ) # lo, hi, onHot, tooHot now bound
    temp = ... some stuff
    if (temp > lo && temp < hi) onHot.call()
    if (temp > hi) tooHot.call()

Any ideas about how to do /*...*/, any other comments or suggestions,
welcome!

p.s. This approach combines ideas of pattern matching with ideas of duck
typing.

···

"Robert Klemme" <bob.news@gmx.net> wrote

Usually these conversions are documented as requirements for method
parameters. We could make them a bit more explicit without changing much
especially not the power of Duck Typing. Here's an idea:

def silly_example(str.to_str, count.to_int)
  # str and count are converted like in the example above
  s = ""
  count.times { s << str }
  s
end

I could count on one hand the number of times I've converted arguments
at the top of the method. In those times, I consider it a bit of a
breakdown of duck-typing, not an extension of it.

Also, I agree with David about use of dot notation for this. This is,
in fact the reverse behavior from the usual dot notation; instead of
the expression returning the result of sending the message to the
object referenced by the variable, it references the variable to the
result of sending the message to the object.

However, I'm sure there are other alternate syntaxes that will work.
And, if you instead simply check that the passed object responds to
the selected message, that would be, imvho, an extension of
duck-typing....

  def foo( str{to_str}, count{times} )
    s = ""
    count.times { s << str }
    s
  end

If foo is called with a str that doesn't respond_to?(to_str), there
should be an error raised. Perhaps a NoMethodError, or maybe a
TypeError, or maybe something new that means both.

I'm fond of doing things like this, especially for testing, and
sometimes for working with stuff in irb:

  num, str = Object.new, Object.new

  def num.times(&block) 23.times &block end
  def str.to_str() "%02i_" % rand(99) end

  foo num, str #==> "74_26_94_..."

I do this to make sure I'm allowing for maximum flexibility, or when
working with other's code, to find out what the actual requirements
are :slight_smile:

There are a couple of problems still: First, an object might still be
able to respond to a message, using method_missing, but #respond_to?
won't show it. Second, I'm not sure about the syntax. It would work
(it currently give a parse error), but I think something better and
more self-explanatory could be found.

cheers,
Mark

···

On Fri, 14 Jan 2005 19:16:12 +0900, Robert Klemme <bob.news@gmx.net> wrote:

def silly_example(str.to_str, count.to_int)
  # str and count are converted like in the example above
  s = ""
  count.times { s << str }
  s
end

Basically this is just a way to save typing. Error reporting will be the
same. RDoc could evaluate this info and generate comments for this
automagically.

"David A. Black" <dblack@wobblini.net> schrieb im Newsbeitrag
news:Pine.LNX.4.61.0501140338360.14852@wobblini...

Hi --

>
> Hi all,
>
> conversion of method parameters seems to be a quite common scenario,
> example:
>
> def silly_example(str, count)
> str = str.to_str
> count = count.to_int
>
> s = ""
> count.times { s << str }
> s
> end
>
> Usually these conversions are documented as requirements for method
> parameters. We could make them a bit more explicit without changing

much

> especially not the power of Duck Typing. Here's an idea:
>
> def silly_example(str.to_str, count.to_int)
> # str and count are converted like in the example above
> s = ""
> count.times { s << str }
> s
> end
>
> Basically this is just a way to save typing. Error reporting will be

the

> same. RDoc could evaluate this info and generate comments for this
> automagically.
>
> Of course, any method could be invoked like this, maybe even with
> parameters. I haven't thouroughly thought about implications of that

fact

> yet.
>
> Thoughs?

I personally don't like the '.' notation used for anything other than
method calls (and floats :slight_smile: I just think it's too important and
central a notation to be borrowed for something else, even something
that is somewhat kindred to a method call (but isn't one).

In fact the first character that came to mind was '#'. The char to use
here is not important to me. Here are some alternatives:

def silly_example(str.to_str, count.to_int)
def silly_example(str#to_str, count#to_int)
def silly_example(str:to_str, count:to_int)
def silly_example(str::to_str, count::to_int)

There's also the question of the interaction of this with duck typing.
Of course that's always a programmer's choice, but I could imagine
cases where the caller would expect a duck-typing treatment and not
get it. For example:

   obj = Object.new
   def obj.times; 10; end
   str = silly_example("hello", obj)

Here you have an object that responds to 'times', so it's capable of
being treated in a duck-typing way by simply being sent the message
'times' -- but if you intercept the object and do a to_int on it,
there's trouble.

Well, of course. But in those cases you would not use that notation. You
would simply declare the parameter as you do now and write a comment that
this parameter must respond to #times.

Btw, did you purposely just return an int from your definition of times?
I mean, no block is invoked from that method.

(Of course you could document your method by saying that it requires
an object that responds to to_int, but that seems a bit roundabout
compared to just saying you want an object that responds to times.)

It's just another (supposedly shorter) form to write a common idiom. If
the writer of silly_example decides to do more complex treatment, he can
still do that. We don't loose anything. Note, that the creator of your
obj.times() would be similarly surprised if the implementor of
silly_example had choosen to do it exactly like I presented in the first
example.

I'm not sure whether I missed your point altogether. Could you please
elaborate? Thanks!

Kind regards

    robert

···

On Fri, 14 Jan 2005, Robert Klemme wrote:

"Ilmari Heikkinen" <kig@misfiring.net> schrieb im Newsbeitrag
news:39518454-662A-11D9-AB45-000A95CD3934@misfiring.net...

Hi,

> def silly_example(str.to_str, count.to_int)
> # str and count are converted like in the example above
> s = ""
> count.times { s << str }
> s
> end

Not to argue against possible syntatic sugar, but you can already do
this in the method signature:

def silly_example(ostr, ocount, str=ostr.to_str, count=ocount.to_int)

Yeah, I know, but that's quite inconvenient IMHO. Also you need to
duplicate the number of your parameters plus it won't work with varying
lenght argument lists.

Regards

    robert

···

On 14.1.2005, at 12:16, Robert Klemme wrote:

Hi --

···

On Fri, 14 Jan 2005, Ilmari Heikkinen wrote:

Hi,

On 14.1.2005, at 12:16, Robert Klemme wrote:

def silly_example(str.to_str, count.to_int)
  # str and count are converted like in the example above
  s = ""
  count.times { s << str }
  s
end

Not to argue against possible syntatic sugar, but you can already do this in the method signature:

def silly_example(ostr, ocount, str=ostr.to_str, count=ocount.to_int)

Yes except that then someone could call it like this:

   silly_example("hi", 1, "hello", 2)

and clobber the conversions you were doing.

David

--
David A. Black
dblack@wobblini.net

"gabriele renzi" <rff_rff@remove-yahoo.it> schrieb im Newsbeitrag
news:L1QFd.3723$fs6.84797@twister2.libero.it...

Robert Klemme ha scritto:

> Basically this is just a way to save typing. Error reporting will be

the

> same. RDoc could evaluate this info and generate comments for this
> automagically.
>
> Of course, any method could be invoked like this, maybe even with
> parameters. I haven't thouroughly thought about implications of that

fact

> yet.
>
> Thoughs?
>

Yes, one. See RCR 280, add this, and you get quite far in replicating
what mr van rossum is advocating as optional typing for python :slight_smile: [1]
With pre/post method hook as supposed to be in Ruby2, you get even

further.

[1]only the last post, the "stop flames" one would recall this, ignore
the other two.

Interesting. Thanks for pointing that out!

Although the two suggestions are clearly related and can be combined,
they're completely orthogonal IMHO. You can always have one without the
other. Personally I'm not sure whether I like the idea of a type
conversion framework like that of RCR 280 mainly because I'm wary about
having this functionality not in classes affected. You'll end up in a
situation where you can't rely on this because you neve know which
conversions are active. I't seems bad for lib designers. But that's
another discussion...

Kind regards

    robert

I think this is the problem with your suggestion. You want to put a lot of
info into this little /*...*/. Have you considered what it might be like?

T.

···

On Friday 14 January 2005 10:31 am, itsme213 wrote:

Any ideas about how to do /*...*/, any other comments or suggestions,
welcome!

"itsme213" <itsme213@hotmail.com> schrieb im Newsbeitrag
news:YyRFd.6210$_56.802@fe2.texas.rr.com...

> Usually these conversions are documented as requirements for method
> parameters. We could make them a bit more explicit without changing

much

> especially not the power of Duck Typing. Here's an idea:
>
> def silly_example(str.to_str, count.to_int)
> # str and count are converted like in the example above
> s = ""
> count.times { s << str }
> s
> end

I like this, and believe it can be generalized to be quite broadly

useful.

I believe your signature tells a caller the following:
    silly_example takes 2 params, x and y
        (str and count, if you prefer; but see * below)
        x must support #to_str, y must support #to_int

Correct.

    silly_example will use them as follows:
        str = x.to_str
        count = y.to_int

Correct.

    silly_example will not have other access to x, y
    (*: since you did: str=str.to_str; count=count.to_int)

Wrong, because to_str need not create a new instance:

s = "foo"

=> "foo"

s.id

=> 135026792

s.to_str.id

=> 135026792

There are 3 main properties about this signature:
1. it reveals the duck-type of x, y as required methods

Yep.

2. it reveals how those methods of x, y are used in the body
    str = x.to_str
    count = y.to_int

Yep.

3. it saves typing: in particular, it has "no extra cost", since it
automatically binds str and count and this does not have to be repeated
within the body of f().

Exactly.

What do you think about the following generalization of your idea? It

will

be a bit of a jump, so *please* consider it carefully:

    Allow a method signature to optionally indicate both
    the duck type of a parameter (what methods it should
    respond_to), as well as named variable bindings that
    indicate the usage of those respond_to methods within
    the method body.

I'll have to sleep over this. You'll get an answer later.

Kind regards

    robert

···

"Robert Klemme" <bob.news@gmx.net> wrote

"Mark Hubbart" <discordantus@gmail.com> schrieb im Newsbeitrag news:de63abca0501141100154206a8@mail.gmail.com...

def silly_example(str.to_str, count.to_int)
  # str and count are converted like in the example above
  s = ""
  count.times { s << str }
  s
end

Basically this is just a way to save typing. Error reporting will be the
same. RDoc could evaluate this info and generate comments for this
automagically.

I could count on one hand the number of times I've converted arguments
at the top of the method. In those times, I consider it a bit of a
breakdown of duck-typing, not an extension of it.

Also, I agree with David about use of dot notation for this. This is,
in fact the reverse behavior from the usual dot notation; instead of
the expression returning the result of sending the message to the
object referenced by the variable, it references the variable to the
result of sending the message to the object.

However, I'm sure there are other alternate syntaxes that will work.
And, if you instead simply check that the passed object responds to
the selected message, that would be, imvho, an extension of
duck-typing....

def foo( str{to_str}, count{times} )
   s = ""
   count.times { s << str }
   s
end

The syntax is not the problem. In fact I provided some alternatives and I like your version, too.

If foo is called with a str that doesn't respond_to?(to_str), there
should be an error raised. Perhaps a NoMethodError, or maybe a
TypeError, or maybe something new that means both.

NoMethod error - same as in my first example (the way one would do it today).

I'm fond of doing things like this, especially for testing, and
sometimes for working with stuff in irb:

num, str = Object.new, Object.new

def num.times(&block) 23.times &block end
def str.to_str() "%02i_" % rand(99) end

foo num, str #==> "74_26_94_..."

I do this to make sure I'm allowing for maximum flexibility, or when
working with other's code, to find out what the actual requirements
are :slight_smile:

Well, then you'll learn that your instance must implement to_int. Same as if someone had coded that directly in the method. I don't see this as an argument against my suggested shortcut syntax, because that mainly affects the *writer* of a method - not the *caller*.

There are a couple of problems still: First, an object might still be
able to respond to a message, using method_missing, but #respond_to?
won't show it.

You introduced the #respond_to? - my suggestion was to simply invoke it and see what happens (duck typing).

Second, I'm not sure about the syntax. It would work
(it currently give a parse error), but I think something better and
more self-explanatory could be found.

Sure. I'm very open here. I think the selection of "." as separator was not good. We can change that any time. But the real issue for me is, does this make sense independend of syntax?

Kind regards

    robert

···

On Fri, 14 Jan 2005 19:16:12 +0900, Robert Klemme <bob.news@gmx.net> > wrote:

I don't see why there would be a need to add documentation indicating
that count must respond to times, since it's already written right there
in the code. We just need a type inference engine to find this and tell
us about it.

cjs

···

On Fri, 14 Jan 2005, David A. Black wrote:

def silly_example(str.to_str, count.to_int)
# str and count are converted like in the example above
s = ""
count.times { s << str }
s
end

obj = Object.new
def obj.times; 10; end
str = silly_example("hello", obj)

Here you have an object that responds to 'times', so it's capable of
being treated in a duck-typing way by simply being sent the message
'times' -- but if you intercept the object and do a to_int on it,
there's trouble.

(Of course you could document your method by saying that it requires
an object that responds to to_int, but that seems a bit roundabout
compared to just saying you want an object that responds to times.)

--
Curt Sampson <cjs@cynic.net> +81 90 7737 2974 http://www.NetBSD.org
      Make up enjoying your city life...produced by BIC CAMERA

Hi --

[I wrote:]

There's also the question of the interaction of this with duck typing.
Of course that's always a programmer's choice, but I could imagine
cases where the caller would expect a duck-typing treatment and not
get it. For example:

   obj = Object.new
   def obj.times; 10; end
   str = silly_example("hello", obj)

[...]

Btw, did you purposely just return an int from your definition of times?
I mean, no block is invoked from that method.

I did it wrong. It should be:

   def obj.times(&block)
     10.times &block
   end

(Of course you could document your method by saying that it requires
an object that responds to to_int, but that seems a bit roundabout
compared to just saying you want an object that responds to times.)

It's just another (supposedly shorter) form to write a common idiom. If
the writer of silly_example decides to do more complex treatment, he can
still do that. We don't loose anything. Note, that the creator of your
obj.times() would be similarly surprised if the implementor of
silly_example had choosen to do it exactly like I presented in the first
example.

I'm not sure whether I missed your point altogether. Could you please
elaborate? Thanks!

Partly I'm just very conservative about special-case syntax and
shortcuts. I can't define exactly why, or exactly where I draw the
line, or whether there's even a line.... I think I'm also not
convinced that this (to_int etc.) is common enough or special enough
to warrant a change in method definitions semantics. I don't think I
can get much more concrete than that, so it may be that at some level
I don't have a point, rather than that you've missed it :slight_smile:

David

···

On Fri, 14 Jan 2005, Robert Klemme wrote:

--
David A. Black
dblack@wobblini.net

Hi,

···

On 14.1.2005, at 15:31, David A. Black wrote:

def silly_example(ostr, ocount, str=ostr.to_str, count=ocount.to_int)

Yes except that then someone could call it like this:

  silly_example("hi", 1, "hello", 2)

and clobber the conversions you were doing.

Could argue that it's wanted behavior.. "if you want to hack this without hacking to_str and to_int, replace the defaulted args"

Since this IMHO is pretty much an auto-documented wish for the caller to supply objects that act like ducks.

Robert Klemme ha scritto:

Although the two suggestions are clearly related and can be combined,
they're completely orthogonal IMHO. You can always have one without the
other. Personally I'm not sure whether I like the idea of a type
conversion framework like that of RCR 280 [..]

Yes, I did not intend to say they implicate each other in some way, It just came to my mind when I saw "any method could be invoked like this, maybe even with parameters[..]".

Misunderstanding. What I meant was, because your semantics are:
    def f (str.to_str, count.to_int)
        ...body
is behaviorally the same as
    def f (str, count)
        str = str.to_str
        count = count.to_int
        ...body
you no longer have access to the original caller's values of str, count
within the body of f (which is why I presented it with x, y) .

Hth.

···

"Robert Klemme" <bob.news@gmx.net> wrote

> silly_example will not have other access to x, y
> (*: since you did: str=str.to_str; count=count.to_int)

Wrong, because to_str need not create a new instance:

I think it is better to consider the proposed functionality separately from
its concrete syntax. e.g. consider the signature information and how it
affects RDoc documentation; or information available via run-time reflective
access to do dynamic interceptors and adaptors; or performance; or whether
it contradicts Duck Typing or The Ruby Way.

That said, you are right that we need some idea of at least a strawman
concrete syntax to discuss examples; and you are also right that not all
cases should be crammed inline. I believe there are many options here. For
example, the starting point could be to draw a parallel between:
    - parameter binding for method call:
        def f(x,y)
        f(2,3) # bind x,y = 2,3 and execute f
    - variable binding for assignment,
        x,y = 2,3 # bind x,y = 2,3
    - built-in patterns (eg.*splat) and binding
        x, *y = 2, 3, 4 # bind x=2, y = [3, 4]
        x, y = *[2, 3] # bind x=2, y=3
        def f (x, *y) ...
    - match + bindings for regex =~:
        regex =~ obj # bind $1,$2...to matching bits of obj

So, with a disclaimer of /*duck_types_with_vars*/ is NOT concrete syntax:
- the primitive syntactic element of /*..*/ could be adapted from
   - var = expr, or regex =~ expr (or something else)
   - where expr impicitly has self = the caller parameter
- special cases ok e.g. Robert's str.to_s, *splat, **keys, &block
- simple cases of /*...*/ could appear inline in param list
- more complex cases could appear between def(...) and body
- type expressions without vars can be named, combined
- even type_with_var expressions can be named, combined
    t1 = /*expr-1*/
    t2 = /*expr-2*/
    t3 = t1 && t2
    t4 = t1 || t2
    t5 = all ducks with #m1(t1)
- such signatures could be used as 'interface' facility e.g. t5
    - with option to indicate *how* params may be used!
- even separate from def...though losing some functionality
    x.method(:foo).signature = /*...expr */

The win really would be that signatures would be more revealing and done in
a Ruby-standard way. Remember that the programmer always has the option of
deciding what he wants to include in signature info vs. exclude. As it is,
he can already exclude all signature info by simply writing every method as:
    def f *args

Florian Gross' Binding.of_caller could probably be used to prototype ideas
like this, but it would take someone considerably smarter than me (Florian?)
to explore this :slight_smile:

···

"trans. (T. Onoma)" <transami@runbox.com> wrote

On Friday 14 January 2005 10:31 am, itsme213 wrote:
> Any ideas about how to do /*...*/, any other comments or suggestions,
> welcome!

I think this is the problem with your suggestion. You want to put a lot of
info into this little /*...*/. Have you considered what it might be like?