[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Named sprintf parameters

Trans

2/28/2008 4:57:00 PM

I have a question and perhaps a bit of challenge for those with mad
parse skills: Has anyone ever considered named parameters for sprintf/
printf? It would be quite useful (to me at least) to be able to do:

"I am %(name)s." % { :name => "Tom" ]

Has anyone worked on something like this before? Is there anything
equivalent in the Perl world or other language? I realize we can use
numerals to identify the substitutions, but I feel the labels are much
more readable. Moreover, ultimately it would be interesting to see:

"I am %(name)s." % binding

Making use of the binding's local_variables.

The challenge, of course, is to override printf/sprintf to do this
(the binding part gets you extra ruby points ;-) Even more
challenging, augment the C code to handle it and submit it as a patch.

T.

14 Answers

ara.t.howard

2/28/2008 5:30:00 PM

0


On Feb 28, 2008, at 9:57 AM, Trans wrote:

> I have a question and perhaps a bit of challenge for those with mad
> parse skills: Has anyone ever considered named parameters for sprintf/
> printf? It would be quite useful (to me at least) to be able to do:
>
> "I am %(name)s." % { :name => "Tom" ]
>
> Has anyone worked on something like this before? Is there anything
> equivalent in the Perl world or other language? I realize we can use
> numerals to identify the substitutions, but I feel the labels are much
> more readable. Moreover, ultimately it would be interesting to see:
>
> "I am %(name)s." % binding
>
> Making use of the binding's local_variables.
>
> The challenge, of course, is to override printf/sprintf to do this
> (the binding part gets you extra ruby points ;-) Even more
> challenging, augment the C code to handle it and submit it as a patch.
>
> T.
>


class String
module M
def % *args
newstuff
super
end
end
include M
end

a @ http://codeforp...
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama




t3ch.dude

2/28/2008 6:22:00 PM

0

On Feb 28, 11:57 am, Trans <transf...@gmail.com> wrote:
> I have a question and perhaps a bit of challenge for those with mad
> parse skills: Has anyone ever considered named parameters for sprintf/
> printf? It would be quite useful (to me at least) to be able to do:
>
>   "I am %(name)s." % { :name => "Tom" ]
>
> Has anyone worked on something like this before? Is there anything
> equivalent in the Perl world or other language? I realize we can use
> numerals to identify the substitutions, but I feel the labels are much
> more readable. Moreover, ultimately it would be interesting to see:
>
>   "I am %(name)s." % binding
>
> Making use of the binding's local_variables.
>
> The challenge, of course, is to override printf/sprintf to do this
> (the binding part gets you extra ruby points ;-)  Even more
> challenging, augment the C code to handle it and submit it as a patch.
>
> T.

That exact feature exists in that form in Python today...
http://docs.python.org/lib/typesseq-st...

-T3ch Dude

yermej

2/28/2008 8:05:00 PM

0

On Feb 28, 11:29 am, ara howard <ara.t.how...@gmail.com> wrote:

> class String
> module M
> def % *args
> newstuff
> super
> end
> end
> include M
> end
>

Can you please explain this? It looks to me like it would allow you to
override a method, but still call the original without using alias.
However, when I try anything like that, it only calls the original
method. The method defined inside of M isn't called. Is that a 1.9
thing or am I misunderstanding what you meant?

Adam Shelly

2/28/2008 8:42:00 PM

0

On 2/28/08, yermej <yermej@gmail.com> wrote:
> On Feb 28, 11:29 am, ara howard <ara.t.how...@gmail.com> wrote:
>
> > class String
> > module M
> > def % *args
> > newstuff
> > super
> > end
> > end
> > include M
> > end
> >
>
> However, when I try anything like that, it only calls the original
> method. The method defined inside of M isn't called.
...
>

I also couldn't get Ara's example to work, so I resorted to monkeypatching.
(Yes, I know, I am Destroying Ruby..)

----------

p "I am %s." % "string"
p "I am %s." % ["array"]
p "I am %s." % { :name => "hash" }
begin
p "I am %(name)s." % { :name => "hash" }
rescue ArgumentError => err
p "caught #{err}"
end

puts "\nMonkeyPatching!\n\n"
class String
alias :old_percent :%
def % arg
arr = (arg.kind_of? Array) ? arg : [arg]
target = self.gsub(/%\((.+?)\)/){|m|
raise ArgumentError, "named parameters need hash" unless arg.kind_of? Hash
arr << arg[$1.to_sym]
"%#{arr.size}$"
}
target.old_percent arr
end
end

p "I am %s." % "string"
p "I am %s." % ["array"]
p "I am %s." % { :name => "hash" }
p "I am %(name)s." % { :name => "hash" }

p "I am %(name)s %(with)s %(what)s"%{:what => "multiple arguments",
:with => "including", :name=> 'hash'}
p "I am %(name)s %(with)s %1$p"%{:with => "containing", :name=> 'hash'}
p "I am %(name)s." % [:name, "array"]


-Adam

P.S. It actually looks like patching sprintf wouldn't be too hard, as
long as you disallowed mixing named arguments with any other type.

Rick DeNatale

2/28/2008 10:42:00 PM

0

On 2/28/08, yermej <yermej@gmail.com> wrote:
> On Feb 28, 11:29 am, ara howard <ara.t.how...@gmail.com> wrote:
>
> > class String
> > module M
> > def % *args
> > newstuff
> > super
> > end
> > end
> > include M
> > end
> >
>
>
> Can you please explain this? It looks to me like it would allow you to
> override a method, but still call the original without using alias.
> However, when I try anything like that, it only calls the original
> method. The method defined inside of M isn't called. Is that a 1.9
> thing or am I misunderstanding what you meant?

No you are right. Including a module in a class effectively inserts
the module above the class in the inheritance chain rather than below,
a class can override methods in a module it includes, not the other
way around. I missed Ara's point as well.

Along these lines I was scratching my head the other night when I was
reading Russ Olsen's "Design Patterns in Ruby" and he was showing an
implementation of the Decorator pattern using modules as decorators, I
missed the subtlety that he was using Object#extend to include a
module above the singleton class of a particular object rather than
including it in a 'real' class. But I don't think that technique
applies here.


--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...

Gary Wright

2/28/2008 11:20:00 PM

0


On Feb 28, 2008, at 11:57 AM, Trans wrote:
> I have a question and perhaps a bit of challenge for those with mad
> parse skills: Has anyone ever considered named parameters for sprintf/
> printf? It would be quite useful (to me at least) to be able to do:
>
> "I am %(name)s." % { :name => "Tom" ]
>
> Has anyone worked on something like this before? Is there anything
> equivalent in the Perl world or other language?

I released a gem last year (http://jig.rub...) that defines
a data structure I nicknamed a Jig that enables this sort of thing
either by parsing a string to get the format or by explicit
construction:

j = Jig.new('I am ', :name)
j2 = Jig.parse('I am %{:name:}')

puts j % { :name => 'Tom'} # I am Tom
puts j2 % { :name => 'Alice'} # I am Alice

A Jig is a ordered sequence of objects and 'gaps'. Simple gaps are
identified as symbols during Jig construction but you can also define
gaps that process anything that is used to fill them:

capitalize = Jig::Gap.new(:name) { |x| x.capitalize }
j2 = Jig.new('before: ', :name, ' after: ', capitalize)
puts j2 % {:name => 'bob' } # 'before: bob after: Bob'

In that example you can see that all gaps with the same name
are plugged simultaneously. Unplugged gaps are rendered as
the empty string when Jig#to_s is called.

You can also construct a Jig or fill a gap with a proc/lambda/method
which will be evaluated at the time the Jig is rendered to a string:

time = Jig.new("The time is ") {Time.now}
puts time # The time is Thu Feb 28 18:16:07 -0500 2008
sleep 5
puts time # The time is Thu Feb 28 18:16:12 -0500 2008

The gem has classes for handling XML, XHTML, and CSS constructs.

I've made a few changes since the initialize release but haven't
gotten around to pushing it a new release to Rubyforge yet....

Gary Wright

http://jig.rub...




ara.t.howard

2/29/2008 12:14:00 AM

0


On Feb 28, 2008, at 1:09 PM, yermej wrote:

> On Feb 28, 11:29 am, ara howard <ara.t.how...@gmail.com> wrote:
>
>> class String
>> module M
>> def % *args
>> newstuff
>> super
>> end
>> end
>> include M
>> end
>>
>
> Can you please explain this? It looks to me like it would allow you to
> override a method, but still call the original without using alias.
> However, when I try anything like that, it only calls the original
> method. The method defined inside of M isn't called. Is that a 1.9
> thing or am I misunderstanding what you meant?
>

i was just being stupid. you'd need something like this


cfp2:~ > cat a.rb
class String

Percent = instance_method '%' unless defined? Percent

def % *a, &b
a.flatten!
string =
case a.last
when Hash
expand a.pop
else
self
end
if a.empty?
string
else
Percent.bind(string).call(*a, &b)
end
end

def expand! vars = {}
loop do
changed = false
vars.each do |var, value|
var = var.to_s
var.gsub! %r/[^a-zA-Z0-9_]/, ''
[
%r/\$#{ var }\b/,
%r/\@#{ var }\b/,
%r/\$\{\s*#{ var }\s*\}/,
%r/\@\{\s*#{ var }\s*\}/,
].each do |pat|
changed = gsub! pat, "#{ value }"
end
end
break unless changed
end
self
end

def expand opts = {}
dup.expand! opts
end

end

puts( 'I am @name'.expand(:name => 'Ara') )
puts( 'I am @name' % {:name => 'Ara'} )



cfp2:~ > ruby a.rb
I am Ara
I am Ara

a @ http://codeforp...
--
share your knowledge. it's a way to achieve immortality.
h.h. the 14th dalai lama



Nobuyoshi Nakada

2/29/2008 4:51:00 AM

0

Hi,

At Fri, 29 Feb 2008 01:57:23 +0900,
Trans wrote in [ruby-talk:292860]:
> I have a question and perhaps a bit of challenge for those with mad
> parse skills: Has anyone ever considered named parameters for sprintf/
> printf? It would be quite useful (to me at least) to be able to do:

Yes, once I had posted the patch for it, and was rejected.

> "I am %(name)s." % { :name => "Tom" ]
>
> Has anyone worked on something like this before? Is there anything
> equivalent in the Perl world or other language? I realize we can use
> numerals to identify the substitutions, but I feel the labels are much
> more readable. Moreover, ultimately it would be interesting to see:
>
> "I am %(name)s." % binding
>
> Making use of the binding's local_variables.

Though I don't feel it attractive, I believe named parameter is
an important feature for I18N, and IIRC, ruby-gettext has it.

--
Nobu Nakada

Gregory Seidman

2/29/2008 3:08:00 PM

0

On Fri, Feb 29, 2008 at 01:51:02PM +0900, Nobuyoshi Nakada wrote:
> Hi,
>
> At Fri, 29 Feb 2008 01:57:23 +0900,
> Trans wrote in [ruby-talk:292860]:
> > I have a question and perhaps a bit of challenge for those with mad
> > parse skills: Has anyone ever considered named parameters for sprintf/
> > printf? It would be quite useful (to me at least) to be able to do:
>
> Yes, once I had posted the patch for it, and was rejected.
>
> > "I am %(name)s." % { :name => "Tom" ]
> >
> > Has anyone worked on something like this before? Is there anything
> > equivalent in the Perl world or other language? I realize we can use
> > numerals to identify the substitutions, but I feel the labels are much
> > more readable. Moreover, ultimately it would be interesting to see:
> >
> > "I am %(name)s." % binding
> >
> > Making use of the binding's local_variables.
>
> Though I don't feel it attractive, I believe named parameter is
> an important feature for I18N, and IIRC, ruby-gettext has it.

You may find the recently announced Jig library of interest. I was sitting
next to Gary during something at RubyConf, maybe RejectConf, and he gave me
a demo. Pretty cool. See http://www.ruby-forum.com/to...

> Nobu Nakada
--Greg


Trans

2/29/2008 6:56:00 PM

0



On Feb 28, 11:51 pm, Nobuyoshi Nakada <n...@ruby-lang.org> wrote:
> Hi,
>
> At Fri, 29 Feb 2008 01:57:23 +0900,
> Trans wrote in [ruby-talk:292860]:
>
> > I have a question and perhaps a bit of challenge for those with mad
> > parse skills: Has anyone ever considered named parameters for sprintf/
> > printf? It would be quite useful (to me at least) to be able to do:
>
> Yes, once I had posted the patch for it, and was rejected.

:(

> > "I am %(name)s." % { :name => "Tom" ]
>
> > Has anyone worked on something like this before? Is there anything
> > equivalent in the Perl world or other language? I realize we can use
> > numerals to identify the substitutions, but I feel the labels are much
> > more readable. Moreover, ultimately it would be interesting to see:
>
> > "I am %(name)s." % binding
>
> > Making use of the binding's local_variables.
>
> Though I don't feel it attractive, I believe named parameter is
> an important feature for I18N, and IIRC, ruby-gettext has it.

Really? It seems like a nice way to apply parameter to templates to
me. Rather then, say,

xml = %{
<customer id="#{params[:id]}">
<name>#{params[:name]}</name>
</customer>
}

One could do:

xml = %{
<customer id="%(id)u">
<name>%(name)s</name>
</customer>
} % params

A little cleaner --and provides a nice means of reusable
interpolation.

I'll have to look at ruby-gettext.

Thanks,
T.