Ruby: difference between hexencode and hexdigest - ruby

Today I read the documentation on Rubies hexdigest method, e.g.
Digest::SHA256.hexdigest('123')
=> "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"
The documentation says:
Returns the hex-encoded hash value of a given string. This is almost equivalent to Digest.hexencode(Digest::Class.new(*parameters).digest(string)).
Highlighting is by me: What does almost mean here? How is it different?
Of course my example string above yields the same result:
Digest.hexencode(Digest::SHA256.digest('123'))
=> "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"
Can anyone point me to the cases where the result can be different? I want to understand whether the "almost" points to an important difference or if the difference is irrelevant for me.

As in the module Digest::Instance described hexdigest(string) return hexencode_str_new(value);. In the module Digest described hexencode(string) return hexencode_str_new(value); too. So, there are no differences if use same instance type. "almost" because in the documentation example can be Digest::SHA512 or other.

Related

Why does s[n..-1] work in ruby?

I'm fairly new to ruby. Recently, I wanted to extract a portion of a string from the n'th character of said string to the end.
Doing something like s[n,(s.size - n)] seemed pretty inelegant to me, so I asked a couple of friends.
One suggested I try s[n..-1], and sure enough that works, but he couldn't give me a good reason why it should work. I find the fact that it works rather puzzling, as the following output from irb1.9 should explain:
> s = "0123456789"
=> "0123456789"
> s[2..-1]
=> "23456789"
> (2..-1).to_a
=> []
So as you can see, the range object 2..-1 is empty -- it has no members, which is absolutely what you expect if you go upwards in value from 2 to -1. This is consistent with the documentation for how range objects should work.
The documentation for indexing a string with a range clearly says: "If given a range, a substring containing characters at offsets given by the range is returned" -- but that is an empty set.
I also can find no examples in "The Ruby Programming Language" or in the Ruby docs in which a string is indexed using s[n..-1] or the like, and can find no examples of it in other official sources. It appears to be folklore, however, that it works even though nothing in the manuals indicate that you can index a string with a range this way, and get the result you get even though the range has no members.
Yet, my friend was correct, it works.
So, could someone please explain why this works to me? I'm also very much interested in knowing if the fact that it works is a fluke of MRI/YARV or if this is absolutely expected to work in all Ruby implementations, and if so, where is it documented to work?
EDITED TO ADD:
An answerer below claimed that only the range's begin and end attributes matter for these purposes, but I can find no documentation of that in TRPL or in the Ruby documentation. The answer also claims that there are indeed examples of such "mixed-sign" range indexing, but the only one I could find was in a context where the mixed-range index was shown to produce nil, not a slice of a string. I therefore don't find that answer satisfying.
EDITED TO ADD:
It appears that the correct answer is that this is indeed a defect in the Ruby documentation.
EDITED TO ADD:
The bug was fixed by the Ruby documentation team: see https://bugs.ruby-lang.org/issues/6106
This is a bug in the documentation.
Ruby's documentation has sucked since the Pickaxe book descended like a meteor on matz's actually correct and comprehensive HTML doc. This is a subject that still irritates me on occasion. The answer to your question, from 1.4: link
self[nth]
Retrieves the nth item from an array. Index starts from zero. If index is the negative, counts backward from the end of the array. The index of the last element is -1. Returns nil, if the nth element is not exist in the array.
self[start..end]
Returns an array containing the objects from start to end, including both ends. If ... is used (instead of ..), then end is not included. if end is larger than the length of the array, it will be rounded to the length. If start is out of an array range , returns nil. And if start is larger than end with in array range, returns empty array ([]).
-1 is the last index of an array by definition, as a convenience.
You're right that the range n..-1 is empty. However that doesn't matter because String#[] doesn't treat the range as a collection - it just uses the range's begin and end attributes.
Regarding documentation: The rdoc documentation of String#[] lists the behavior of String#[] for every possible type of argument (including ranges with negative numbers) with examples. So you don't have to rely on folklore. Relevant quote:
If given a range, a substring containing characters at offsets given by the range is returned. [...] if an offset is negative, it is counted from the end of str.
[...]
a = "hello there"
# ...
a[-4..-2] #=> "her"

Turn string into number in Racket

I used read to get a line from a file. The documentation said read returns any, so is it turning the line to a string? I have problems turning the string "1" to the number 1, or "500.8232" into 500.8232. I am also wondering if Racket can directly read numbers in from a file.
Check out their documentation search, it's complete and accurate. Conversion functions usually have the form of foo->bar (which you can assume takes a foo and returns a bar constructed from it).
You sound like you're looking for a function that takes a string and returns a number, and as it happens, string->number does exist, and does pretty much exactly what you're looking for.
Looks like this was answered in another question:
Convert String to Code in Scheme
NB: that converts any s-expression, not just integers. If you want just integers, try:
string->number
Which is mentioned in
Scheme language: merge two numbers
HTH

Ruby: Best way to parse a conditional array element

I'm doing API calls that will conditionally return a couple different elements. My code is currently:
if array['productId']
value = array['productId'][0]
end
I feel like there is a more succinct way of doing this. Some Ruby magic.
A better way :
value = array['productId'][0] if array['productId']
However, array['productId'][0] is not ruby natural. What does your array consist of ?
Since Ruby 2.3.0, the shortest way is Array#dig:
array.dig('productId', 0)
http://ruby-doc.org/core-2.3.0_preview1/Array.html#method-i-dig
I am not sure if you are using value just temporarily or actually using it later, and what you want to do with value when the condition is not met. If you want to return nil for missing keys, then
array['productId'].to_a[0]
can work. Otherwise, SpyrosP's answer will be the best.
This might be a bit pedantic, but to make sure it works in all circumstances, you should not check 'not-nil', but rather that it is indexable; something like this:
value = array['productId'][0] if array['productId'].is_a? Array
Or even better:
value = array['productId'][0] if array['productId'].respond_to? '[]'
Otherwise your code will fail if array['productId'] == 2 (which on the other hand seems reasonable, given the key used - I would have gone product_ids instead).
You could use a ternary:
value = array['productId'].nil? ? nil : array['productId'][0]
Your code pattern looks OK; it's possible to be slightly shorter...
value = (t = x['productId']) && t[0]
Using the maybe pattern of Ick, terse and explicit:
value = array['productId'].maybe[0]
While I think your code is fine (although I'd prefer SpyrosP's one-line version), you have some possibilities:
Rails has Object#try, which would let you do either array['productId'].try(:[], 0) or array['productId'].try(:at, 0).
Some people like the andand gem, which defines Object#andand and is used like array['productId'].andand[0].
Ha, I love all the options here. But since I didn't see what I use most, I'll add one more!
value = array['productId'] && array['productId'].first
(I prefer .first to [0] because it reads a little better)
This presumes you'll have an array in array['productId'], which is the right way to do it (rather than type-checking).
Otherwise, the biggest diference between this and your original code, is that this results in value having nil assigned to it if the array doesn't have anything, whereas your original results in value not being defined (which may cause errors, depending on how you use it down the road).
Hope that helps!

Why is "#{String}" a common idiom in Ruby

A Ruby dev I know asked this; my answer is below... Are there other, better reasons?
Why do so many Ruby programmers do
"#{string}"
rather than
string
since the second form is simpler and more efficient?
Is this a common idiom for Ruby developers? I don't see it that much.
Smaller changes when you later need to do more than simply get the value of the string, but also prepend/append to it at the point of use seems to be the best motivation I can find for that idiom.
There is only one case where this is a recommended idiom :
fname = 'john'
lname = 'doe'
name = "#{fname} #{lname}"
The code above is more efficient than :
name = fname + ' ' + lname
or
name = [fname, lname].join(' ')
What's the broader context of some of the usages? The only thing I can come up with beyond what's already been mentioned is as a loose attempt at type safety; that is, you may receive anything as an argument, and this could ensure that whatever you pass in walks like a duck..or, well, a string (though string.to_s would arguably be clearer).
In general though, this is probably a code smell that someone along the way thought was Best Practices.
I use this kind of code, so that I can pass nil as string and it still will work on a string, rather than seeing some exceptions flying:
def short(string = nil)
"#{string}"[0..7]
end
And it's easier/faster to append some debug code, if it's already in quotes.
So in short: It's more convenient.
Interesting answers, everyone. I'm the developer who asked the original question. To give some more context, I see this occasionally at my current job, and also sometimes in sample code on the Rails list, with variables that are known in advance to contain strings. I could sort of understand it as a substitute for to_s, but I don't think that's what's going on here; I think people just forget that you don't need the interpolation syntax if you're just passing a string variable.
If anyone tried to tell me this was a best practice, I'd run away at top speed.
maybe it is easy way to convert any to string? Because it is the same as call to_s method. But it is quite strange way :).
a = [1,2,3]
"#{a}"
#=> "123"
a.to_s
#=> "123"
I could image this being useful in cases where the object being interpolated is not always a String, as the interpolation implicitly calls #to_s:
"#{'bla'}" => "bla"
"#{%r([a-z])}" => "(?-mix:[a-z])"
"#{{:bla => :blub}}" => "blablub"
May make sense when logging something, where you don't care so much about the output format, but never want an error because of a wrong argument type.

Ruby string mutability

This may be a bit of a nooby question, I have been trying to get better at ruby recently, and started reading the fantastic The Ruby Programming Language. Something that was mentioned is that string literals are considered mutable, so in a loop it is better to use a variable then a literal, as a new string will get instantiated at every iteration.
My question is why? At first I thought it was because of interpolation, but symbols are immutable and they support interpolation. Coming from a static background, it doesn't really make much sense to me.
EDIT:
After reading thenduks answer, I think I may have it. AFAIK, languages like Java or C# don't have destructive string methods (they use upcase, but not upcase!). Because of things like upcase! or <<, the literal cannot be immutable.
Not 100% sure on that, the other possibility is that it is a compile-time interning that happens, which is something that just doesn't happen in a scripting language.
Not really sure what exactly your question is, but consider the following code:
10.times { puts "abc".object_id }
This prints out 10 different id's. Why? Just because you know this string wont change doesn't mean Ruby does. If you think that "abc" should only be created once then what happens if you do:
10.times { puts "abc".upcase! }
The upcase! method mutates the string to be upper case, on the next iteration the string created in the first iteration isn't the same anymore.
Perhaps post a code example that is confusing to you?

Resources