From: "Ara.T.Howard" Date: 2005-06-02T05:30:28+09:00 Subject: Re: binding, ObjectSpace._id2ref [WAS] Re: [ANN] parseargs-0.0.0 On Wed, 1 Jun 2005, Zev Blut wrote: > Hello, > > This looks like a nice tool! Looking at your samples made me think about a > few interesting details about Ruby. To start the discussion, below is your > posted (a.rb) sample: > > On Wed, 01 Jun 2005 00:20:25 +0900, Ara.T.Howard > wrote: > >> def method(*a) >> pa = >> parseargs(a) { >> required_argument :a >> optional_argument :b => 2 >> } >> >> puts "#{ pa.a }#{ pa.b }" >> end >> >> method 4 >> >> ~ > ruby sample/a.rb >> >> 42 > > This looks like a fairly reasonable API, but one thing really struck me was > that your variables needed to be referenced with the pa instance. This is > understandable, but I kind of feel that if I were to use this API a lot I > would really rather have parseargs just go ahead and set the variables in > the current method's binding. Thus I can just reference a and b without the > need to use pa. > > I was going to post a patch to your code, but decided it might be better to > flesh out this idea. Below is some sample code that will display how I > implemented a simple example of how you could remove the need to reference > pa. > > ------ > def parse_data_hash(data, bd = binding) > data.each do |k,v| > vid = v.object_id > eval("#{k.to_s} = ObjectSpace._id2ref(#{vid})", bd) > end > end > > def parse_test(data_hash) > parse_data_hash(data_hash) > puts local_variables.join(",") > > puts "Explicit binding passed" > parse_data_hash(data_hash, binding) > puts local_variables > local_variables.each do |k| > print "#{k} => " > eval("print #{k}.inspect") > puts > end > end > > parse_test({:a => [1,2,3], :b => "hello"}) > ------ the problem here is that the variables will only be __available__ through eval either. eg. you'd have to p 'eval a' and could never p a i seem to recall a way of working around this but can't remember the thread... if i can figure it out i'll add this feature. currently parsearges supports an undoccumented feature, if you parseargs(argv => receiver) { arg 'a' kw 'b' } then receiver will be used to 'receive' the arguments. this works by begin receiver.send '[]=', name, value rescue NoMethodError begin receiver.send "#{ name }=", value rescue NoMethodError receiver.send "#{ name }", value end end eg. any object that responds_to? []=, #{name}=, or #{name} can be used. examples would be parseargs(argv => a_hash) { arg 'a' kw 'b' } or parseargs(argv => a_open_struct) { arg 'a' kw 'b' } and those objects will be parsed 'into'. this means that, if a way can be found to 'set the variable a, given the string "a", in the current scope' i could have the following work fine parseargs(argv => binding) { arg 'a' kw 'b' } p a p b to accomplish what you want. so. how can one do this?? eval 'a = 42' p a i don't know how... -a -- =============================================================================== | email :: ara [dot] t [dot] howard [at] noaa [dot] gov | phone :: 303.497.6469 | My religion is very simple. My religion is kindness. | --Tenzin Gyatso ===============================================================================