[RCR] Unified type conversion framework

G

gabriele renzi

Hi gurus and nubys,

You can find the full text at
http://rcrchive.net/rcr/RCR/RCR280
(sorry if there are typos/errors, I'm having some problems with the
submit phase).

The proposed system unifies the various way to convert or to extract an
object from another, like to_f, to_set, Integer() or to_enum.
It also allows declarative checking of the type of an object and reduces
duplication of code. Yes, I mean type, not class ;).

But it's not something really new and does not break compatibility at
all, it is mostly a refactoring and generalization of already used
practices.

Anyway I think you could understand better reading the rationale and
sample implementation on the rcr page. If you're going to vote against
this please take some time to comment on why you did it, it would be
much more useful.

Finally I'd like to thank Paul Brannan for helping me in refining this
and David Black for the great help in the rcr publishing process :)
 
G

gabriele renzi

Sam McCall ha scritto:
Cool! Occasionally I think about doing something like this, so I can
have some nice way to remember the custom conversions I use.

I think most of us did, this is why I'm telling this is not something new :)
Maybe you could sneak some extra conversions in with it, like
[[1,2],[3,4]].as Hash # => {1=>2,3=>4}

The system is open, I did thought of this when thinking how unintuitive
Hash[anArray] is . This is another example of the need for a better
approach, I guess there are much more ;)
Related to this is type-checking when you do want it (duck typing is
good, but I'd give it up in some cases to have an easy, readable way of
checking that I'm not passing a hash instead of an array).
I'd really like to be able to do:
def method(foo,bar)
foo.is! Hash
bar.can_be! Array
#...
end
where they do something like
def is! t
raise TypeError.new("Expected a #{t} but got a " +
"#{self.type}: #{self.inspect}") unless is_a? t
end

def can_be! t
raise TypeError.new("Can't convert to #{t} from "+
"#{self.type}: #{self.inspect}") unless can_be? t
end

And can_be? is the does-this-conversion-exist method.

#is! is broken, because it relies on is_a? that is not powerful enough
to really express a type, but #as (or #to.. I mean, the proposed system)
is powerful enough to expres any kind of type, including your #is! :)

The same is said for can_be? Sure, I could introduce a method in the
ConvTable that checks if a conversion path exists, but it won't work
for, say,
'ciao'.as Integer
because even if a String -> Integer conversion path do exist, you still
have to check the whole string. So you end up needing #as again.

This might even be rdoc-able, if it was at the top of a method. It'd
certainly make the ad-hoc documentation I write today executable.

exacylt what I was thinking of. The IdeaSpace is limited, it seem ;)
 
P

Paul Brannan

The system is open, I did thought of this when thinking how unintuitive
Hash[anArray] is . This is another example of the need for a better
approach, I guess there are much more ;)

I think you mean Hash[*anArray]. IMO, It's not totally unintuitive, but
it's not consistent with other conversions.

Paul
 
F

Florian Gross

Paul said:
I think you mean Hash[*anArray]. IMO, It's not totally unintuitive, but
it's not consistent with other conversions.

Actually converting an assoc array to a Hash is done via
Hash[*array.flatten]. I think that that is pretty low level. I'd prefer
something like Hash.from_assoc()

Regards,
Florian Gross
 
G

Gavin Sinclair

Florian said:
Paul said:
I think you mean Hash[*anArray]. IMO, It's not totally unintuitive,
but it's not consistent with other conversions.


Actually converting an assoc array to a Hash is done via
Hash[*array.flatten]. I think that that is pretty low level. I'd
prefer something like Hash.from_assoc()

At work we have Array#to_h in a library, it's really useful for things
like:

db.select_all(...).map {|foo,bar| [foo,bar]}.to_h

Sam

This is my approach (very similar) and I love it:

require 'extensions/all'
db.select_all(...).build_hash { |foo, bar| [foo,bar] }

Gavin
 
M

Markus

Florian said:
Paul Brannan wrote:

I think you mean Hash[*anArray]. IMO, It's not totally unintuitive,
but it's not consistent with other conversions.


Actually converting an assoc array to a Hash is done via
Hash[*array.flatten]. I think that that is pretty low level. I'd
prefer something like Hash.from_assoc()

At work we have Array#to_h in a library, it's really useful for things
like:

db.select_all(...).map {|foo,bar| [foo,bar]}.to_h

Sam

This is my approach (very similar) and I love it:

require 'extensions/all'
db.select_all(...).build_hash { |foo, bar| [foo,bar] }

Gavin

Well, as long as we're playing "show me yours and I'll show you mine," I
use (again, very similar):


module Enumerable
def collect_hash
result = {}
each { |x| result[x] = yield(x) }
result
end
end

and thus would write (for the initial):

db.select_all(...).collect_hash { |foo, bar| bar }


-- Markus
 
G

Gavin Sinclair

Well, as long as we're playing "show me yours and I'll show you mine," I
use (again, very similar):

I like that game :)
module Enumerable
def collect_hash
result = {}
each { |x| result[x] = yield(x) }
result
end
end

and thus would write (for the initial):

db.select_all(...).collect_hash { |foo, bar| bar }

-- Markus

You don't see a need for transforming the keys?

db.select_all(...).build_hash { |foo, bar| [foo.to_i, bar.to_s] }

Gavin
 
M

Martin DeMello

Gavin Sinclair said:
require 'extensions/all'
db.select_all(...).build_hash { |foo, bar| [foo,bar] }

This would be nice too:

build_hash {|key, val| {key => val}}

martin
 
G

gabriele renzi

Gavin Sinclair ha scritto:
I like that game :)

Let me play a little too:

def build_hash (ary)
result = {}
ary.each do |elt|
key, value = yield elt # maybe default behaviour is needed
result[key] = value
end
result
end


ConvRegistry[Array,Hash]= method :build_hash

[[1,2],[3,4]].as(Hash) {|k,v| [k,v] } #{1=>2, 3=>4}
[1,2,3,4].as(Hash) {|k| [k,true] } #{1=>true, 2=>true, 3=>true, 4=>true}
 
M

Markus

You don't see a need for transforming the keys?

I call that "Enumerable#collect_hash_with_key"; in my extensions I tried
as much as possible to stay consistent with the built-ins, if for no
other reason than brain-tax.evasion.

-- MarkusQ
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top