[#106939] [Ruby master Bug#18455] `IO#close` has poor performance and difficult to understand semantics. — "ioquatix (Samuel Williams)" <noreply@...>

Issue #18455 has been reported by ioquatix (Samuel Williams).

10 messages 2022/01/01

[#106977] [Ruby master Feature#18461] closures are capturing unused variables — "bughit (bug hit)" <noreply@...>

Issue #18461 has been reported by bughit (bug hit).

12 messages 2022/01/05

[#106994] [Ruby master Feature#18462] Proposal to merge WASI based WebAssembly support — "katei (Yuta Saito)" <noreply@...>

Issue #18462 has been reported by katei (Yuta Saito).

8 messages 2022/01/07

[#106996] [Ruby master Feature#18463] Random number generation with xoshiro — "bbrklm (Benson Muite)" <noreply@...>

Issue #18463 has been reported by bbrklm (Benson Muite).

8 messages 2022/01/07

[#107005] [Ruby master Bug#18464] RUBY_INTERNAL_EVENT_NEWOBJ tracepoint causes an interpreter crash when combined with Ractors — "kjtsanaktsidis (KJ Tsanaktsidis)" <noreply@...>

Issue #18464 has been reported by kjtsanaktsidis (KJ Tsanaktsidis).

14 messages 2022/01/08

[#107008] [Ruby master Bug#18465] Make `IO#write` atomic. — "ioquatix (Samuel Williams)" <noreply@...>

Issue #18465 has been reported by ioquatix (Samuel Williams).

16 messages 2022/01/09

[#107073] [Ruby master Feature#18481] Porting YJIT to Rust (request for feedback) — "maximecb (Maxime Chevalier-Boisvert)" <noreply@...>

Issue #18481 has been reported by maximecb (Maxime Chevalier-Boisvert).

26 messages 2022/01/12

[#107106] [Ruby master Bug#18487] Kernel#binding behaves differently depending on implementation language of items on the stack — "alanwu (Alan Wu)" <noreply@...>

Issue #18487 has been reported by alanwu (Alan Wu).

11 messages 2022/01/13

[#107190] [Ruby master Feature#18498] Introduce a public WeakKeysMap that compares by equality — "byroot (Jean Boussier)" <noreply@...>

Issue #18498 has been reported by byroot (Jean Boussier).

17 messages 2022/01/19

[#107203] [Ruby master Bug#18501] [BUG] try to mark T_NONE object in RubyVM::InstructionSequence. load_from_binary — "byroot (Jean Boussier)" <noreply@...>

Issue #18501 has been reported by byroot (Jean Boussier).

8 messages 2022/01/20

[#107204] [Ruby master Bug#18502] Make ruby-2.7.5 on Solaris 10 ld.so.1: gcc: fatal: libintl.so.8: open failed: No such file or directory — "dklein (Dmitri Klein)" <noreply@...>

Issue #18502 has been reported by dklein (Dmitri Klein).

8 messages 2022/01/20

[#107275] [Ruby master Bug#18512] MacOS 12.1 Monterey Bug — "oucl5976@... (Paul Liu)" <noreply@...>

Issue #18512 has been reported by oucl5976@gmail.com (Paul Liu).

9 messages 2022/01/25

[#107291] [Ruby master Bug#18518] NoMemoryError + [FATAL] failed to allocate memory for twice 1 << large — "Eregon (Benoit Daloze)" <noreply@...>

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

12 messages 2022/01/26

[#107310] [Ruby master Bug#18555] Running "bundle exec middleman server" on M1 Mac gives [BUG] Bus Error at 0x0000000104b04000 — "anthonyaykut (Anthony Aykut)" <noreply@...>

Issue #18555 has been reported by anthonyaykut (Anthony Aykut).

13 messages 2022/01/28

[#107346] [Ruby master Misc#18557] DevMeeting-2022-02-17 — "mame (Yusuke Endoh)" <noreply@...>

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

18 messages 2022/01/29

[#107392] [Ruby master Bug#18560] "Compaction isn't available on this platform" error running PG test suite on ppc64le — "vo.x (Vit Ondruch)" <noreply@...>

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

7 messages 2022/01/31

[ruby-core:107190] [Ruby master Feature#18498] Introduce a public WeakKeysMap that compares by equality

From: "byroot (Jean Boussier)" <noreply@...>
Date: 2022-01-19 11:14:21 UTC
List: ruby-core #107190
Issue #18498 has been reported by byroot (Jean Boussier).

----------------------------------------
Feature #18498: Introduce a public WeakKeysMap that compares by equality
https://bugs.ruby-lang.org/issues/18498

* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
----------------------------------------
This is a clean take on #16038 

### Spec

#### Weak keys only

After a chat with @eregon we believe that what would make the most sense and would be most useful would be
a "WeakKeysMap". Meaning **the keys would be weak references, but the values would be strong references**.
This behavior is also consistent with the terminology in other popular languages such as Javascript and Java were `WeakMap` only have weak keys.

By default **it would use equality semantic, just like a regular `Hash`**. Having an option to compare by indentity instead
could be useful, but not strictly required.

#### Immediate objects support

Many WeakMap implementation in other languages don't accept "immediate" objects (or their equivalent) in the weak slots.
This is because since they are never collected, the weak reference will never possibly expire.

`ObjectSpace::WeakMap` currently accept them, but since both keys and values are weak references, there is legitimate use.

However in a `WeakKeysMap`, using an immediate object as key should likely raise a `TypeError`.

What is less clear is wether `BIGNUM` (allocated `Integer`) and dynamic symbols (allocated `Symbol`) should be accepted.

I believe they shouldn't for consistency, so:

  - No immediate objects
  - No `Integer`
  - No `Symbol`

#### `member` method to lookup an existing key

For some use case, notably deduplication sets, a `member` method that maps `st_get_key` would be useful.

```ruby
def member(key) -> existing key or nil
```

Not sure if `member` is the best possible name, but `#key` is already used for looking up a key by value.

That same method could be useful on `Hash` and `Set` as well, but that would be a distinct feature request.

#### Naming

Possible names:

  - `::WeakMap`
  - `::WeakKeysMap`
  - `::WeakRef::Map`
  - `::WeakRef::WeakMap`
  - `::WeakRef::WeakKeysMap`
  - `::WeakRef::WeakHash`
  - `::WeakRef::WeakKeysHash`

My personal, ligthly held, preference goes toward `::WeakRef::WeakKeysMap`.

### Use cases

#### Deduplicating constructors.

Can be used by large value object classes to automatically re-use existing instances:

```ruby
class SomeValueObject
  CACHE = WeakKeysMap.new

  def self.build(attributes)
    CACHE[attributes] ||= new(attributes).freeze # The instance hold the reference
  end

  def initialize(attributes)
    @attributes = attributes
    ... # compute some expensive or large data
  end

  ...
end
```

#### WeakSet

A `WeakKeysMap` would be a good enough primitive to implement a `WeakSet` in pure Ruby code, just like `Set` is
implemented with a `Hash`.

`WeakSet` are useful for use cases such as avoiding cycles in an object graph without holding strong references.

#### Deduplication sets

Assuming `WeakMap` have the `#member` method.

A small variation on the "deduplicating constructors" use case, better suited for smaller but numerous objects.
The difference here is that we first build the object and then lookup for a pre-existing one. This is the
strategy used to [deduplicate Active Record schema metadata](https://github.com/rails/rails/blob/3be590edbedab8ddcacdf72790d50c3cf9354434/activerecord/lib/active_record/connection_adapters/deduplicable.rb#L5).


```ruby
class DeduplicationSet
  def initialize
    @set = WeakKeysMap.new
  end

  def dedup(object)
    if existing_object = @set.member(object)
      existing_object
    else
      @set[object] = true
      object
    end
  end
end
```

#### Third party object extension

When you need to record some associated data on third party objects for which you don't control the lifetime.
A WeakMap can be used:

```ruby
METADATA = WeakKeysMap.new
def do_something(third_party_object)
  metadata = (METADATA[third_party_object] ||= Metadata.new)
  metadata.foo = "bar"
end
```




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

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

In This Thread

Prev Next