Proposal for Random related functions

102 views
Skip to first unread message

eksperimental

unread,
Jun 3, 2016, 9:18:29 PM6/3/16
to elixir-l...@googlegroups.com
You can read this proposal formated
https://github.com/eksperimental/experimental/blob/random/PROPOSAL.md

# Introducing random related functions

First I would like to address the need for implementing in Elixir our
function for generating random integers: `Integer.random/1` All
functions using random numbers, are calling `:erlang.random_uniform/1`.
This Erlang function is not zero based, so there is an overhead to deal
with it every time, adding and subtracting (`:rand.uniform(n + 1) -
1`), thus leading to potential bugs.


## Integer module

So my proposal is to add `Integer.random/1` and `Integer.random/2`

- `Integer.random(limit)` - It returns a random integer from 0 to limit
(positive or negative integers)

- `Integer.random(lower_limit, upper_limit)` - It returns a random
integer withing two limits.


## Range module

- `Range.random(range)` - It returns an integer within range.
- `Range.random(range, count)` - It returns an list of `count` integers
within range. count can be bigger than the range size.

Uses cases: `Range.random/2` can be useful for generating charlists of
random chars within a range. It is also used by `Enum.random/2` when
the enumerable is a range.

## Enum module

- `Enum.random(enumerable, count)` - It returns a list of count size,
of random items from enumerable. The main difference with
`Enum.take_random/2` is that latter will not include repeated
results, and if count is greater than the number of elements in the
enumerable, it will return short. So `Enum.random/2` guarantees the
count of items, and allows them to be repeated.

`Enum.random/1` has been updated to not to call `Enum.take_random/2`,
but to use `Enum.at/3` instead.

`Enum.at/3` has been optimized to use `Range.at/3` when the enumerable
is a range.


## Additional functions implemented

### Integer.pad_random/2

If we are about to generate huge numbers, `:erlang.random_uniform/1`
will work to a certain limit. `Integer.pad_random/2` has fine tuning
options such as:
- force_size: true | false
- return: :integer | :positive | :negative | :zero_or_positive
| :zero_or_negative

This list can generate incredible HUGE integers, in a very efficient
way.

Use cases: benchmarking functions with different integers and data size
of specific length.

### Kernel.delta/2 and Range.delta/1

I took the chance and introduce new functions that helped me archive
random related functions listed above.

- `Kernel.delta(number1, number2)`: It returns the absolute difference
between two numbers (integer or float).
- `Range.delta(range)`: It returns the absolute difference between the
range limits.

It may sound simple, but I had made mistakes in the past implementing a
quick delta functions.


## Implemented code

It can be found here:
https://github.com/eksperimental/experimental/tree/random

It can be cloned locally by running:

$ git clone -b random --single-branch
https://github.com/eksperimental/experimental.git

Looking forward to hearing your opinion,

— Eksperimental

eksperimental

unread,
Jun 3, 2016, 9:37:26 PM6/3/16
to elixir-l...@googlegroups.com
I forgot to mention that Range.at/3 has been implemented.

***************
### Range.at/3

It works the same way as Enum.at/3, but given a range, it returns an
integer at the given `index`.

This function is used to optimize `Enum.at/3` when dealing with ranges.
***************

eksperimental

unread,
Jun 23, 2016, 6:21:28 PM6/23/16
to elixir-l...@googlegroups.com
An answer from someone from the core team would be more than welcome on
this proposal.

In addition to the proposed funtions, this proposal also tackles an issue in Enum.random/1 when dealing with
a ranges, which is really slow if the range is huge, since it delegates
to take_random to be converted to a list to later pick one element.

It optimized Enum.at/2 when dealing with ranges.

Thank you.

José Valim

unread,
Jun 23, 2016, 6:42:34 PM6/23/16
to elixir-l...@googlegroups.com
We should definitely optimize functions like at and random when we can, so definitely +1 on this front.

Regarding the other functions, I am still skeptical of their need. In particular, if we implement Enum.random fast enough for ranges, it would be enough to replace many of the other functions listed, like Integer.random and Range.random. :)



José Valim
Skype: jv.ptec
Founder and Director of R&D


--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/20160624052120.33c80adc.eksperimental%40autistici.org.
For more options, visit https://groups.google.com/d/optout.

eksperimental

unread,
Jun 23, 2016, 7:05:37 PM6/23/16
to elixir-l...@googlegroups.com
Initially Range.at/2 and Range.random/1 were part of Enum.at/2 and
Enum.random/1 respectively.
They were just moved to their own functions because it made more sense
to me.

These functions are fast enough IMO (as fast as I can
think of).

I would not get rid of Integer.random/1-2 as it's the base for all
other random functions. I think it is very cumbersome to
call `:rand.uniform(n + 1) - 1` every time a need a random number
between 0 and n, and even more complicated if i want a random number
between two integers.

Please let me know how should I proceed
thank you for your feedback

On Fri, 24 Jun 2016 00:42:13 +0200
José Valim <jose....@plataformatec.com.br> wrote:

> We should definitely optimize functions like at and random when we
> can, so definitely +1 on this front.
>
> Regarding the other functions, I am still skeptical of their need. In
> particular, if we implement Enum.random fast enough for ranges, it
> would be enough to replace many of the other functions listed, like
> Integer.random and Range.random. :)
>
>
>
> *José Valim*

José Valim

unread,
Jun 23, 2016, 7:14:13 PM6/23/16
to elixir-l...@googlegroups.com
Please let me know how should I proceed
thank you for your feedback

For now let's go with the optimizations for Enum.random / Enum.take_random. :)

eksperimental

unread,
Jun 23, 2016, 7:19:31 PM6/23/16
to elixir-l...@googlegroups.com
ok. I will submit a PR as soon as I have some spare time
Reply all
Reply to author
Forward
0 new messages