Bug #16173

ENV.delete returns nil when name does not exist and block given

Added by (Burdette Lamar) 30 days ago. Updated 19 days ago.

Target version:
ruby -v:
ruby 2.6.4p104 (2019-08-28 revision 67798) [x64-mingw32]


Attached diff.txt:

  • ENV.delete for nonexistent name and block given:
    • Test enhanced to verify return value is nil.
    • Documentation corrected to say that return value is nil, not value.


diff.txt (2.22 KB) diff.txt (Burdette Lamar), 09/21/2019 05:08 PM


Updated by alanwu (Alan Wu) 29 days ago

This gives the impression that the return value is always nil, which isn't true when the environment variable exists.
Maybe it's worth clarifying that.

Updated by nobu (Nobuyoshi Nakada) 29 days ago

Comparing with Hash#delete, it looks that the document is correct and the code is wrong.

diff --git i/hash.c w/hash.c
index 8b84a14484..7880178dc8 100644
--- i/hash.c
+++ w/hash.c
@@ -4779,7 +4779,7 @@ env_delete_m(VALUE obj, VALUE name)
     VALUE val;

     val = env_delete(name);
-    if (NIL_P(val) && rb_block_given_p()) rb_yield(name);
+    if (NIL_P(val) && rb_block_given_p()) val = rb_yield(name);
     return val;

diff --git i/test/ruby/test_env.rb w/test/ruby/test_env.rb
index b01c3b12ee..1a7656ea7d 100644
--- i/test/ruby/test_env.rb
+++ w/test/ruby/test_env.rb
@@ -107,6 +107,7 @@
     assert_invalid_env {|v| ENV.delete(v)}
     assert_nothing_raised { ENV.delete(PATH_ENV) }
+    assert_equal("NO TEST", ENV.delete("TEST") {|name| "NO "+name})

   def test_getenv

Updated by (Burdette Lamar) 29 days ago

Thanks, nobu (Nobuyoshi Nakada), but I'm not going to propose a change to the functionality.

Updated by (Burdette Lamar) 29 days ago

Thanks, @alanwu. I'm refreshing diff.txt with more fulsome documentation, along with enhanced testing.


Updated by (Burdette Lamar) 29 days ago

  • File deleted (diff.txt)

Updated by Eregon (Benoit Daloze) 28 days ago

IMHO it's better to fix behavior to be consistent with Hash#delete.
And the compatibility risk seems non existent here.

So I think we should change behavior, and not change documentation which would be inconsistent with Hash#delete.
+1 for nobu (Nobuyoshi Nakada)'s patch.

Updated by (Burdette Lamar) 26 days ago

I, being a member only of The Outer Party, can't merge anything here.

I'm agnostic on whether the change should be to the documentation or to the code. My part was just to note the discrepancy.

Can someone in The Inner Party take action?


Updated by jeremyevans0 (Jeremy Evans) 26 days ago

I also agree that nobu's patch should be merged.

Updated by nobu (Nobuyoshi Nakada) 19 days ago (Burdette Lamar) wrote:

Thanks, @alanwu. I'm refreshing diff.txt with more fulsome documentation, along with enhanced testing.

Thank you for the patch.

+ * Deletes the environment variable for +name+ if it exists (ignoring the block, if given); returns +nil+:
+ *   ENV.delete('LINES') # => '300'
+ *   ENV.delete('COLUMNS') { |name| fail 'boo' } # => '120'

It should return the old value, not nil.

+ * Calls the block and returns +nil+ if the environment variable does not exist and block given:
+ *   ENV.delete('NOSUCH') { |name| } # => nil

Non-empty block and non-nil result feels better to me.

Also available in: Atom PDF