Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Define random() behavior for numbers with units #3361

Merged
merged 3 commits into from
Jul 22, 2022
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
103 changes: 103 additions & 0 deletions proposal/random-with-units.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Random With Units: Draft 1

*([Issue](https://github.com/sass/sass/issues/1890))*

This proposal modifies the behavior of the built-in [`math.random()`][random]
function to return a number with matching units to the numeric argument it
received.

[random]: ../spec/built-in-modules/math.md#random

## Table of Contents

* [Background](#background)
* [Summary](#summary)
* [Design Decisions](#design-decisions)
* [New Behavior vs New Syntax](#new-behavior-vs-new-syntax)
* [No Stripping Units Fallback](#no-stripping-units-fallback)
* [Semantics](#semantics)
* [Deprecation Process](#deprecation-process)

## Background

> This section is non-normative.

Sass provides a built-in [`math.random()` function][random] which takes an
optional numeric parameter `$limit` (defaults to `null`).

When `null` is passed it returns a decimal in range `[0, 1)`. When an integer
greater than zero is passed it returns a number in range `[1, $limit)`.
Otherwise it throws an error.

However a numeric integer can include units (e.g. `5px` or `8em`) and the
Goodwine marked this conversation as resolved.
Show resolved Hide resolved
current behavior [drops the units][issue], which is unexpected for most users.
For example: `math.random(42px) => 28` (there is no `px`).

[random]: https://sass-lang.com/documentation/modules/math#random
[issue]: https://github.com/sass/sass/issues/1890

## Summary

> This section is non-normative.

The built-in `math.random($limit: null)` function will keep the same behavior
for numbers without units, but when given an integer with units it will return a
random integer with matching units.

### Design Decisions

#### New Behavior vs New Syntax

This proposal keeps the existing syntax but changes the semantics, therefore it
is a breaking change.

A backwards compatible alternative was a second optional parameter for units,
e.g. `math.random(42, 'px')`, but it didn't solve the problem when the first
parameter has units, e.g. `math.random(42em, 'px')`.

We decided to update the behavior and follow the [deprecation process].

[deprecation process]: #deprecation-process

#### No Stripping Units Fallback

Sass considers [stripping units an anti-pattern], so we won't provide a fallback
option for the previous unit-stripping behavior. Users are expected to rely on
unit-based arithmetic.

[stripping units an anti-pattern]: https://github.com/sass/sass/issues/533#issuecomment-52531596

## Semantics

The `math.random()` function can take an optional parameter `$limit` which
defaults to `null`.

* If `$limit` is `null` then return a floating-point number in range `[0, 1)`.
Goodwine marked this conversation as resolved.
Show resolved Hide resolved
Goodwine marked this conversation as resolved.
Show resolved Hide resolved

> Example: `math.random() => 0.1337001337`

* If `$limit` is an **integer** [number] greater than zero:

* Generate an integer number in range `[1, $limit)`

* If `$limit` [is unitless], return the generated number without units.

> Example: `math.random(123) => 87`

* If `$limit` has [units], return the generated number with the same units.

> Examples: `math.random(123px) => 97px` and `math.random(500%) => 238%`
Goodwine marked this conversation as resolved.
Show resolved Hide resolved

* Otherwise throw an error.

[number]: https://sass-lang.com/documentation/values/numbers
[is unitless]: ../spec/built-in-modules/math.md#is-unitless
[units]: https://sass-lang.com/documentation/values/numbers#units

## Deprecation Process

Given some users may be relying on the existing Dart Sass implementation which
strips off the units, this will be a breaking change for Dart Sass v1.

We will emit deprecation warnings for any use of `math.random($limit)` where the
`$limit` argument evaluates to a number with units.