Why does String#% method not work with hash having keys as strings?

I am good with the below two :

hash = {"_id"=> 12, "result"=>2177, "time" => '2014-05-22 06:15:45 UTC' }
"%s => %s" % hash.values_at('time', 'result')
# => "2014-05-22 06:15:45 UTC => 2177"
# !> too many arguments for format string
hash = {"_id"=> 12, :result => 2177, :time => '2014-05-22 06:15:45 UTC' }
"%{time} => %{result}" % hash # !> possibly useless use of % in void context
# => "2014-05-22 06:15:45 UTC => 2177"

# the below is not working
hash = {"_id"=> 12, "result"=>2177, "time" => '2014-05-22 06:15:45 UTC' }
"%{time} => %{result}" % hash
# ~> -:6:in `%': key{time} not found (KeyError)
# ~> from -:6:in `<main>'

Does it mean I can use String#% to hash only when Hash will have keys as a
symbol ? Or there is a trick, that I am missing.

···

--

Regards,
Arup Rakshit

# the below is not working
hash = {"_id"=> 12, "result"=>2177, "time" => '2014-05-22 06:15:45 UTC' }
"%{time} => %{result}" % hash
# ~> -:6:in `%': key{time} not found (KeyError)
# ~> from -:6:in `<main>'

Does it mean I can use String#% to hash only when Hash will have keys as a
symbol ? Or there is a trick, that I am missing.

no tricks here. just plain ruby code

"%{time} => %{result}" % hash.map{|k,v| [k.to_s.to_sym,v]}.to_h

=> "2014-05-22 06:15:45 UTC => 2177"

best regards
-botp

···

On Sat, May 31, 2014 at 2:12 AM, Arup Rakshit <aruprakshit@rocketmail.com> wrote:

String#% does not hash - it's a shortcut for sprintf():

irB(mAin):008:0> "A%04dB" % 1
=> "A0001B"
irB(mAin):009:0> "A%04dB" % 34
=> "A0034B"
irB(mAin):010:0> "A%04dB%pX" % [34, 99]
=> "A0034B99X"
irB(mAin):011:0> "A%04dB%pX" % [34, [1,2]]
=> "A0034B[1, 2]X"

irb(main):012:0> sprintf "A%04dB", 1
=> "A0001B"
irb(main):013:0> sprintf "A%04dB", 34
=> "A0034B"
irb(main):014:0> sprintf "A%04dB%pX", 34, 99
=> "A0034B99X"
irb(main):015:0> sprintf "A%04dB%pX", 34, [1,2]
=> "A0034B[1, 2]X"

Cheers

robert

···

On Fri, May 30, 2014 at 8:12 PM, Arup Rakshit <aruprakshit@rocketmail.com> wrote:

Does it mean I can use String#% to hash only when Hash will have keys as a
symbol ? Or there is a trick, that I am missing.

--
[guy, jim].each {|him| remember.him do |as, often| as.you_can - without end}
http://blog.rubybestpractices.com/

Not true anymore:

% ri String.%
= String.%

(from ruby core)

···

On May 31, 2014, at 6:18, Robert Klemme <shortcutter@googlemail.com> wrote:

On Fri, May 30, 2014 at 8:12 PM, Arup Rakshit > <aruprakshit@rocketmail.com> wrote:

Does it mean I can use String#% to hash only when Hash will have keys as a
symbol ? Or there is a trick, that I am missing.

String#% does not hash - it's a shortcut for sprintf():

irB(mAin):008:0> "A%04dB" % 1
=> "A0001B"
irB(mAin):009:0> "A%04dB" % 34
=> "A0034B"
irB(mAin):010:0> "A%04dB%pX" % [34, 99]
=> "A0034B99X"
irB(mAin):011:0> "A%04dB%pX" % [34, [1,2]]
=> "A0034B[1, 2]X"

irb(main):012:0> sprintf "A%04dB", 1
=> "A0001B"
irb(main):013:0> sprintf "A%04dB", 34
=> "A0034B"
irb(main):014:0> sprintf "A%04dB%pX", 34, 99
=> "A0034B99X"
irb(main):015:0> sprintf "A%04dB%pX", 34, [1,2]
=> "A0034B[1, 2]X"

------------------------------------------------------------------------------
  str % arg -> new_str

------------------------------------------------------------------------------

Format---Uses str as a format specification, and returns the result of
applying it to arg. If the format specification contains more than one
substitution, then arg must be an Array or Hash containing the values to
be substituted. See Kernel::sprintf for details of the format string.

  "%05d" % 123 #=> "00123"
  "%-5s: %08x" % [ "ID", self.object_id ] #=> "ID : 200e14d6"
  "foo = %{foo}" % { :foo => 'bar' } #=> "foo = bar"

I wouldn't convert a hash to hash again. Because for me, it is then easy to
use *array* .

hash = {"_id"=> 12, "result"=>2177, "time" => '2014-05-22 06:15:45 UTC' }
"%s => %s" % hash.values_at('time', 'result')
# => "2014-05-22 06:15:45 UTC => 2177"

···

On Saturday, May 31, 2014 03:01:57 PM botp wrote:
no tricks here. just plain ruby code

> "%{time} => %{result}" % hash.map{|k,v| [k.to_s.to_sym,v]}.to_h

=> "2014-05-22 06:15:45 UTC => 2177"

best regards
-botp

--

Regards,
Arup Rakshit

Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it.

--Brian Kernighan

Does it mean I can use String#% to hash only when Hash will have keys as a
symbol ? Or there is a trick, that I am missing.

String#% does not hash - it's a shortcut for sprintf():

irB(mAin):008:0> "A%04dB" % 1
=> "A0001B"
irB(mAin):009:0> "A%04dB" % 34
=> "A0034B"
irB(mAin):010:0> "A%04dB%pX" % [34, 99]
=> "A0034B99X"
irB(mAin):011:0> "A%04dB%pX" % [34, [1,2]]
=> "A0034B[1, 2]X"

irb(main):012:0> sprintf "A%04dB", 1
=> "A0001B"
irb(main):013:0> sprintf "A%04dB", 34
=> "A0034B"
irb(main):014:0> sprintf "A%04dB%pX", 34, 99
=> "A0034B99X"
irb(main):015:0> sprintf "A%04dB%pX", 34, [1,2]
=> "A0034B[1, 2]X"

Not true anymore:

What is not true any more? You are just confirming what I wrote above.

% ri String.%
= String.%

(from ruby core)
------------------------------------------------------------------------------
  str % arg -> new_str

------------------------------------------------------------------------------

Format---Uses str as a format specification, and returns the result of
applying it to arg. If the format specification contains more than one
substitution, then arg must be an Array or Hash containing the values to
be substituted. See Kernel::sprintf for details of the format string.

  "%05d" % 123 #=> "00123"
  "%-5s: %08x" % [ "ID", self.object_id ] #=> "ID : 200e14d6"
  "foo = %{foo}" % { :foo => 'bar' } #=> "foo = bar"

Yes, exactly my point.

Cheers

robert

···

On Mon, Jun 2, 2014 at 6:55 AM, Ryan Davis <ryand-ruby@zenspider.com> wrote:

On May 31, 2014, at 6:18, Robert Klemme <shortcutter@googlemail.com> wrote:

On Fri, May 30, 2014 at 8:12 PM, Arup Rakshit >> <aruprakshit@rocketmail.com> wrote:

--
[guy, jim].each {|him| remember.him do |as, often| as.you_can - without end}
http://blog.rubybestpractices.com/

Does it mean I can use String#% to hash only when Hash will have keys as a
symbol ? Or there is a trick, that I am missing.

String#% does not hash - it's a shortcut for sprintf():

irB(mAin):008:0> "A%04dB" % 1
=> "A0001B"
irB(mAin):009:0> "A%04dB" % 34
=> "A0034B"
irB(mAin):010:0> "A%04dB%pX" % [34, 99]
=> "A0034B99X"
irB(mAin):011:0> "A%04dB%pX" % [34, [1,2]]
=> "A0034B[1, 2]X"

irb(main):012:0> sprintf "A%04dB", 1
=> "A0001B"
irb(main):013:0> sprintf "A%04dB", 34
=> "A0034B"
irb(main):014:0> sprintf "A%04dB%pX", 34, 99
=> "A0034B99X"
irb(main):015:0> sprintf "A%04dB%pX", 34, [1,2]
=> "A0034B[1, 2]X"

Not true anymore:

What is not true any more? You are just confirming what I wrote above.

I read your statement to say that String#% doesn't handle hashes, tho on second reading you might have meant that it doesn't #hash. Not that I can figure out why you'd say such a thing. Arup's mail was pretty clear that he was using String#% with a hash argument.

% ri String.%
= String.%

(from ruby core)
------------------------------------------------------------------------------
str % arg -> new_str

------------------------------------------------------------------------------

Format---Uses str as a format specification, and returns the result of
applying it to arg. If the format specification contains more than one
substitution, then arg must be an Array or Hash containing the values to
be substituted. See Kernel::sprintf for details of the format string.

"%05d" % 123 #=> "00123"
"%-5s: %08x" % [ "ID", self.object_id ] #=> "ID : 200e14d6"
"foo = %{foo}" % { :foo => 'bar' } #=> "foo = bar"

Yes, exactly my point.

Not exactly your point. None of your examples of sprintf are like the last example of the String#% rdoc:

"foo = %{foo}" % { :foo => 'bar' }

returns:

"foo = bar"

So you were confusing the issue when the OP was clearly using a hash argument.

···

On Jun 2, 2014, at 0:27, Robert Klemme <shortcutter@googlemail.com> wrote:

On Mon, Jun 2, 2014 at 6:55 AM, Ryan Davis <ryand-ruby@zenspider.com> wrote:

On May 31, 2014, at 6:18, Robert Klemme <shortcutter@googlemail.com> wrote:

On Fri, May 30, 2014 at 8:12 PM, Arup Rakshit >>> <aruprakshit@rocketmail.com> wrote:

Not true anymore:

What is not true any more? You are just confirming what I wrote above.

I read your statement to say that String#% doesn't handle hashes, tho on second reading you might have meant that it doesn't #hash. Not that I can figure out why you'd say such a thing. Arup's mail was pretty clear that he was using String#% with a hash argument.

Well, I read it differently but there you go.

Not exactly your point. None of your examples of sprintf are like the last example of the String#% rdoc:

"foo = %{foo}" % { :foo => 'bar' }

returns:

"foo = bar"

So you were confusing the issue when the OP was clearly using a hash argument.

I was replying to the OP's question "Does it mean I can use String#%
to hash?" You cannot use String#% to hash something - it's just a
formatting function. I just did not provide examples for all use
cases.

Cheers

robert

···

On Mon, Jun 2, 2014 at 12:20 PM, Ryan Davis <ryand-ruby@zenspider.com> wrote:

On Jun 2, 2014, at 0:27, Robert Klemme <shortcutter@googlemail.com> wrote:

On Mon, Jun 2, 2014 at 6:55 AM, Ryan Davis <ryand-ruby@zenspider.com> wrote:

--
[guy, jim].each {|him| remember.him do |as, often| as.you_can - without end}
http://blog.rubybestpractices.com/

​I suspect Arup meant "with a hash" rather than "to hash."​ Only folk with
a certain amount of computer science type background would consider "to
hash" to be a verb. Further, I'd imagine someone without that background,
and maybe without the same fluency in English, would have misinterpreted
your "String#% does not hash" statement similarly (i.e. as "String#% does
not accept a hash"), and thus confusion ensues.

Though it'd be kind of cool if String#% had a format thingy for the MD5 of
the input. :wink:

···

On 2 June 2014 21:30, Robert Klemme <shortcutter@googlemail.com> wrote:

I was replying to the OP's question "Does it mean I can use String#%
to hash?" You cannot use String#% to hash something - it's just a
formatting function. I just did not provide examples for all use
cases.

--
  Matthew Kerwin
  http://matthew.kerwin.net.au/

That's my mistake and bad English made you guys confused.

My straight question was -

We can pass a hash object as an argument to the method *String#%*. But when
the hash will be having keys as a string object, if i try to access it, it
will throw error as below :

hash = { 'apple' => 2 }

"I want %{apple} apples" % hash
#key{apple} not found (KeyError)

But no problem, while the hash is having keys as symbols -

hash = { :apple => 2 }

"I want %{apple} apples" % hash
# => "I want 2 apples"

Why so? Because I didn't find any such *note* in the documentation.

···

On Monday, June 02, 2014 01:30:51 PM Robert Klemme wrote:

> So you were confusing the issue when the OP was clearly using a hash
> argument.
I was replying to the OP's question "Does it mean I can use String#%
to hash?" You cannot use String#% to hash something - it's just a
formatting function. I just did not provide examples for all use
cases.

--

Regards,
Arup Rakshit

Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it.

--Brian Kernighan