Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Ruby (http://www.velocityreviews.com/forums/f66-ruby.html)
-   -   Lexical Casts with Ruby (http://www.velocityreviews.com/forums/t824198-lexical-casts-with-ruby.html)

RĂ¼diger Sonderfeld 09-03-2005 03:13 PM

Lexical Casts with Ruby
 
Hello,
I want to assign some values I recive in string form to attributes of a
user specified class. The problem is that I have to lexical cast the
strings into the required type. I can't use to_i or to_f because the attribute
type can only be determined at runtime.

Is there a way for lexical casts between types in Ruby? Something like
convert("10", Fixnum)
=> 10

Regards,
RĂ¼diger Sonderfeld <kingruedi@c-plusplus.de>

Robert Klemme 09-03-2005 03:25 PM

Re: Lexical Casts with Ruby
 
2005/9/3, R=FCdiger Sonderfeld <kingruedi@c-plusplus.de>:
> Hello,
> I want to assign some values I recive in string form to attributes of a
> user specified class. The problem is that I have to lexical cast the
> strings into the required type. I can't use to_i or to_f because the attr=

ibute
> type can only be determined at runtime.
>=20
> Is there a way for lexical casts between types in Ruby? Something like
> convert("10", Fixnum)
> =3D> 10


Well, there are several options:

You can use send, like your_string.send(:to_i) where you determine the
symbol (:to_i, :to_f etc) at runtime.

You can use case

result =3D case your_string
when /^\d+$/ then your_string.to_i
when /^\d.\.\d+/ then your_string.to_f
else your_string
end

Or you put conversions into a map

conv =3D {
Fixnum =3D> lambda {|x| x.to_i},
Float =3D> lambda {|x| x.to_f},
}

result =3D conv[Fixnum][your_string]

Hope, that gets you started.

Kind regards

robert



David A. Black 09-03-2005 03:35 PM

Re: Lexical Casts with Ruby
 
--8323328-1020658632-1125761734=:19128
Content-Type: MULTIPART/MIXED; BOUNDARY="8323328-1020658632-1125761734=:19128"

This message is in MIME format. The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.

--8323328-1020658632-1125761734=:19128
Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

Hi --

On Sun, 4 Sep 2005, [utf-8] R=C3=BCdiger Sonderfeld wrote:

> Hello,
> I want to assign some values I recive in string form to attributes of a
> user specified class. The problem is that I have to lexical cast the
> strings into the required type. I can't use to_i or to_f because the attr=

ibute
> type can only be determined at runtime.
>
> Is there a way for lexical casts between types in Ruby? Something like
> convert("10", Fixnum)
> =3D> 10


See Robert's answer. Also, another possibility would be to put the
knowledge directly in the object:

class MyClass
def x=3D(s)
@x =3D s.to_i
end

def y=3D(s)
@y =3D s.to_f
end

# ...
end

That way, you can just do:

obj.x =3D "10"

and have the conversion be encapsulated in the object.

If using the assignment syntax seems *too* transparent (since you're
not really setting it to "10"), you could use differently-named
methods. But the principle would be the same: put the knowledge in
the object.


David

--=20
David A. Black
dblack@wobblini.net
--8323328-1020658632-1125761734=:19128--
--8323328-1020658632-1125761734=:19128--



Paul Brannan 09-07-2005 04:37 PM

Re: Lexical Casts with Ruby
 
On Sun, Sep 04, 2005 at 12:16:26AM +0900, R??diger Sonderfeld wrote:
> Hello,
> I want to assign some values I recive in string form to attributes of a
> user specified class. The problem is that I have to lexical cast the
> strings into the required type. I can't use to_i or to_f because the attribute
> type can only be determined at runtime.
>
> Is there a way for lexical casts between types in Ruby? Something like
> convert("10", Fixnum)
> => 10


In C++, boost::lexical_cast uses streams to convert the object to a
string and then from the string to the desired type.

It is easy to do the first part in ruby; all objects have a to_s method.

The second part is harder. There is no uniform mechanism for converting
a string into an object.

Paul





Eric Mahurin 09-07-2005 05:09 PM

Re: Lexical Casts with Ruby
 
--- Paul Brannan <pbrannan@atdesk.com> wrote:

> On Sun, Sep 04, 2005 at 12:16:26AM +0900, R??diger Sonderfeld
> wrote:
> > Hello,
> > I want to assign some values I recive in string form to

> attributes of a
> > user specified class. The problem is that I have to lexical

> cast the
> > strings into the required type. I can't use to_i or to_f

> because the attribute
> > type can only be determined at runtime.
> >=20
> > Is there a way for lexical casts between types in Ruby?

> Something like
> > convert("10", Fixnum)
> > =3D> 10

>=20
> In C++, boost::lexical_cast uses streams to convert the
> object to a
> string and then from the string to the desired type.
>=20
> It is easy to do the first part in ruby; all objects have a
> to_s method.
>=20
> The second part is harder. There is no uniform mechanism for
> converting
> a string into an object.



A while back, I suggested adding some klass.from_* methods.=20
For example:

def Integer.from_s(s)
s.to_i;
end

Any class that could make one of its objects from a String
would put this method in. You could do the same for other
classes to convert from also: from_i, from_f, etc. Here would
be the usage:

Integer.from_s("10") # 10
10.to_s # "10" - nothing new

As a convienence you could also add this:

class String
def to(klass)
klass.from_s(self)
end
def self.from(obj)
obj.to_s
end
end

so you could do:

"10".to(Integer) # 10
String.from(10) # "10"

If this is a good solution for you, maybe an RCR for this more
general conversion mechanism is in order.



=09
=09
__________________________________________________ ____
Click here to donate to the Hurricane Katrina relief effort.
http://store.yahoo.com/redcross-donate3/



Paul Brannan 09-08-2005 05:37 PM

Re: Lexical Casts with Ruby
 
On Thu, Sep 08, 2005 at 02:09:32AM +0900, Eric Mahurin wrote:
> so you could do:
>
> "10".to(Integer) # 10
> String.from(10) # "10"
>
> If this is a good solution for you, maybe an RCR for this more
> general conversion mechanism is in order.


See RCR#280. The implementation is 34 lines long.

Paul





Eric Mahurin 09-08-2005 06:49 PM

Re: Lexical Casts with Ruby
 
--- Paul Brannan <pbrannan@atdesk.com> wrote:

> On Thu, Sep 08, 2005 at 02:09:32AM +0900, Eric Mahurin wrote:
> > so you could do:
> >=20
> > "10".to(Integer) # 10
> > String.from(10) # "10"
> >=20
> > If this is a good solution for you, maybe an RCR for this

> more
> > general conversion mechanism is in order.

>=20
> See RCR#280. The implementation is 34 lines long.


Don't know why I missed that one. I don't really like the
implementation with the global (or rather class variable) hash.
I would rather see an encapsulated API - each class gives
methods for converting to/from objects of other classes of
interest (i.e. String). You may have duplicated code or one
from_* calling another to_* (or vice-versa), but so what. This
way requires 0 lines of overhead - nothing needs to manage
framework. It's simple and is an extension of what we already
have. The klass#to(toKlass) and klass.from(fromObj) are
shortcuts to get a little more abstract if you want:

class String
def self.from(obj); obj.to_s; end
def to(klass); klass.from_s(self); end
end

If you did this, then I guess you could consider this the
overhead for each class that other classes want to convert
to/from - String, Integer, Float, Array, etc.

I would think this more straight-forward approach would be more
likely accepted.



=09
=09
__________________________________________________ ____
Click here to donate to the Hurricane Katrina relief effort.
http://store.yahoo.com/redcross-donate3/



gabriele renzi 09-08-2005 07:53 PM

Re: Lexical Casts with Ruby
 
Eric Mahurin ha scritto:
>>>If this is a good solution for you, maybe an RCR for this

>>
>>more
>>
>>>general conversion mechanism is in order.

>>
>>See RCR#280. The implementation is 34 lines long.

>
>
> Don't know why I missed that one. I don't really like the
> implementation with the global (or rather class variable) hash.
> I would rather see an encapsulated API - each class gives
> methods for converting to/from objects of other classes of
> interest (i.e. String).

<snip>

The reason for the global transformation table is basically being able
to handle any kind of "type" not just Classes. I like to think of ruby
as object based more than Class based.

Anyway, even if your approach is more conservative, I'd appreciate if it
was blessed[1].

I wonder what matz think of this stuff.


[1]
what I'd really like to see is multimethods. Just specialize #new and
everything goes fine ;)

Paul Brannan 09-08-2005 08:58 PM

Re: Lexical Casts with Ruby
 
On Fri, Sep 09, 2005 at 03:49:59AM +0900, Eric Mahurin wrote:
> class String
> def self.from(obj); obj.to_s; end
> def to(klass); klass.from_s(self); end
> end
>
> If you did this, then I guess you could consider this the
> overhead for each class that other classes want to convert
> to/from - String, Integer, Float, Array, etc.
>
> I would think this more straight-forward approach would be more
> likely accepted.


Would you be more amenable to a solution like:

class Object
def to(type, *args, &block)
return send("to_#{type}", *args, &block)
end

def to_String
return to_s
end
end

class String
def to_Integer
return Integer(self)
end

# etc.
end

This eliminates the global constant by using double-dispatch, plus
retains the ability to convert to a non-class type (e.g.
foo.to(Enumerable)).

Paul





Eric Mahurin 09-08-2005 10:05 PM

Re: Lexical Casts with Ruby
 
--- Paul Brannan <pbrannan@atdesk.com> wrote:

> On Fri, Sep 09, 2005 at 03:49:59AM +0900, Eric Mahurin wrote:
> > class String
> > def self.from(obj); obj.to_s; end
> > def to(klass); klass.from_s(self); end
> > end
> >=20
> > If you did this, then I guess you could consider this the
> > overhead for each class that other classes want to convert
> > to/from - String, Integer, Float, Array, etc.
> >=20
> > I would think this more straight-forward approach would be

> more
> > likely accepted.

>=20
> Would you be more amenable to a solution like:
>=20
> class Object
> def to(type, *args, &block)
> return send("to_#{type}", *args, &block)
> end
>=20
> def to_String
> return to_s
> end
> end
>=20
> class String
> def to_Integer
> return Integer(self)
> end
>=20
> # etc.
> end
>=20
> This eliminates the global constant by using double-dispatch,
> plus
> retains the ability to convert to a non-class type (e.g.
> foo.to(Enumerable)).
>=20
> Paul


Let's say you have some aribitrary class that you want to
convert to/from a string. With the above, you'd put the
to-string method in this class and the from-string method in
String. I think better encapsulation would be to put both of
these in this new aribitrary class. To do it this way and
force the method names to have the class name in them, you'd do
this:

class Object
def self.from(obj,*args,&block)
send("from_#{self}".to_sym,obj,*args,&block)
rescue
obj.send("to_#{self}".to_sym,*args,&block)
end
def to(klass,*args,&block)
send("to_#{klass}".to_sym,*args,&block)
rescue
klass.send("from_#{self.class}".to_sym,self,*args, &block)
end
def to_String
to_s
end
def to_Integer
to_i
end
end


class Xyz
def self.from_String(s,base=3D10)
... make a Xyz from s ...
end
def to_String(base=3D10)
... make a String from self ...
end
end


Of course in the above, "klass" doesn't have to be a Class, but
it does need to respond to the right from_* method.

I'm not sure of the value of using from_String/to_String over
from_s/to_s. I think you'll have just a few classes that
you'll have many classes converting from/to them. You'll
never be able to convert from one arbitrary class to another.=20
Also, the above code is kind of ugly forming method names and
trying two different methods (not very duck-type like) - but I
could get over it.

Would this work with the non-class types you are talking about?




=09
=09
__________________________________________________ ____
Click here to donate to the Hurricane Katrina relief effort.
http://store.yahoo.com/redcross-donate3/




All times are GMT. The time now is 08:28 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.