proposal: let kind_of take more arguments

S

Simon Strandgaard

It just hit me.. why not let kind_of? take more arguments?

irb(main):001:0> x = 3
=> 3
irb(main):002:0> x.kind_of?(String)
=> false
irb(main):003:0> x.kind_of?(String, Fixnum)
ArgumentError: wrong number of arguments(2 for 1)
from (irb):3:in `kind_of?'
from (irb):3
irb(main):004:0>



For instance I have

def push(choice)
if choice.kind_of?(Zero) == false and choice.kind_of?(One) == false
raise "got #{choice.class}"
end
@choices << choice
end


It could turn into

def push(choice)
unless choice.kind_of?(Zero, One)
raise "got #{choice.class}"
end
@choices << choice
end
 
R

Robert Klemme

Simon Strandgaard said:
It just hit me.. why not let kind_of? take more arguments?

irb(main):001:0> x = 3
=> 3
irb(main):002:0> x.kind_of?(String)
=> false
irb(main):003:0> x.kind_of?(String, Fixnum)
ArgumentError: wrong number of arguments(2 for 1)
from (irb):3:in `kind_of?'
from (irb):3
irb(main):004:0>



For instance I have

def push(choice)
if choice.kind_of?(Zero) == false and choice.kind_of?(One) == false

Never compare boolean values to get boolean values. This can lead to
hideous bugs if the method at hand does not return "true" or "false" -
especially with languages that have more than one value for either.
raise "got #{choice.class}"
end
@choices << choice
end


It could turn into

def push(choice)
unless choice.kind_of?(Zero, One)
raise "got #{choice.class}"

ArgumentError is a good choice here. :)
end
@choices << choice
end

Why don't you just do

def push(choice)
case choice
when Zero, One
@choices << choice
else
raise ArgumentError, "got #{choice.class}"
end
end

or

def push(choice)
raise ArgumentError, "got #{choice.class}" unless [Zero,
One].map{|cl|choice.kind_of? cl}.any?
@choices << choice
end

or

class Object
def kind_of_any?( *classes )
classes.each{|cl| return true if kind_of? cl}
false
end
end

Then:

def push(choice)
raise ArgumentError, "got #{choice.class}" unless
choice.kind_of_any?(Zero, One)
@choices << choice
end

Regards

robert
 
S

Simon Strandgaard

Never compare boolean values to get boolean values. This can lead to
hideous bugs if the method at hand does not return "true" or "false" -
especially with languages that have more than one value for either.

Thanks for the warning. I have actually had a few problems with it
earlier, without realizing this.

ArgumentError is a good choice here. :)

I don't have full overview over Ruby's exception hierarchy, but yes
I should use this one here (which I do now). ;-)
Why don't you just do

def push(choice)
case choice
when Zero, One
@choices << choice
else
raise ArgumentError, "got #{choice.class}"
end
end

a switch statement.. easier to read.
However I like to do bailout as soon as possible,
raising ArgumentError this late may make confusion.


or

def push(choice)
raise ArgumentError, "got #{choice.class}" unless [Zero,
One].map{|cl|choice.kind_of? cl}.any?
@choices << choice
end

Confusion :)



def Object#kind_of_any?( *classes )

Yes thought of this.. which maked me propose this idea.
 
R

Robert Klemme

Simon Strandgaard said:
Thanks for the warning. I have actually had a few problems with it
earlier, without realizing this.

:))

I forgot to mention, that it's totally superfluous, too, and thus may cost
you some machine cycles... :))
I don't have full overview over Ruby's exception hierarchy, but yes
I should use this one here (which I do now). ;-)
:))


a switch statement.. easier to read.
However I like to do bailout as soon as possible,
raising ArgumentError this late may make confusion.

What do you mean by "late"? Do you mean that the line with "raise" stands
below the actual operation. Didn't think of that, but yes, it might be
confusing. OTOH, if you can read "case" then it's not so difficult, is
it?
or

def push(choice)
raise ArgumentError, "got #{choice.class}" unless [Zero,
One].map{|cl|choice.kind_of? cl}.any?
@choices << choice
end

Confusion :)
http://lyricsheaven.topcities.com/survey_d_k_bestanden/ELO.htm#confusion
def Object#kind_of_any?( *classes )

Yes thought of this.. which maked me propose this idea.

I'm wondering though whether it's worth the effort. When using duck
typing, you don't need kind_of? anyway.

Btw, I had another idea:

PUSH_ALLOWED = {Zero, One}

def push(choice)
raise ArgumentError, "got #{choice.class}" unless
PUSH_ALLOWED[choice.class]
@choices << choice
end

Of course there is a subtle difference since this does not take sub
classes into consideration. But other than that, it should be faster -
especially if you have more classes that shoule be checked.

:)

Kind regards

robert
 
A

Ara.T.Howard

Date: Thu, 19 Feb 2004 15:43:05 +0100
From: Robert Klemme <[email protected]>
Newsgroups: comp.lang.ruby
Subject: Re: proposal: let kind_of take more arguments




Never compare boolean values to get boolean values. This can lead to
hideous bugs if the method at hand does not return "true" or "false" -
especially with languages that have more than one value for either.


what do you reccomend (when a case won't do) ?

....
unless choice.kind_of?(Zero) or choice.kind_of?(One)
....

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
A

Ara.T.Howard

Date: Thu, 19 Feb 2004 15:25:27 +0100
From: Simon Strandgaard <[email protected]>
Newsgroups: comp.lang.ruby
Subject: proposal: let kind_of take more arguments

It just hit me.. why not let kind_of? take more arguments?

this is a good idea regardless of your exact situation - it reads nicer than a
case, which i generally use for this

-a
irb(main):001:0> x = 3
=> 3
irb(main):002:0> x.kind_of?(String)
=> false
irb(main):003:0> x.kind_of?(String, Fixnum)
ArgumentError: wrong number of arguments(2 for 1)
from (irb):3:in `kind_of?'
from (irb):3
irb(main):004:0>



For instance I have

def push(choice)
if choice.kind_of?(Zero) == false and choice.kind_of?(One) == false
raise "got #{choice.class}"
end
@choices << choice
end


It could turn into

def push(choice)
unless choice.kind_of?(Zero, One)
raise "got #{choice.class}"
end
@choices << choice
end

--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
S

Simon Strandgaard

What do you mean by "late"? Do you mean that the line with "raise" stands
below the actual operation. Didn't think of that, but yes, it might be
confusing. OTOH, if you can read "case" then it's not so difficult, is
it?

It isn't clear at first sight when the method bailouts, and if
the switch statement spans over many lines, then its not visible at all
that its capable of raising exceptions.

Kind_of? similar to bouncer pattern, see
http://www.rubygarden.org/ruby?BouncerPattern


:)

Yes thought of this.. which maked me propose this idea.

I'm wondering though whether it's worth the effort. When using duck
typing, you don't need kind_of? anyway.

Btw, I had another idea:

PUSH_ALLOWED = {Zero, One}

def push(choice)
raise ArgumentError, "got #{choice.class}" unless
PUSH_ALLOWED[choice.class]
@choices << choice
end

Good idea, but gives a complex impression at first sight.

Of course there is a subtle difference since this does not take sub
classes into consideration. But other than that, it should be faster -
especially if you have more classes that shoule be checked.

Im in the make it work phase.

There is 3 phases:
1) make it work
2) make it right
3) make it fast ;-)
 
S

Simon Strandgaard

what do you reccomend (when a case won't do) ?

...
unless choice.kind_of?(Zero) or choice.kind_of?(One)
...

My brain is terrible at dealing with 'unless'.
If its just "unless something" then its ok.
But when its "unless a or b and c" then it chokes.

Am I the only one feeling like this?

Where can I seek help ? ;-)
 
A

Ara.T.Howard

Date: Thu, 19 Feb 2004 16:29:42 +0100
From: Simon Strandgaard <[email protected]>
Newsgroups: comp.lang.ruby
Subject: Re: proposal: let kind_of take more arguments



My brain is terrible at dealing with 'unless'.
If its just "unless something" then its ok.
But when its "unless a or b and c" then it chokes.

Am I the only one feeling like this?

Where can I seek help ? ;-)

a digital logic book, the simplest, will help. de morgan's laws..., eg.

noting that 'unless' is the negation of 'if', in otherwords 'unless' => 'if
not'

let

^ => and

v => or

~ => negation

Z => kind_of? Zero

O => kind_of? One

then we can say your original statement

choice.kind_of?(Zero) == false and choice.kind_of?(One) == false

as simply

~Z ^ ~O

if we want use this conjunction in the negative sense (convert to 'unless')
we can convert using the following heuristic 'negate each clause and flip
the operation'

so

~(~Z ^ ~O) => Z v 0

or

choice.kind_of?(Zero) or choice.kind_of?(One)


now we have the _negation_ of the conjuction. this is want we want though
since were are trying to use it in the negative sense (unless). eg. we're
done:

unless choice.kind_of?(Zero) or choice.kind_of?(One)
...
end


if you express in simple terms it's pretty easy. eg.

HTH.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
R

Robert Klemme

Ara.T.Howard said:
what do you reccomend (when a case won't do) ?

...
unless choice.kind_of?(Zero) or choice.kind_of?(One)
...

Exactly. Boolean operators are for transformation of boolean values.
Comparison with 'true', 'false', 'nil' or whatever is not appropriate for
the stated reasons.

:)

robert
 
R

Robert Klemme

Simon Strandgaard said:
It isn't clear at first sight when the method bailouts, and if
the switch statement spans over many lines, then its not visible at all
that its capable of raising exceptions.

Kind_of? similar to bouncer pattern, see
http://www.rubygarden.org/ruby?BouncerPattern

I see, you want to save the extra method check_arg_xyz(). :)
http://lyricsheaven.topcities.com/survey_d_k_bestanden/ELO.htm#confusion
:)

def Object#kind_of_any?( *classes )

Yes thought of this.. which maked me propose this idea.

I'm wondering though whether it's worth the effort. When using duck
typing, you don't need kind_of? anyway.

Btw, I had another idea:

PUSH_ALLOWED = {Zero, One}

def push(choice)
raise ArgumentError, "got #{choice.class}" unless
PUSH_ALLOWED[choice.class]
@choices << choice
end

Good idea, but gives a complex impression at first sight.

Really? PUSH_ALLOWED[choice.class] looks pretty much like a method call
to me... And it's blindingly fast even for large amounts of classes.
Well, I guess it's a matter of taste then...

You could also use a Set for this like in

require 'Set'
PUSH_ALLOWED = Set.new([Zero, One])

def push(choice)
raise ArgumentError, "got #{choice.class}" unless
PUSH_ALLOWED.include? choice.class

@choices << choice
end

Did I say there are tons of ways in Ruby? :))
Im in the make it work phase.

There is 3 phases:
1) make it work
2) make it right
3) make it fast ;-)

:)))

Have fun!

robert
 
S

Simon Strandgaard

a digital logic book, the simplest, will help. de morgan's laws..., eg.
[snip talk about de morgans law]

Yes I know these rules.. also karnough maps helps gaining overview of
boolean operations. When an expression gets too complex then I like
place a comment with the corresponding karnough map.

What I should have said was that I grew up with 'if then else'.
The 'unless' keyword is a recent addition to my vocabulary, I am still
a bit rusty in its usage.
 
A

Ara.T.Howard

Date: Thu, 19 Feb 2004 18:44:23 +0100
From: Simon Strandgaard <[email protected]>
Newsgroups: comp.lang.ruby
Subject: Re: proposal: let kind_of take more arguments

a digital logic book, the simplest, will help. de morgan's laws..., eg.
[snip talk about de morgans law]

Yes I know these rules.. also karnough maps helps gaining overview of
boolean operations. When an expression gets too complex then I like
place a comment with the corresponding karnough map.

What I should have said was that I grew up with 'if then else'.
The 'unless' keyword is a recent addition to my vocabulary, I am still
a bit rusty in its usage.

ah. i got it from a the 'p' language - one of the good things about it IMHO.
;-)

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL :: http://www.ngdc.noaa.gov/stp/
| TRY :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done
===============================================================================
 
R

Robert Klemme

Simon Strandgaard said:
a digital logic book, the simplest, will help. de morgan's laws...,
eg.
[snip talk about de morgans law]

Yes I know these rules.. also karnough maps helps gaining overview of
boolean operations. When an expression gets too complex then I like
place a comment with the corresponding karnough map.

What I should have said was that I grew up with 'if then else'.
The 'unless' keyword is a recent addition to my vocabulary, I am still
a bit rusty in its usage.

.... unless you use it more and more: this will accustom you to the u-word.

:))

robert
 
N

nobu.nokada

Hi,

At Fri, 20 Feb 2004 20:20:09 +0900,
Simon Strandgaard wrote in [ruby-talk:93193]:
It could turn into

def push(choice)
unless choice.kind_of?(Zero, One)
raise "got #{choice.class}"
end
@choices << choice
end

unless [Zero, One].any? {|klass| choice.kind_of?(klass)}

Or shorter

unless [Zero, One].any?(&choice.method:)kind_of?)
 
S

Simon Strandgaard

I see, you want to save the extra method check_arg_xyz(). :)

Yes, it depends on if its understandable at first sight and isn't
too visually disturbing. The concept of minimizing visual noise.

If it isn't clear what is going on, then turn that piece of code into a
check_something method.

If the 'if-statement' is simple, then I typically don't make a
check_something method out of that.
 
Y

Yukihiro Matsumoto

Hi,

In message "proposal: let kind_of take more arguments"

|It just hit me.. why not let kind_of? take more arguments?

kinf_of? method easily hinders "duck typing", so that I don't feel
good to make it easier to use.

matz.
 
G

Gavin Kistner

unless [Zero, One].any? {|klass| choice.kind_of?(klass)}

Or shorter

unless [Zero, One].any?(&choice.method:)kind_of?)

Or, as I noted on the RCR:

unless ([Zero,One] & choice.class.ancestors).length>0
 
R

Robert Klemme

Gavin Kistner said:
unless [Zero, One].any? {|klass| choice.kind_of?(klass)}

Or shorter

unless [Zero, One].any?(&choice.method:)kind_of?)

Or, as I noted on the RCR:

unless ([Zero,One] & choice.class.ancestors).length>0

if ([Zero,One] & choice.class.ancestors).empty?

:))
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,143
Messages
2,570,822
Members
47,368
Latest member
michaelsmithh

Latest Threads

Top