Why doesn’t rand take an integer range and then generate a random number
in between the two?
Example:
rand(5…10) -> a random number from 5 to 10 including 10
rand(5…10) -> a random number from 5 to 10 excluding 10
That or maybe add rand to range so it picks a random item out of the
range. For that matter why doesn’t Array/Hash have a method to return a
random element?
That way [1,2,4].rand and (5…10).rand would work.
Why doesn’t rand take an integer range and then generate a random number
in between the two?
Example:
rand(5…10) → a random number from 5 to 10 including 10
rand(5…10) → a random number from 5 to 10 excluding 10
That or maybe add rand to range so it picks a random item out of the
range. For that matter why doesn’t Array/Hash have a method to return a
random element?
That way [1,2,4].rand and (5…10).rand would work.
Charles,
We were talking about this in IRC. Maybe you were one of those?
Someone suggested allowing not just rand(Fixnum) and rand(Range)
but in general rand(Enumerable).
Someone else said: That’s kind of “overloading” the meaning of rand.
Well, I can see that might not be appropriate.
I think if it were my decision, I’d do something like:
Let rand accept a (numeric) Range, since rand is already a numeric
kind of thing.
Add pick to Enumerable to pick a random element. (See #3)
Add pick! also, to do a pick with deletion. (rand! is not an
intuitive name)
Why doesn’t rand take an integer range and then generate a random number
in between the two?
Example:
rand(5…10) → a random number from 5 to 10 including 10
rand(5…10) → a random number from 5 to 10 excluding 10
That or maybe add rand to range so it picks a random item out of the
range. For that matter why doesn’t Array/Hash have a method to return a
random element?
That way [1,2,4].rand and (5…10).rand would work.
Charles,
We were talking about this in IRC. Maybe you were one of those?
Someone suggested allowing not just rand(Fixnum) and rand(Range)
but in general rand(Enumerable).
Someone else said: That’s kind of “overloading” the meaning of rand.
Well, I can see that might not be appropriate.
I’m the one who said that, and I was actually referring to the
rand(range) idea I don’t know if overloading is the right word.
It just had the feel of kind of sugarizing this:
rand(x) + y
into this:
rand(x…y)
I’m not strongly against it, though. Given that rand(x) itself is, in
effect, bound by a range, it’s certainly not a big stretch to specify
that range as a Range.
Why doesn’t rand take an integer range and then generate a random number
in between the two?
Example:
rand(5…10) → a random number from 5 to 10 including 10
rand(5…10) → a random number from 5 to 10 excluding 10
That or maybe add rand to range so it picks a random item out of the
range. For that matter why doesn’t Array/Hash have a method to return a
random element?
That way [1,2,4].rand and (5…10).rand would work.
Charles,
We were talking about this in IRC. Maybe you were one of those?
Someone suggested allowing not just rand(Fixnum) and rand(Range)
but in general rand(Enumerable).
Someone else said: That’s kind of “overloading” the meaning of rand.
Well, I can see that might not be appropriate.
I think if it were my decision, I’d do something like:
Let rand accept a (numeric) Range, since rand is already a numeric
kind of thing.
Add pick to Enumerable to pick a random element. (See #3)
Add pick! also, to do a pick with deletion. (rand! is not an
intuitive name)
We were talking about this in IRC. Maybe you were one of those?
Someone suggested allowing not just rand(Fixnum) and rand(Range)
but in general rand(Enumerable).
Someone else said: That’s kind of “overloading” the meaning of rand.
Well, I can see that might not be appropriate.
I think if it were my decision, I’d do something like:
Let rand accept a (numeric) Range, since rand is already a numeric
kind of thing.
Add pick to Enumerable to pick a random element. (See #3)
Add pick! also, to do a pick with deletion. (rand! is not an
intuitive name)
Comments?
Hal
Well I wasn’t in the IRC channel, it gets filtered on my connection, but
I am glad others have thought of using rand in that fashion. I think
those 3 systems make logical sense. I would have the pick command have
some argument to choose what sort of distribution though, defaulting to
uniform distribution. Not sure if it makes more sense to specify these
as constants or as passed blocks or something. I would be worried about
the use of pick though on some things though. Also how would you notate
that pick! had removed an item from a range? It makes sense for sets,
arrays, hashes, but does it make sense for a numeric range? Definitely
have pick for Enumerable, but pick! may have some issues.
Someone suggested allowing not just rand(Fixnum) and rand(Range)
but in general rand(Enumerable).
Would be tricky for general Enumerables…
class Seq
include Enumerable
def each
i = 0
loop do
yield i
i += 1
end
end
end
I’m not quite following (?) – I think the original idea was
something like:
module Enumerable
def rand
to_a[Kernel.rand(size)]
end
end
Please don’t redefine a Kernel method. I think that’s a Bad Idea™.
Why not use #random instead?
>> module Enumerable
>> def random
>> to_a[rand(size)]
>> end
>> end
=> nil
>> [1,4,6].random
=> 4
>> [1,4,6].random
=> 6
It would look like an attribute rather than a method… that is, it
would fit in with #first and #last.
OTOH, I also like the other idea, using #pick and #pick!. #random! just
doens’t make sense, and one method for plucking a random element out of
an array would be nice.
–Mark
···
On Mar 6, 2004, at 10:29 AM, David A. Black wrote:
Please don’t redefine a Kernel method. I think that’s a Bad Idea™.
Why not use #random instead?
Why is redefining a kernel method to take a different class of argument
a bad idea? It’s not like it changes existing functionality, even if
you had aliased it to take a range yourself, since your alias would take
effect before it hit the underlying version. I don’t understand why
this is considered so bad. It hurts in static typed languages sure, but
with duck typing this doesn’t hurt us.
Someone suggested allowing not just rand(Fixnum) and rand(Range)
but in general rand(Enumerable).
Would be tricky for general Enumerables…
class Seq
include Enumerable
def each
i = 0
loop do
yield i
i += 1
end
end
end
I’m not quite following (?) – I think the original idea was
something like:
module Enumerable
def rand
to_a[Kernel.rand(size)]
end
end
No Enumerable#size. Try:
module Enumerable
## Return a random element, or nil if empty.
def rand
i = 1
ret = nil
each do |el|
if Kernel.rand(i) == 0
ret = el
end
i += 1
end
return ret
end
end
Please don’t redefine a Kernel method. I think that’s a Bad Idea™.
Why not use #random instead?
>> module Enumerable
>> def random
>> to_a[rand(size)]
>> end
>> end
=> nil
>> [1,4,6].random
=> 4
>> [1,4,6].random
=> 6
It would look like an attribute rather than a method… that is, it
would fit in with #first and #last.
OTOH, I also like the other idea, using #pick and #pick!. #random! just
doens’t make sense, and one method for plucking a random element out of
an array would be nice.
FWIW, I’m not really for #pick with no args meaning “pick a random
element”. There’s no notion of randomness in “pick”. I’d expect it
to pick an arbitrary element rather than a random one. Perhaps #rand and #pop_random or #delete_at(:random) or something. (#pick!
wouldn’t make sense in Enumerable anyway.)
···
On Mar 6, 2004, at 10:29 AM, David A. Black wrote:
It’s not redefining rand to take more varied arguments that’s a bad
thing, it’s defining it for Array#rand that’s a Bad Idea™, IMHO.
Kernel is included in Object so that you can access it’s methods easily
within other objects. Redefining it in a subclass could potentially
break lots of code. For example, I often do this:
class Array
def randomize()
sort{rand(2)-0.5}
end
end
… and defining an Array#rand would break this.
I like the idea of allowing Kernel.rand(range), for reasons already
presented by others. Kernel.rand(array) seems a little iffy to me, but
that’s me.
–Mark
···
On Mar 6, 2004, at 11:54 AM, Charles Comstock wrote:
Please don’t redefine a Kernel method. I think that’s a Bad Idea™.
Why not use #random instead?
Why is redefining a kernel method to take a different class of
argument a bad idea? It’s not like it changes existing functionality,
even if you had aliased it to take a range yourself, since your alias
would take effect before it hit the underlying version. I don’t
understand why this is considered so bad. It hurts in static typed
languages sure, but with duck typing this doesn’t hurt us.
module Enumerable
## Return a random element, or nil if empty.
def rand
i = 1
ret = nil
each do |el|
if Kernel.rand(i) == 0
ret = el
end
i += 1
end
return ret
end
end
Umm I don’t think that is a uniform distribution, not to mention the
fact that you don’t break out of the each if it succeeds.
Hmm we definitely should allow integer array’s, but I am seeing more and
more potential problems with generic Enumerables. Maybe have it be
another include module, but demand a way to initialize a value anywhere
in an enumerable, not just with each / yield. With integer ranges you
just need the upper/lower bound, but if your defining each object with
succ, it causes issues I think.
Please don’t redefine a Kernel method. I think that’s a Bad Idea™.
Why not use #random instead?
Why is redefining a kernel method to take a different class of
argument a bad idea? It’s not like it changes existing functionality,
even if you had aliased it to take a range yourself, since your alias
would take effect before it hit the underlying version. I don’t
understand why this is considered so bad. It hurts in static typed
languages sure, but with duck typing this doesn’t hurt us.
It’s not redefining rand to take more varied arguments that’s a bad
thing, it’s defining it for Array#rand that’s a Bad Idea™, IMHO.
Kernel is included in Object so that you can access it’s methods easily
within other objects. Redefining it in a subclass could potentially
break lots of code. For example, I often do this:
class Array
def randomize()
sort{rand(2)-0.5}
end
end
… and defining an Array#rand would break this.
You must not be very fond of IO#gets, Thread#exit, Dir::open, or
Proc#binding Which is to say – there are cases where Kernel
methods we use without a receiver do get redefined for specialized
purposes. However, while it’s moot anyway because of my fatal
Enumerable#size flaw, my snippet was really just to show the behavior
we were discussing on IRC. No endorsement of reckless endangerment of
Kernel intended
I like the idea of allowing Kernel.rand(range), for reasons already
presented by others. Kernel.rand(array) seems a little iffy to me, but
that’s me.
I agree; rand(range) seems reasonable but beyond that it starts to
feel wrong.
David
···
On Sun, 7 Mar 2004, Mark Hubbart wrote:
On Mar 6, 2004, at 11:54 AM, Charles Comstock wrote:
I like the idea of allowing Kernel.rand(range), for reasons already
presented by others. Kernel.rand(array) seems a little iffy to me, but
that’s me.
I agree, FWIW.
A thought: what about a “Random” module, somewhat like the Enumerable module.
We can include it where we want it.
Also, there are times when I don’t necessarily want a uniform random “pick” from an Array, but need a certain weighting. The module could help provide that.
def rand
i = 1
ret = nil
each do |el|
if Kernel.rand(i) == 0
ret = el
end
i += 1
end
return ret
end
end
Umm I don’t think that is a uniform distribution, not to mention the
It is uniform…
fact that you don’t break out of the each if it succeeds.
… precisely because he doesn’t break out of the each if it succeeds.
S(i): element i is taken in ret = el (i.e. Kernel.rand(i) == 0)
AND: intersection
PI: big PI (product)
N: number of elements in the Enumerable (if infinite, rand would never
return)
P(ret == el(i) at the end) = P(S(i) AND (for all N >= j > i NOT S(j)))
== { they’re independent if we ignore the fact that this is a PRNG } ==
= P(S(i)) * P(for all j > i NOT (S(j))) == { S(j) and S(j+1) indep. } ==
= 1/i * PI(1-P(S(j)), j = i+1 … N) =
= 1/i * (1-1/(i+1)) * (1-1/(i+2)) * … * (1-1/(N)) =
= 1/i * i/(i+1) * (i+1)/(i+2) * … * (N-1)/N =
= 1/i * i / N = 1 / N
···
On Sun, Mar 07, 2004 at 04:49:39PM +0900, Charles Comstock wrote:
–
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com
Netscape is not a newsreader, and probably never shall be.
– Tom Christiansen
It’s not redefining rand to take more varied arguments that’s a bad
thing, it’s defining it for Array#rand that’s a Bad Idea™, IMHO.
Kernel is included in Object so that you can access it’s methods easily
within other objects. Redefining it in a subclass could potentially
break lots of code. For example, I often do this:
class Array
def randomize()
sort{rand(2)-0.5}
end
end
… and defining an Array#rand would break this.
I like the idea of allowing Kernel.rand(range), for reasons already
presented by others. Kernel.rand(array) seems a little iffy to me, but
that’s me.
–Mark
That’s kind of interesting, I have always thought that half the reason
wy object oriented programming is popular is that it allows you to have
to different methods of scoping. One way is the standard lexical
function style, and the other is dynamic scoping. It’s just cleverely
disguised.
It’s not redefining rand to take more varied arguments that’s a bad
thing, it’s defining it for Array#rand that’s a Bad Idea™, IMHO.
Kernel is included in Object so that you can access it’s methods
easily
within other objects. Redefining it in a subclass could potentially
break lots of code. For example, I often do this:
class Array
def randomize()
sort{rand(2)-0.5}
end
end
… and defining an Array#rand would break this.
You must not be very fond of IO#gets, Thread#exit, Dir::open, or
Proc#binding Which is to say – there are cases where Kernel
methods we use without a receiver do get redefined for specialized
purposes.
point taken Still, with IO#gets and Thread#exit (I admit I haven’t
used the others), the kernel methods were redefined so that they would
make more sense in the context. My beef with Array#rand is that it
redefines it to do something very different from what the Kernel
method does. Kernel.rand generates a random number within parameters,
the proposed Array.rand would select a random element from a list.
Maybe it’s only a distinction I make in my head
However, while it’s moot anyway because of my fatal
Enumerable#size flaw, my snippet was really just to show the behavior
we were discussing on IRC.
Just because it can’t be added to Enumerable, doesn’t mean it should be
nixed. I would certainly still want it in Array, personally. I just
think it should have a different name.
No endorsement of reckless endangerment of
Kernel intended
BTW, the reason I’m fairly strong against Array#rand is because I added
that exact method into my personal “utils” library a while back, and
suddenly a lot of my scripts started failing. It took me a while to
figure out where the problem was.
I like the idea of allowing Kernel.rand(range), for reasons already
presented by others. Kernel.rand(array) seems a little iffy to me, but
that’s me.
I agree, FWIW.
A thought: what about a “Random” module, somewhat like the Enumerable module.
We can include it where we want it.
Also, there are times when I don’t necessarily want a uniform random “pick” from an Array, but need a certain weighting. The module could help provide that.
Whatever.
What about this…
Or, what would the dangers be?
class Range
def random
r = self.to_a
r[ rand(r.size) ]
end
end