ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: shevegen@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:87244] [Ruby trunk Feature#14784] One-sided Comparable#clamp
Date: Wed, 23 May 2018 20:44:44 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-72232.20180523204443.3e85f4c482611689@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-14784.20180523130407@ruby-lang.org

Issue #14784 has been updated by shevegen (Robert A. Heiler).


Considering that Ranges allow a ruby hacker to omit the end value,
for infinity/endless, I think your example makes sense in this
regard, e. g.

    begin .. end

being the same as:

    begin ..

or
    begin..

Perhaps also the converse, but I have to admit that
all these examples look very strange to my eyes. Like:

    clamp(..Date.today)

I always look at it as if something is missing. Personally
I prefer explicit "begin .. end".


The:

    clamp(min: 0, max: 10)

seems to be a nice API, in my opinion. At the least the names "min"
and "max" appear explicit and make sense (to me).

I agree, mostly for consistency, that if endless range has been
accepted, being able to do so via #clamp may seem a logical
continuation (to me). I am mostly neutral to the issue though,
as I do not (yet) use clamp in my own ruby code.

----------------------------------------
Feature #14784: One-sided Comparable#clamp
https://bugs.ruby-lang.org/issues/14784#change-72232

* Author: zverok (Victor Shepelev)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
**Proposal**

Allow "one-sided" `clamp` to limit only upper bound (and, ideally, only lower too).

Proposed implementation: allow `clamp(begin..end)` call sequence (without deprecating `clamp(begin, end)`), to take advantage from open-ended ranges with `clamp(begin..)`.

**Reasoning about range**

I looked through `#clamp` [discussion](https://bugs.ruby-lang.org/issues/10594), but couldn't find there why syntax `clamp(b, e)` was preferred to `clamp(b..e)`. The only one I could think of is possible confuse of how `clamp(b..e)` and `clamp(b...e)` behaviors should differ.

The problem becomes more important with the introduction of [open-ended ranges](https://bugs.ruby-lang.org/issues/12912). I believe this is pretty natural:

```ruby
some_calculation.clamp(0..)    # now, I use clamp(0, Float::INFINITY)
timestamp.clamp(Date.today..)  # now, I typically use clamp(Date.today..INFINITE_FUTURE_DATE) with custom defined constant
```

Counter-arguments:

1. This is "one-sided", you can't do `clamp(..Date.today)`. To this I can answer than from my experience "clamping only minimum" is more frequent, and if you need to clamp only maximum, most of the time there is some "reasonable minumum". Another idea is that maybe this is a proof why "start-less" ranges are necessary, after all, [doubted here](https://bugs.ruby-lang.org/issues/12912#note-12)
2. Why not just leave current `clamp(b, e)` and allow `clamp(b)`? Answer: because when you see `clamp(10)`, is it `clamp(10, nil)`, or `clamp(nil, 10)` (yes, logically it is the first argument that is left, but from readability point of view it is not that obvious). Possible alternative: `clamp(min: 0, max: 10)`, where you can omit any of two.
3. Why do you need one-sided clamp at all? Because alternatives is much more wordy, making reader think:

```ruby
# with clamp
chain.of.calculations.clamp(0..)

# without clamp
v = chain.of.calculations
v < 0 ? 0 : v

# or, with yield_self (renamed to then)
chain.of.calculations.then { |v| v < 0 ? 0 : v }
```

Both alternatives "without `#clamp`" shows intentions much less clear.



-- 
https://bugs.ruby-lang.org/

  parent reply	other threads:[~2018-05-23 20:44 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-14784.20180523130407@ruby-lang.org>
2018-05-23 13:04 ` [ruby-core:87241] [Ruby trunk Feature#14784] One-sided Comparable#clamp zverok.offline
2018-05-23 20:44 ` shevegen [this message]
2018-05-24  4:55 ` [ruby-core:87248] " nobu
2018-05-24  8:39 ` [ruby-core:87251] " zverok.offline
2018-07-18  5:45 ` [ruby-core:87976] " akr
2018-10-07 12:05 ` [ruby-core:89308] " zverok.offline
2018-10-10  6:29 ` [ruby-core:89353] " matz
2018-10-10  6:44 ` [ruby-core:89354] [Ruby trunk Feature#14784] Comparable#clamp with a range shyouhei
2018-10-11  0:26 ` [ruby-core:89364] " akr
2019-04-30 16:38 ` [ruby-core:92500] " jonathan
2019-08-16  7:29 ` [ruby-core:94381] [Ruby master " svoop
2019-08-29  6:56 ` [ruby-core:94655] " matz
2019-10-25  6:48 ` [ruby-core:95540] " zverok.offline
2019-10-25 13:30 ` [ruby-core:95545] " nobu
2019-10-25 14:27 ` [ruby-core:95546] " daniel
2019-11-26 11:01 ` [ruby-core:95955] " zverok.offline
2019-11-26 15:07 ` [ruby-core:95963] " nobu
2019-11-26 15:25 ` [ruby-core:95964] " zverok.offline

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-72232.20180523204443.3e85f4c482611689@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).