From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS4713 221.184.0.0/13 X-Spam-Status: No, score=-2.6 required=3.0 tests=AWL,BAYES_00, DKIM_ADSP_CUSTOM_MED,FORGED_GMAIL_RCVD,FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_PASS shortcircuit=no autolearn=no autolearn_force=no version=3.4.2 Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by dcvr.yhbt.net (Postfix) with ESMTP id 5C5561F463 for ; Tue, 26 Nov 2019 15:25:39 +0000 (UTC) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id 17EF5120AD9; Wed, 27 Nov 2019 00:25:28 +0900 (JST) Received: from xtrwkhkc.outbound-mail.sendgrid.net (xtrwkhkc.outbound-mail.sendgrid.net [167.89.16.28]) by neon.ruby-lang.org (Postfix) with ESMTPS id D5955120ACF for ; Wed, 27 Nov 2019 00:25:25 +0900 (JST) Received: by filter0186p3mdw1.sendgrid.net with SMTP id filter0186p3mdw1-2167-5DDD43E8-28 2019-11-26 15:25:28.398568776 +0000 UTC m=+574440.529399575 Received: from herokuapp.com (unknown [54.224.235.43]) by ismtpd0062p1iad1.sendgrid.net (SG) with ESMTP id u8dPcVBFS36DSrxo_RNi-Q for ; Tue, 26 Nov 2019 15:25:28.326 +0000 (UTC) Date: Tue, 26 Nov 2019 15:25:28 +0000 (UTC) From: zverok.offline@gmail.com Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 71598 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 14784 X-Redmine-Issue-Author: zverok X-Redmine-Sender: zverok X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: =?us-ascii?Q?3be0g8093pjUjT94eiCA64csFDBI=2FmHQTWm54P5gda5gqiNy9jP1mgkfXCWmBm?= =?us-ascii?Q?3pdDFoxedtdA4ln+Uj2gJmpvEV24Mun7AxBI6vT?= =?us-ascii?Q?ZEmW2vzTudIg3OTX3qQqwLqz2Q14arvevKA5iTZ?= =?us-ascii?Q?3KR6K2HYWeq4ie4TW4D4bHrZEctJ7aOGBzWFAbl?= =?us-ascii?Q?uppX13izDzBk42FqhX1Wk26HhT7KTxcwxQg=3D=3D?= To: ruby-core@ruby-lang.org X-ML-Name: ruby-core X-Mail-Count: 95964 Subject: [ruby-core:95964] [Ruby master Feature#14784] Comparable#clamp with a range X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #14784 has been updated by zverok (Victor Shepelev). @nobu Ugh, sorry, I didn't check the latest one (just judged from the ticket state). All is awesome! Thank you. ---------------------------------------- Feature #14784: Comparable#clamp with a range https://bugs.ruby-lang.org/issues/14784#change-82799 * Author: zverok (Victor Shepelev) * Status: Closed * 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/