[#100689] [Ruby master Feature#17303] Make webrick to bundled gems or remove from stdlib — hsbt@...

Issue #17303 has been reported by hsbt (Hiroshi SHIBATA).

11 messages 2020/11/02

[#100715] [Ruby master Bug#17306] TestGCCompact#test_ast_compacts test failures — v.ondruch@...

Issue #17306 has been reported by vo.x (Vit Ondruch).

11 messages 2020/11/05

[#100720] [Ruby master Feature#17307] A way to mark C extensions as thread-safe, Ractor-safe, or unsafe — eregontp@...

Issue #17307 has been reported by Eregon (Benoit Daloze).

22 messages 2020/11/05

[#100744] [Ruby master Bug#17310] Closed ractors should die — marcandre-ruby-core@...

Issue #17310 has been reported by marcandre (Marc-Andre Lafortune).

12 messages 2020/11/08

[#100753] [Ruby master Feature#17312] New methods in Enumerable and Enumerator::Lazy: flatten, product, compact — zverok.offline@...

Issue #17312 has been reported by zverok (Victor Shepelev).

11 messages 2020/11/09

[#100763] [Ruby master Feature#17314] Provide a way to declare visibility of attributes defined by attr* methods in a single expression — radek.bulat@...

SXNzdWUgIzE3MzE0IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IHJhZGFyZWsgKFJhZG9zxYJhdyBCdcWC

17 messages 2020/11/10

[#100777] [Ruby master Feature#17316] On memoization — sawadatsuyoshi@...

Issue #17316 has been reported by sawa (Tsuyoshi Sawada).

18 messages 2020/11/11

[#100788] [Ruby master Misc#17319] Rename Random::urandom to os_random and document random data sources — zofrex@...

Issue #17319 has been reported by zofrex (James Sanderson).

11 messages 2020/11/11

[#100807] [Ruby master Feature#17322] Deprecate `Random::DEFAULT` and introduce `Random.default()` method to provide Ractor-supported default random generator — ko1@...

Issue #17322 has been reported by ko1 (Koichi Sasada).

14 messages 2020/11/12

[#100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage — ko1@...

Issue #17323 has been reported by ko1 (Koichi Sasada).

19 messages 2020/11/12

[#100849] [Ruby master Feature#17325] Adds Fiber#cancel, which forces a Fiber to break/return — nicholas.evans@...

Issue #17325 has been reported by nevans (Nicholas Evans).

17 messages 2020/11/14

[#100852] [Ruby master Feature#17326] Add Kernel#must! to the standard library — zimmerman.jake@...

SXNzdWUgIzE3MzI2IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IGpleiAoSmFrZSBaaW1tZXJtYW4pLg0K

24 messages 2020/11/14

[#100858] [Ruby master Feature#17327] The Queue constructor should take an initial set of items — chris@...

Issue #17327 has been reported by chrisseaton (Chris Seaton).

10 messages 2020/11/15

[#100897] [Ruby master Feature#17330] Object#non — zverok.offline@...

Issue #17330 has been reported by zverok (Victor Shepelev).

21 messages 2020/11/17

[#100925] [Ruby master Feature#17331] Let Fiber#raise work with transferring fibers — nicholas.evans@...

Issue #17331 has been reported by nevans (Nicholas Evans).

12 messages 2020/11/18

[#100930] [Ruby master Feature#17333] Enumerable#many? — masafumi.o1988@...

Issue #17333 has been reported by okuramasafumi (Masafumi OKURA).

10 messages 2020/11/18

[#100971] [Ruby master Bug#17337] Don't embed Ruby build time configuration into Ruby — v.ondruch@...

Issue #17337 has been reported by vo.x (Vit Ondruch).

16 messages 2020/11/20

[#100999] [Ruby master Feature#17339] Semantic grouping on BigDecimal#to_s — co.chuma@...

Issue #17339 has been reported by chumaltd (Takahiro Chuma).

9 messages 2020/11/21

[#101071] [Ruby master Feature#17342] Hash#fetch_set — hunter_spawn@...

Issue #17342 has been reported by MaxLap (Maxime Lapointe).

26 messages 2020/11/25

[#101093] [Ruby master Misc#17346] DevelopersMeeting20201210Japan — mame@...

Issue #17346 has been reported by mame (Yusuke Endoh).

17 messages 2020/11/26

[#101141] [Ruby master Bug#17354] Module#const_source_location is misleading for constants awaiting autoload — tom@...

SXNzdWUgIzE3MzU0IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IHRvbXN0dWFydCAoVG9tIFN0dWFydCku

21 messages 2020/11/29

[#101143] [Ruby master Feature#17355] Or-patterns (pattern matching like Foo(x) | Bar(x)) — fg@...

Issue #17355 has been reported by decuplet (Nikita Shilnikov).

8 messages 2020/11/29

[#101153] [Ruby master Feature#17356] Alignment of memory allocated through Fiddle struct's malloc — andrea.ribuoli@...

Issue #17356 has been reported by AndreaRibuoli (Andrea Ribuoli).

8 messages 2020/11/30

[ruby-core:100921] Re: [Ruby master Feature#17326] Add Kernel#must! to the standard library

From: Austin Ziegler <halostatue@...>
Date: 2020-11-17 21:46:10 UTC
List: ruby-core #100921
There=E2=80=99s a cognitive cost to every new method added to Ruby objects,=
 and
when adding to Kernel, that cost is higher as it affects all objects and is
*also* usable as a bare function.

This latter suggests that you don=E2=80=99t actually want `Kernel#must!`, b=
ut
`Object#must!` and `Nil#must!` or even `BasicObject#must!`, as `must!` by
itself would be `self.must!`, and would change per context.

I=E2=80=99ve already said this, but I think that this has no place in Ruby=
=E2=80=99s core
method definitions as opposed to how Sorbet already provides it or how it
could be provided as a common types assertion library used by Sorbet and
other type checkers. I would have no problem with a bundled/default gem
being added to Ruby that provides `T.must` and other common type checking
tests (as suggested by zverok
https://bugs.ruby-lang.org/issues/17326#note-10), but I don=E2=80=99t think=
 that
the ability to use `must` in a point-free style is a sufficient reason to
add this as a default method to Ruby objects with special behaviour on
`nil`.

-a

On Tue, Nov 17, 2020 at 4:13 PM <zimmerman.jake@gmail.com> wrote:

> Issue #17326 has been updated by jez (Jake Zimmerman).
>
>
> jeremyevans0 (Jeremy Evans) wrote in #note-12:
>
> > the benefit of adding it is smaller than the cost of adding another
> method to Kernel
>
> Can you speak more on the const of adding a method to Kernel? While I
> understand the costs of something new syntax would bring, I am less
> familiar with the cost to adding something to the standard library.
>
> The benefit to having something in the standard library instead of a gem
> is specifically to make it a common idiom shared across typed and non-typ=
ed
> Ruby codebases. `T.must` already exists in `sorbet-runtime` for the peopl=
e
> who want to only use Sorbet. I am of the belief that third party gems
> should refrain from monkey patching new methods into standard library
> classes, which is why I proposed a change to the standard library directl=
y.
>
> jeremyevans0 (Jeremy Evans) wrote in #note-12:
>
> > I think that outside of Stripe/Sorbet users (a small fraction of Ruby
> programmers), .must! meaning raise if nil? is not intuitive.
>
> Again, I'm 100% fine to change the name to make it more intuitive.
> `.not_nil`, `.not_nil!`, `.unwrap_nil`, `.drop_nil`, etc. If the only
> blocker is the name, that is great: I will agree to any name. I am very
> open to further suggestions of what the name should be.
>
> ----------------------------------------
> Feature #17326: Add Kernel#must! to the standard library
> https://bugs.ruby-lang.org/issues/17326#change-88571
>
> * Author: jez (Jake Zimmerman)
> * Status: Open
> * Priority: Normal
> ----------------------------------------
> # Abstract
>
> We should add a method `Kernel#must!` (name TBD) which raises if `self` i=
s
> `nil` and returns `self` otherwise.
>
>
> # Background
>
> Ruby 3 introduces type annotations for the standard library.
> Type checkers consume these annotations, and report errors for type
> mismatches.
> One of the most common and most valuable type errors is whether `nil` is
> allowed as an argument or return value.
> Sorbet's type system tracks this, and RBS files have syntax for annotatin=
g
> whether `nil` is allowed or not.
>
> Since Sorbet checks proper usage of `nil`, it requires code that looks
> like this:
>
> ```ruby
> if thing.nil?
>   raise "The thing was nil"
> end
>
> thing.do_something
> ```
>
> This is good because it forces the programmer to acknowledge that the
> thing might be `nil`, and declare
> that they'd rather raise an exception in that case than handle the `nil`
> (of course, there are many other
> times where `nil` is both possible and valid, which is why Sorbet forces
> at least considering in all cases).
>
> It is annoying and repetitive to have to write these `if .nil?` checks
> everywhere to ignore the type error,
> so Sorbet provides it as a library function, called `T.must`:
>
> ```ruby
> T.must(thing).do_something
> ```
>
> Sorbet knows that the call to `T.must` raises if `thing` is `nil`.
> To make this very concrete, here's a Sorbet playground where you can see
> this in action:
>
> [=E2=86=92 View on sorbet.run](
> https://sorbet.run/#%23%20typed%3A%20true%0Aextend%20T%3A%3ASig%0A%0Aclas=
s%20Thing%0A%20%20def%20do_something%3B%20end%0Aend%0A%0Asig%20%7Bparams(th=
ing%3A%20T.nilable(Thing)).void%7D%0Adef%20example1(thing)%0A%20%20%23%20er=
ror%2C%20might%20be%20nil%3A%0A%20%20thing.do_something%0Aend%0A%0Asig%20%7=
Bparams(thing%3A%20T.nilable(Thing)).void%7D%0Adef%20example2(thing)%0A%20%=
20if%20thing.nil%3F%0A%20%20%20%20raise%20%22The%20thing%20was%20nil%22%0A%=
20%20end%0A%0A%20%20%23%20no%20error%2C%20because%20it's%20after%20the%20%6=
0if%20.nil%3F%60%20check%3A%0A%20%20thing.do_something%0Aend%0A%0Asig%20%7B=
params(thing%3A%20T.nilable(Thing)).void%7D%0Adef%20example3(thing)%0A%20%2=
0%23%20no%20error%2C%20because%20it's%20after%20the%20%60if%20.nil%3F%60%20=
check%3A%0A%20%20T.must(thing).do_something%0Aend
> )
>
> You can read more about `T.must` in the [Sorbet documentation](
> https://sorbet.org/docs/type-assertions#tmust).
>
>
> # Problem
>
> While `T.must` works, it is not ideal for a couple reasons:
>
> 1.  It leads to a weird outward spiral of flow control, which disrupts
> method chains:
>
>     ```ruby
>     # =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=90
>     # =E2=94=82      =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=90     =E2=94=82
>     # =E2=96=BC      =E2=96=BC    =E2=94=82     =E2=94=82
>     T.must(T.must(task).mailing_params).fetch('template_context')
>     # =E2=94=82      =E2=94=82          =E2=96=B2               =E2=96=B2
>     # =E2=94=82      =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=98               =E2=
=94=82
>     # =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=80=E2=94=80=E2=94=98
>     ```
>
>     compare that control flow with this:
>
>     ```ruby
>     # =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90=E2=94=8C=E2=
=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90=E2=94=8C=E2=94=80=E2=94=80=E2=94=
=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=
=E2=94=80=E2=94=80=E2=94=90=E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=
=94=90
>     # =E2=94=82    =E2=96=BC=E2=94=82    =E2=96=BC=E2=94=82             =
=E2=96=BC=E2=94=82    =E2=96=BC
>       task.must!.mailing_params.must!.fetch('template_context')
>     ```
>
> 2.  It is not a method, so you can't `map` it over a list using
> `Symbol#to_proc`. Instead, you have to expand the block:
>
>     ```ruby
>     array_of_integers =3D array_of_nilable_integers.map {|x| T.must(x) }
>     ```
>
>     Compare that with this:
>
>     ```ruby
>     array_of_integers =3D array_of_nilable_integers.map(&:must!)
>     ```
>
> 3.  It is in a Sorbet-specific gem. We do not intend for Sorbet to be the
> only type checker.
>     It would be nice to have such a method in the Ruby standard library s=
o
> that it can be shared by all type checkers.
>
> 4.  This method can make Ruby codebases that **don't** use type checkers
> more robust!
>     `Kernel#must!` could be an easy way to assert invariants early.
>     Failing early makes it more likely that a test will fail, rather than
> getting `TypeError`'s and `NoMethodError`'s in production.
>     This makes all Ruby code better, not just the Ruby code using types.
>
>
> # Proposal
>
> We should extend the Ruby standard library with something like this::
>
> ```ruby
> module Kernel
>   def must!; self; end
> end
>
> class NilClass
>   def must!
>     raise TypeError.new("nil.must!")
>   end
> end
> ```
>
> These methods would get type annotations that look like this:
> (using Sorbet's RBI syntax, because I don't know RBS well yet)
>
> ```ruby
> module Kernel
>   sig {returns(T.self_type)}
>   def must!; end
> end
>
> class NilClass
>   sig {returns(T.noreturn)}
>   def must!; end
> end
> ```
>
> What these annotations say:
>
> - In `Kernel#must!`, the return value is `T.self_type`, or "whatever the
> type of the receiver was."
>   That means that `0.must!` will have type `Integer`, `"".must!` will hav=
e
> type `String`, etc.
>
> - In `NilClass#must!`, there is an override of `Kernel#must!` with return
> type `T.noreturn`.
>   This is a fancy type that says "this code either infinitely loops or
> raises an exception."
>   This is the name for Sorbet's [bottom type](
> https://en.wikipedia.org/wiki/Bottom_type), if you
>   are familiar with that terminology.
>
> Here is a Sorbet example where you can see how these annotations behave:
>
> [=E2=86=92 View on sorbet.run](
> https://sorbet.run/#%23%20typed%3A%20true%0A%0Amodule%20Kernel%0A%20%20T%=
3A%3ASig%3A%3AWithoutRuntime.sig%20%7Breturns(T.self_type)%7D%0A%20%20def%2=
0must!%3B%20self%3B%20end%0Aend%0A%0Aclass%20NilClass%0A%20%20T%3A%3ASig%3A=
%3AWithoutRuntime.sig%20%7Breturns(T.noreturn)%7D%0A%20%20def%20must!%0A%20=
%20%20%20raise%20TypeError.new(%22nil.must!%22)%0A%20%20end%0Aend%0A%0Axs%2=
0%3D%20T%3A%3AArray%5BInteger%5D.new(%5B0%5D)%0AT.reveal_type(xs.first)%20%=
20%20%20%20%20%20%23%20T.nilable(Integer)%0AT.reveal_type(xs.first.must!)%2=
0%23%20Integer%0A%0Ays%20%3D%20T%3A%3AArray%5BT.nilable(Integer)%5D.new(%5B=
0%2C%20nil%2C%201%2C%20nil%2C%202%5D)%0AT.reveal_type(ys)%20%20%20%20%20%20=
%20%20%20%20%20%20%20%20%23%20T%3A%3AArray%5BT.nilable(Integer)%5D%0AT.reve=
al_type(ys.map(%26%3Amust!))%20%23%20T%3A%3AArray%5BInteger%5D
> )
>
> # Alternatives considered
>
> There was some discussion of this feature at the Feb 2020 Ruby Types
> discussion:
>
> Summarizing:
>
> - Sorbet team frequently recommends people to use `xs.fetch(0)` instead o=
f
> `T.must(xs[0])`
>   on `Array`'s and `Hash`'s because it chains and reads better.
>   `.fetch` not available on other classes.
>
> - It's intentional that `T.must` requires as many characters as it does.
>   Making it slightly annoying to type encourages developers to refactor
> their code so that `nil` never occurs.
>
> - There was a proposal to introduce new syntax like `thing.!!`. This is
> currently a syntax error.
>
>   **Rebuttal**: There is burden to introducing new syntax. Tools like
> Rubocop, Sorbet, and syntax highlighting
>   plugins have to be updated. Also: it is hard to search for on Google (a=
s
> a new Ruby developer). Also: it
>   is very short=E2=80=94having something slightly shorter makes people th=
ink about
> whether they want to type it out
>   instead of changing the code so that `nil` can't occur.
>
> Another alternative would be to dismiss this as "not useful / common
> enough". I don't think that's true.
> Here are some statistics from Stripe's Ruby monolith (~10 million lines o=
f
> code):
>
> | methood | percentage of files mentioning method | number of occurrences
> of method |
> | --- | --- | --- |
> | `.nil?` | 16.69% | 31340 |
> | `T.must` | 23.89% | 74742 |
>
> From this, we see that
>
> - `T.must` is in 1.43x more files than `.nil?`
> - `T.must` occurs 2.38x more often than `.nil?`
>
>
> # Naming
>
> I prefer `must!` because it is what the method in Sorbet is already calle=
d.
>
> I am open to naming suggestions. Please provide reasoning.
>
>
> # Discussion
>
> In the above example, I used `T.must` twice. An alternative way to have
> written that would have been using save navigation:
>
> ```ruby
> T.must(task&.mailing_params).fetch('template_context')
> ```
>
> This works as well. The proposed `.must!` method works just as well when
> chaining methods with safe navigation:
>
> ```ruby
> task&.mailing_params.must!.fetch('template_context')
> ```
>
> However, there is still merit in using `T.must` (or `.must!`) twice=E2=80=
=94it
> calls out that the programmer
> intended neither location to be `nil`. In fact, if this method had been
> chained across multiple lines,
> the backtrace would include line numbers saying specifically **which**
> `.must!` failed:
>
>
> ```ruby
> task.must!
>   .mailing_params.must!
>   .fetch('template_context')
> ```
>
>
>
>
> --
> https://bugs.ruby-lang.org/
>
> Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=3Dunsubscrib=
e>
> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>
>


--=20
Austin Ziegler =E2=80=A2 halostatue@gmail.com =E2=80=A2 austin@halostatue.c=
a
http://www.halostatue.ca/ =E2=80=A2 http://twitter.com/halostatue

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread