Method '!='

Hello all.

I’ve tried something like this:

‘a’.send(’==’, ‘b’) #it works, returns true

But

‘a’.send(’!=’, ‘b’)

said to me:

tricks.rb:11:in Kernel#send': undefined method!=’ for “a”:String
(NoMethodError)

Where am I wrong?

V.

Victor S. wrote:

said to me:

tricks.rb:11:in Kernel#send': undefined method!=’ for “a”:String
(NoMethodError)

Where am I wrong?

V.

a != b gets turned into !(a == b) or something like that.

So != isn’t really a method - it’s just syntax.

-Justin

From: Justin C. [mailto:[email protected]]
Sent: Friday, May 26, 2006 8:28 AM

a != b gets turned into !(a == b) or something like that.

So != isn’t really a method - it’s just syntax.

It’s intuitively understandable; but I feel myself very uncomfortable
when I
can call, but can’t send. OK, would remember this one.

-Justin

V.

I’ve tried something like this:

‘a’.send(’==’, ‘b’) #it works, returns true

Sorry. Return ‘false’, of couse.

V.

On 5/26/06, Victor S. [email protected] wrote:

From: Justin C. [mailto:[email protected]]
Sent: Friday, May 26, 2006 8:28 AM

It’s intuitively understandable; but I feel myself very uncomfortable when I
can call, but can’t send. OK, would remember this one.

-Justin

You can’t call:

irb(main):007:0> ‘a’.!= ‘b’
SyntaxError: compile error
(irb):7: parse error, unexpected tNEQ
‘a’.!= ‘b’
^

So it actually makes sense: you can’t call, so you can’t send.

Quoting [email protected], on Fri, May 26, 2006 at 02:50:27PM +0900:

So, other question: is there way for uniform compare objects by some
operator? (where operator is either == or != or <, or even include?)

Perhaps <=>

Sam

From: Alder G. [mailto:[email protected]]
Sent: Friday, May 26, 2006 8:44 AM

You can’t call:

irb(main):007:0> ‘a’.!= ‘b’
SyntaxError: compile error
(irb):7: parse error, unexpected tNEQ
‘a’.!= ‘b’
^

So it actually makes sense: you can’t call, so you can’t send.

Hmmm… Really :slight_smile:
So, other question: is there way for uniform compare objects by some
operator? (where operator is either == or != or <, or even include?)

-Alder

Victor.

From: Sam R. [mailto:[email protected]]
Sent: Friday, May 26, 2006 9:11 AM

Quoting [email protected], on Fri, May 26, 2006 at 02:50:27PM +0900:

So, other question: is there way for uniform compare objects by some
operator? (where operator is either == or != or <, or even include?)

Perhaps <=>

No-no.

The point was to do things like this:

def filter(object, op, criteria)
object.send op, criteria
end

filter ‘a’, :==, ‘b’
filter ‘Ruby’, :include?, ‘Ru’
filter 110, :<, 15

#filter ‘a’, :!=, ‘b’ <== doesn’t work! :frowning:

Sam

V.

Quoting [email protected], on Fri, May 26, 2006 at 03:16:20PM +0900:

The point was to do things like this:

def filter(object, op, criteria)
object.send op, criteria
end

filter ‘a’, :==, ‘b’
filter ‘Ruby’, :include?, ‘Ru’
filter 110, :<, 15

#filter ‘a’, :!=, ‘b’ <== doesn’t work! :frowning:

Ok, I see.

Probably, its because you are showing us a small piece of a larger
puzzle, but
why not have filter take a block:

def filter(object, op, criteria)
yield object, criteria
end
filter(‘a’, ‘b’) { |o,c| o != c }

or even a proc:

def filter(object, op, criteria)
op.call(object, criteria)
end
filter(‘a’, Proc.new{ |o,c| o != c }, ‘b’)

Cheers,
Sam

From: Sam R. [mailto:[email protected]]
Sent: Friday, May 26, 2006 9:30 AM

No-no.

end
filter(‘a’, ‘b’) { |o,c| o != c }

or even a proc:

def filter(object, op, criteria)
op.call(object, criteria)
end
filter(‘a’, Proc.new{ |o,c| o != c }, ‘b’)

OK, some more pieces of puzzle :slight_smile:

  1. really, the former is used as bunch of filters:

Request.filter [
[:base_type, :==, ‘cpu’],
[:fullname, :include?, ‘Intel’],
[:frequency, :>, 2300]
]

  1. I’m planning inside Request to do the following:
    a) search some pre-fetched array (through Array#select)
    b) so some additional request to database

For (a), filter as lambda is good; but for (b), I need some format I can
convert into plain SQL.

Strange things, right? :slight_smile:

Sam

V.

Victor S. wrote:

filter 110, :<, 15
[:frequency, :>, 2300]
]

  1. I’m planning inside Request to do the following:
    a) search some pre-fetched array (through Array#select)
    b) so some additional request to database

For (a), filter as lambda is good; but for (b), I need some format I can
convert into plain SQL.

From ZenSpider’s Ruby QuickRef, with a couple of corrections:

Operators by Precedence:
:: .
[]
**
-(unary) +(unary) ! ~

  • / %

<< >>
&
| ^

= < <=
<=> == === != =~ !~
&&
||
… …
=(+=, -=…)
not
and or

All of the above are just methods except these:

=, …, …, !, not, &&, and, ||, or, !=, !~, ::

In addition, assignment operators(+= etc.) are not user-definable.

You may want to transform &&, || and != into a certain proc and a
certain other string for use in SQL.

Perhaps something like this:

op = Hash.new do |h, k|
{ :sql => k,
:proc => proc {|obj, *args| obj.send(k, *args) } }
end

op[“&&”] = {:sql => " AND “, :proc => proc {|l,r| l && r } }
op[”||“] = {:sql => " OR “, :proc => proc {|l,r| l || r } }
op[”!=”] = {:sql => " <> “, :proc => proc {|l,r| l != r } }
op[”=="] = {:sql => " = ", :proc => proc {|l,r| l == r } }

op[“>”][:sql] #=> “>”
op[“>”][:proc].call(2, 1) #=> true

Cheers,
Dave

said to me:

tricks.rb:11:in Kernel#send': undefined method!=’ for “a”:String
(NoMethodError)

The syntax magic makes != work… but that doesn’t mean you can’t create
methods to do the same things. define_method is much more lenient on
method names than def is:

class Object
define_method(:<) {|arg| self < arg }
define_method(:>) {|arg| self > arg }
define_method(:!=) {|arg| self != arg }
end

1.send(:>, 5)
=> false

1.send(:<, 5)
=> true

From: Daniel S. [mailto:[email protected]]
Sent: Friday, May 26, 2006 10:18 AM

said to me:
define_method(:>) {|arg| self > arg }
define_method(:!=) {|arg| self != arg }
end

1.send(:>, 5)
=> false

1.send(:<, 5)
=> true

Wow! Elegant. Thanks.

V.

On 5/26/06, Daniel S. wrote:

1.send(:>, 5)
=> false

1.send(:<, 5)
=> true

A good point.

:< and :>, though, are already methods!

1.methods.include? “>” #=> true

Cheers,
Dave

On 5/26/06, Daniel S. [email protected] wrote:

Trying to define a method != doesn’t wfm, even with define_method:

irb(main):013:0> class Object; define_method(:!=) {|arg| self != arg };
end
class Object; define_method(:!=) {|arg| self != arg }; end

SyntaxError: compile error
(irb):13: parse error, unexpected tNEQ, expecting tSTRING_CONTENT or
tSTRING_DBEG or tSTRING_DVAR or tSTRING_END
class Object; define_method(:!=) {|arg| self != arg }; end
^

On 5/26/06, Alder G. wrote:

Trying to define a method != doesn’t wfm, even with define_method:

irb(main):013:0> class Object; define_method(:!=) {|arg| self != arg }; end
class Object; define_method(:!=) {|arg| self != arg }; end

SyntaxError: compile error
(irb):13: parse error, unexpected tNEQ, expecting tSTRING_CONTENT or
tSTRING_DBEG or tSTRING_DVAR or tSTRING_END
class Object; define_method(:!=) {|arg| self != arg }; end
^

No, just that symbol syntax. :!= is not a valid symbol. “!=” will work
just fine, though.

irb(main):001:0> class << self
irb(main):002:1> define_method("!=") {}
irb(main):003:1> end
=> #Proc:0x00000000@:3(irb)

Cheers,
Dave

On 5/26/06, Dave B. [email protected] wrote:

                           ^

Dave
Yup, good tip. However, the relations between the operator syntax and
the method calls reveals itself to be more mysterious than I thought:

class Foo
define_method(‘!=’) { ‘Foo#!= was called’ }
define_method(‘==’) { ‘Foo#== was called’ }
end

irb(main):003:0> foo = Foo.new
#Foo:0x2c88e28

irb(main):004:0> foo != 1
false # looks like ‘foo != arg’ isn’t simply syntactic sugar for
!foo.==(arg)

irb(main):005:0> foo.==
“Foo#== was called”

irb(main):008:0> foo.send ‘!=’
“Foo#!= was called” # And send seems to be the only way to call !=

But as far as Victor is concerned, as long as #send is used, those
methods would work as expected.

2006/5/26, Victor S. [email protected]:

#filter ‘a’, :!=, ‘b’ <== doesn’t work! :frowning:
filter(‘a’, ‘b’) { |o,c| o != c }

  1. really, the former is used as bunch of filters:

For (a), filter as lambda is good; but for (b), I need some format I can
convert into plain SQL.

This solution is not very nice, but the usage of != as symbol in
awkward anyway, the only way I got it to work is this:

irb(main):036:0> :‘!=’
=> :“!=”

module Enumerable
def filter(criteria)
select do |x|
criteria.all? do |member, op, value|
if op == “!=”
x.send(member) != value
else
x.send(member).send(op, value)
end
end
end
end
end

irb(main):024:0> St = Struct.new :name, :size
=> St
irb(main):025:0> a=[St.new(“foo”, 10), St.new(“bar”, -20)]
=> [#<struct St name=“foo”, size=10>, #<struct St name=“bar”, size=-20>]
irb(main):026:0> a.filter [ [:name , “!=” , “foo”], [:size , :< , 0] ]
=> [#<struct St name=“bar”, size=-20>]
irb(main):027:0> a.filter [ [:name , “!=” , “foo”], [:size , :> , 0] ]
=> []

Strange things, right? :slight_smile:

No, IMHO that’s a perfectly valid requirement.

Kind regards

robert

Alder G. wrote:

tSTRING_DBEG or tSTRING_DVAR or tSTRING_END

irb(main):003:0> foo = Foo.new
#Foo:0x2c88e28

irb(main):004:0> foo != 1
false # looks like ‘foo != arg’ isn’t simply syntactic sugar for
!foo.==(arg)

Actually, it still is:

foo.==(1) returns the string ‘Foo#== was called’ which is true. Then it
is negated: false.

Try changing it to:

class Foo
define_method(’!=’) { puts ‘Foo#!= was called’ }
define_method(’==’) { puts ‘Foo#== was called’ }
end

And you will see it call ‘==’.

-Justin

On 5/26/06, Justin C. [email protected] wrote:

irb(main):002:1> define_method(“!=”) {}
define_method(‘!=’) { ‘Foo#!= was called’ }

end

And you will see it call ‘==’.

-Justin

Do’h! You are correct, of course.