-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Checking a Hash for the presence of a key #21
Comments
It's possible :) Qo[foo: Any] See the https://github.com/baweaver/any Before this you would have used a "wildcard": Qo[foo: :*] Does that satisfy the need? |
Also noted as of
require "any/version"
class Any
class << self
def ==(other) true end
def ===(other) true end
def to_proc; proc { true } end
end
end The only difference between this and the actual code is I stripped out the comments and spacing: https://github.com/baweaver/any/blob/master/lib/any.rb |
That's not great, but I guess it works well enough. Thanks. Does the same trick work for FWIW, for the rabbit hole that led me to creating this issue I'm trying to check that a Hash has keys and values that match certain constraints without checking any particular key/value pair. For example, check that all keys are Symbols and that all values are Integers. |
Hrm. That'd break the API as it exists. It assumes a key or method is
present. I _could_ potentially make === work on keys as a last comparator
but that'd break a lot of code.
I'd have to think it over. I could make a contract type method and see if
that works.
…On Wed, Sep 5, 2018, 1:32 PM Brandon Fosdick ***@***.***> wrote:
That's not great, but I guess it works well enough. Thanks.
Does the same trick work for Hash#value?? ie. Qo[Any => 42]
FWIW, for the rabbit hole that led me to creating this issue I'm trying to
check that a Hash has keys and values that match certain constraints
without checking any particular key/value pair. For example, check that all
keys are Symbols and that all values are Integers. Qo[Symbol => Integer]
doesn't seem to work.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#21 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AA7zCxxSLlXORhqQWf0fVewYYfL_lCWHks5uYDT3gaJpZM4WZ6I7>
.
|
Example: contract = Qo.contract.all(Symbol => Integer)
contract.call(a: 1, b: 2) # => true
contract.call('a' => 1, b: 2) # => false There would have to be an additional stipulation of all, so as to not violate the current API contract. I'd need to think this one through. |
(though now I almost wonder if this is another gem entirely as Qo itself doesn't behave like this) |
Musing on it a bit, it seems like the only way to get it to work is to make a distinction between 1-item and true multi-arity lists. The problem is that'd slow the entire thing down a few clicks and introduce a bit more implied magic into the code. |
I managed to get it to work relatively easily, with the caveat that I created a stripped down For starters I created an # Compare the given pattern to all of the elements of a container and return true if they all match
def self.all?(*args)
_m = self.new(*args)
-> other { other.all?(_m) }
end
# RSpec
...
expect(Matcher.all?(Symbol => Integer)).to be === {foo:42, bar:24}
... The arguments to def ===(other)
...
if other.is_a?(Array) and (2 == other.length)
(k === other.first) and (v === other.last)
end
...
end And that's enough to pass the test. Admittedly it could use more testing, and the special-case logic certainly isn't ideal. In fact, it's probably terrible. So far it's working well enough for what I need. ¯\(ツ)/¯ |
Looking back on this issue, I believe it would add too much magic to the API. It would likely be better suited as an extension implementing some of the same interfaces. |
It's currently possible to check that a Hash contains a given key and that the key's value matches a desired value. However, checking for the presence of a key without checking the key's value (ie. a matcher that's equivalent to
Hash#key?
) isn't possible.My first thought was to try
Qo[key? => :foo]
, but that fails with an ArgumentError becausekey?
needs an argument.After reading the source I thought that
Qo[ [:key?, :foo] => true ]
would work, but it didn't, presumably because thematcher
argument topublic_send
isn't being splatted. Unfortunately, even if the calls to public_send were "fixed", this would be a tough solution to come up with without reading the code very carefully, and of course it would be an implementation-dependent hack.I humbly suggest extending the API to allow for something like
Qo.key?[:foo]
for handling this use-case. Another option would be to have HashMatcher special-case thekey?
key.The text was updated successfully, but these errors were encountered: