I have been trying to generate a random string. One approach in, say,
pascal would be something like this:
function GetRandomChar: char;
var
r: integer;
begin
r := random(36);
case r of
0…25: result := chr(ord(‘a’) + r);
else : result := chr(ord(‘0’) + r);
end;
end;
I know that there is something like “a”.next but I need something more
like “a” + some_random_value. Even though it is more terse than the
Pascal, I am trying to avoid something time consuming and inelegant like
def gen_random_string(len)
(0…len).collect{rand(36).to_s(36)}.map{|x|
(rand<0.5)?x:x.upcase}.join
end
…for short strings of length 64 or whatever. For very long strings,
the
above may be a bit inefficient. (To generate a 1_000_000 character
string takes about 2.4 seconds on my system.)
function GetRandomChar: char;
var
r: integer;
begin
r := random(36);
case r of
0…25: result := chr(ord(‘a’) + r);
else : result := chr(ord(‘0’) + r);
end;
end;
In this case, you can just do:
def get_random_char
rand(36).to_s(36)
end
Since Ruby allows arbitrary bignums, you can also get strings this way
too. e.g. for an 8-digit string:
rand(36 ** 8).to_s(36)
However there’s a bug there, because numbers with one or more leading
zeros will be truncated. How to left-pad a non-decimal number with zeros
isn’t actually that obvious. Maybe someone can point out something
simpler than this:
("0"*8 + rand(36 ** 8).to_s(36))[-8..-1]
(Unfortunately, “%08s” as a format string pads with spaces not zeros)
end;
rand(36 ** 8).to_s(36)
Interesting idea! Does rand have enough precision to fill arbitrary
large numbers?
However there’s a bug there, because numbers with one or more leading
zeros will be truncated. How to left-pad a non-decimal number with zeros
isn’t actually that obvious. Maybe someone can point out something
simpler than this:
(“0”*8 + rand(36 ** 8).to_s(36))[-8…-1]
(Unfortunately, “%08s” as a format string pads with spaces not zeros)
You can probably squeeze out a bit performance especially for large
strings by replacing this with “s.upcase!; s”.
A very bad idea IMO. Why make your code larger and less readable for the
sake of perhaps one microsecond or less? If performance matters on this
microscopic scale, you should be writing in C.
microscopic scale, you should be writing in C.
I agree that “s.upcase!; s” is ugly, and I really wish the bang
methods returned self on success and raised an exception on error as
that’s closer to how I use them than the current approach, but it’s
still a well-established idiom and hardly likely to confuse even a
neophyte so long as they bother to RTFM.
As to the notion that we should only write performant code in C… why
complicate a codebase by using two languages (with all the debugging
nightmare that can entail) if the language you’re already working in
is capable of doing the job anyway?
As to the notion that we should only write performant code in C… why
complicate a codebase by using two languages (with all the debugging
nightmare that can entail) if the language you’re already working in
is capable of doing the job anyway?
“Doing the job” is the critical part of that sentence.
In my opinion, if (and only if) your existing program won’t do the job
within acceptable parameters, should you start modifying the code to
make it acceptable. Since you should have “done the simplest thing that
will possibly work” in the first place, then by definition, the modified
code will be more complex.
But more importantly: profile first, modify second. I find it highly
unlikely that in a real-world program, removing that one single hidden
string dup will make a noticeable improvement. More likely you’ll want
to change your algorithm or data structures.
Of course, if in your particular application this change does improve
performance noticeably, then by all means make the change (and add a
comment as to why it was necessary to write it in a non-obvious way, so
that somebody doesn’t simplify it back again later). But I think that’s
the point: write more complex code only if it makes a measurable
improvement, not on the off-chance that it might.
I agree that “s.upcase!; s” is ugly, and I really wish the bang methods
returned self on success and raised an exception on error as that’s closer to
how I use them than the current approach, but it’s still a well-established
idiom and hardly likely to confuse even a neophyte so long as they bother to
RTFM.
I don’t think the distinction is between success and failure, though.
(str=“ABC”).upcase! succeeds – it just doesn’t change str. (I’m not a
huge fan of the nil returns either, by the way.)
You can probably squeeze out a bit performance especially for large
strings by replacing this with “s.upcase!; s”.
A very bad idea IMO. Why make your code larger and less readable for the
sake of perhaps one microsecond or less?
I do not subscribe to the “less readable” assessment of yours -
uglier, yes. Also note that a microsecond per execution can be
harmful when the method is invoked often and / or the rest of the code
is not much costlier.
If performance matters on this
microscopic scale, you should be writing in C.
I couldn’t have put it better than Ellie. Notice that object
allocation is one of the most expensive operations in Ruby. So it may
pay off to save one. Btw, this is also the reason why my solution
only works with Fixnums.
Apart from that I find unnecessary object creation ugly. You may call
that personal taste but with GC in mind there is also a quantifiable
reason to not waste objects.
I couldn’t have put it better than Ellie. Notice that object
allocation is one of the most expensive operations in Ruby. So it may
pay off to save one. Btw, this is also the reason why my solution
only works with Fixnums.
Apart from that I find unnecessary object creation ugly. You may call
that personal taste but with GC in mind there is also a quantifiable
reason to not waste objects.
I share that view. Being promiscuous with resources just because it’s
simple to do so seems like a sure-fire way to build applications with
intrinsic scalability problems. It may save me some effort today, but
experience taught me long ago that it’s a decision that will come back
to haunt me.
I don’t think the distinction is between success and failure, though.
(str=“ABC”).upcase! succeeds – it just doesn’t change str. (I’m not a
huge fan of the nil returns either, by the way.)