Is the ruby operator ||= intelligent?

前端 未结 5 2003
长发绾君心
长发绾君心 2020-11-29 10:30

I have a question regarding the ||= statement in ruby and this is of particular interest to me as I\'m using it to write to memcache. What I\'m wondering is, does ||= check

5条回答
  •  囚心锁ツ
    2020-11-29 10:44

    This is extremely easy to test:

    class MyCache
      def initialize
        @hash = {}
      end
    
      def []=(key, value)
        puts "Cache key '#{key}' written"
        @hash[key] = value
      end
    
      def [](key)
        puts "Cache key '#{key}' read"
        @hash[key]
      end
    end
    

    Now simply try the ||= syntax:

    cache = MyCache.new
    cache["my key"] ||= "my value"  # cache value was nil (unset)
    # Cache key 'my key' read
    # Cache key 'my key' written
    
    cache["my key"] ||= "my value"  # cache value is already set
    # Cache key 'my key' read
    

    So we can conclude that no assignment takes place if the cache key already exists.

    The following extract from the Rubyspec shows that this is by design and should not be dependent on the Ruby implementation:

    describe "Conditional operator assignment 'obj.meth op= expr'" do
      # ...
      it "may not assign at all, depending on the truthiness of lhs" do
        m = mock("object")
        m.should_receive(:foo).and_return(:truthy)
        m.should_not_receive(:foo=)
        m.foo ||= 42
    
        m.should_receive(:bar).and_return(false)
        m.should_not_receive(:bar=)
        m.bar &&= 42
      end
      # ...
    end
    

    In the same file, there is a similar spec for [] and []= that mandates identical behaviour.

    Although the Rubyspec is still a work in progress, it has become clear that the major Ruby implementation projects intend to comply with it.

提交回复
热议问题