Sth. wrong with File.file? (or with me)

Mohammad Khan wrote:

Austin Ziegler said:

See, that's why I'm not getting this. [...]

Me too.

Actually, I see #true? as potentially confusing. Imagine explaining to a
newbie why

  if cond

and

  if cond.true?

are not equivalent.

As a newbie, this is also confusing to me

[snip]

That's the key, right there. There is nothing wrong with being a newbie. We've all been there. But the fact is, there will ALWAYS be things that will be surprising to a newbie. Instead of raising a red flag and asking that it change, please try to live with it for a while and see if it still bothers you when you have more experience.

As most of the people who have replied to this thread have stated, the whole #true?/#false? thing is really not _that_ much of an issue. Yes, there are times where it would be convenient, but most of the time it is inconsequential.

···

On Mon, 2004-11-01 at 16:02, Jim Weirich wrote:

--
Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck.org/jamis

Shouldn't that be:

def solar_elev_file=(value)
   @solar_elev_file =
     case value
     when String
  value
     when true
  1
     when false
  0
     when Fixnum
       raise ArgumentError unless [0, 1].include?(value)
  value
     else
       raise TypeError, "solar_elev_file <#{ value.class }> "
     end
end

This way, your gen_command never needs to see true or false values.

i actually coded it that way up front and hated it. the reason is that the
actual value set was lost. it made debugging really hard since i could not
tell if

   a) original input was bad

   b) i created bad bad input

also, by keeping the actual values around i can use the ruby properties of
them. for example, some of the attributes are Time objects - if i convert to
string up front i lost all Times.instance_methods and am left with only a
String (what idl needs). so i made the choice to keep to original value for
each attribute (verified as begin correct) and convert only at the last
minute. in fact i find this to be a general rule with input/ouput of any kind
while programming - never convert input up front unless required for
performance, always keep the 'raw' input and defer conversion

another very important reason, in this specific case, was that certain error
checking cannot be done untill all attributes have been set and i am
generating the command - for example attribute A may be require to be a String,
but only if attribute B is a bool (true? false?). i could do some complex
dependancy tracking but it was easier to simply allow all attributes to be
idependantly correct when setting and to confirm the relationships when
generating the command...

The issue I have with a BoolClass is that it's not clearly an ancestor of
TrueClass and FalseClass (although you'll find arguments from 2002 that
suggest that I think it should be; I was wrong), and there are many possible
values for String#to_bool to choose from:

hai
iie
1
0
true
false
yes
no
da
nyet
...

:slight_smile:

yes - good point.

i think most people would agree that TrueClass and FalseClass and two sides of
the same coin though?

Mmmm. I think that it's more common to encounter a nil variable (e.g.,
unset) than one that is randomly false or true.

i'm running into the latter alot lately:

   config = <<-yaml
     key : ~
   yaml

   conf = YAML::load config

   unless conf['key']
     if conf['key'] == false
       ...
     end
     if conf['key'].nil?
       ...
     end
   else
     ...
   end

eg. both cases. i think the above is just too heavy for ruby. i'd really
like to see something better - maybe

   case conf['key'].truth
     when true
     when false
     when nil
   end

i dunno... saying "if it is false and 'false' or it is false and 'nil'" is
just ... heavy.

I disagree on the commonality. I think that #nil? is a common enough
operation, but I personally rarely use explicit Boolean values.

think hashes:

   h = {
     :key => false,
   }

i end up using #has_key? alot in these conditions... maybe i use hashes too
much :wink:

anyway - i'm not hung up on it but do think it's a normal expectation to have
true? and false? when we have nil? and zero?. after all, how common is zero?
? (sheesh there a too many ? marks here!). also, i really feel the
'asignment vs. comparison' argument is strong.

so now you know my two cents - for all that they are worth. it's great that
we can complain about things like this instead of 'triple contruction upon
insert into the stl::map' or something horrible like that eh? :wink:

cheers.

-a

···

On Tue, 2 Nov 2004, Austin Ziegler wrote:
--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
When you do something, you should burn yourself completely, like a good
bonfire, leaving no trace of yourself. --Shunryu Suzuki

===============================================================================

Flow I guess. If I am reading source, it feels better to say "if a is
not nil" as opposed to "if it is not true that a is nil"

···

On Fri, 12 Nov 2004 09:45:06 +0900, trans. (T. Onoma) <transami@runbox.com> wrote:

What's wrong with:

   if not a.nil?
     ...
   end

T.

Hi --

···

On Fri, 12 Nov 2004, Hal Fulton wrote:

Joel VanderWerf wrote:
>
> Why not just define #empty? for Fixum, File, NilClass, and Object, and
> then define nonempty? instead of (argh, can't... make... self... type...
> this...) nnull? ?

Yes, nnull? is a pretty ugly name, isn't it? But I dislike long names
such as non_null, not_null, non_empty, aint_null, etc.

How about ull? :slight_smile:

David

--
David A. Black
dblack@wobblini.net

Hi --

> Smiley shmiley:
>
> require 'extensions/object'
>
> if a.notnil?
> ...
> elsif b.nonnil?
> ...
> end

What's wrong with:

   if not a.nil?
     ...
   end

It looks good to me. Also:

  unless a.nil?
    ...
  end

although I know some people don't like the unless/else sequence that
might follow on that.

David

···

On Fri, 12 Nov 2004, trans. (T. Onoma) wrote:

On Thursday 11 November 2004 07:30 pm, Gavin Sinclair wrote:

--
David A. Black
dblack@wobblini.net

trans. (T. Onoma) wrote:

> Smiley shmiley:
>
> require 'extensions/object'
>
> if a.notnil?
> ...
> elsif b.nonnil?
> ...
> end

What's wrong with:

   if not a.nil?
     ...
   end

Nothing, really. I'd ordinarily use that, especially in public.

It's a minor bit of (my personal) psychology, really. I'd rather
ask what something IS rather than what it ISN'T.

In the same way, we could say and 'if not a' -- but there is
something a little clearer about 'a.nil?' instead.

It's (distantly) like the line of code I wrote which said:

   upload unless unchanged

and people commented, Why wouldn't you say:

   upload if changed

And I could really only say: Well, that's how I think.

When I code an if, I usually code the "expected" or "normal" case
as the first branch, and the rest as the "else" part.

Similarly when I use unless, it's usually when a case is (expected
to be) rare or exceptional.

Because the file would "normally" be changed, the "unless" part was
an exception to the rule.

This is that kind of thing. It's all in my head.

Hal

···

On Thursday 11 November 2004 07:30 pm, Gavin Sinclair wrote:

Thanks, for your explanation, David.
I have learned it after a confusion about Array#delete

···

On Fri, 2004-11-12 at 16:18, David A. Black wrote:

Hi --

On Sat, 13 Nov 2004, Michael DeHaan wrote:

> "In ruby there have many methods that names end with '!' like, collect!,
> compact!. I was so used to that '!' means its return the object after
> 'affect' and without '!' return the part of the object that was
> affected."
>
> The exclamation actually means the operation is destructive and
> forever changes the contents of the calling object. It doesn't have
> anything to do with the return codes. It's a very nice convention.

Bang (!) methods don't have to be destructive; the ! basically means
"dangerous operation -- be careful!" So there can be non-destructive
methods with ! (like exit!), and destructive methods without it (like
Array#pop). A lot of destructive methods are also bang-methods, but
there's no direct correlation.

What this means, in Matz's words, is: "Every bang method has non-bang
(i.e. safer) counterpart. You can totally forget about bang methods
at first."

David

--
Mohammad

The same way when a newbie working in C is surprised when comparing against true sometimes fails.

Which is why I thought the create response when seeing someone writing

if a == true

was to hit them round the head with a clue stick and to say, don't do that, do this

if a

:wink:

But if we add in a true? method then it'll be harder to explain that this is the wrong thing to do.

Not that I'm against the idea. I'm just pointing out a potential problem.

···

Ara.T.Howard@noaa.gov wrote:

On Tue, 2 Nov 2004, mark sparshatt wrote:

then they'll be surprised when something like

re = /./
if re.match("a").true? then
puts "match"
end

never prints match

don't you think would suprise most newbies too?

  harp:~ > cat a.rb
  re = /./
  if re.match("a") == true
    puts "match"
  end

  harp:~ > ruby a.rb
  (nothing)

--
Mark Sparshatt

i don't think there is anyway around that the fact that newbies must learn that
true (in ruby) is a singleton object and that fact can bite you many ways - and
this is not limited to only #true?

--
Mark Sparshatt

or,

case conf['key'].class
   when TrueClass : true
   when FalseClass : false
   when NilClass : nil
   else : Klass
end

···

On Mon, 2004-11-01 at 18:03, Ara.T.Howard@noaa.gov wrote:

On Tue, 2 Nov 2004, Austin Ziegler wrote:

> Shouldn't that be:
>
> def solar_elev_file=(value)
> @solar_elev_file =
> case value
> when String
> value
> when true
> 1
> when false
> 0
> when Fixnum
> raise ArgumentError unless [0, 1].include?(value)
> value
> else
> raise TypeError, "solar_elev_file <#{ value.class }> "
> end
> end
>
> This way, your gen_command never needs to see true or false values.

i actually coded it that way up front and hated it. the reason is that the
actual value set was lost. it made debugging really hard since i could not
tell if

   a) original input was bad

   b) i created bad bad input

also, by keeping the actual values around i can use the ruby properties of
them. for example, some of the attributes are Time objects - if i convert to
string up front i lost all Times.instance_methods and am left with only a
String (what idl needs). so i made the choice to keep to original value for
each attribute (verified as begin correct) and convert only at the last
minute. in fact i find this to be a general rule with input/ouput of any kind
while programming - never convert input up front unless required for
performance, always keep the 'raw' input and defer conversion

another very important reason, in this specific case, was that certain error
checking cannot be done untill all attributes have been set and i am
generating the command - for example attribute A may be require to be a String,
but only if attribute B is a bool (true? false?). i could do some complex
dependancy tracking but it was easier to simply allow all attributes to be
idependantly correct when setting and to confirm the relationships when
generating the command...

> The issue I have with a BoolClass is that it's not clearly an ancestor of
> TrueClass and FalseClass (although you'll find arguments from 2002 that
> suggest that I think it should be; I was wrong), and there are many possible
> values for String#to_bool to choose from:
>
> hai
> iie
> 1
> 0
> true
> false
> yes
> no
> da
> nyet
> ...
>
> :slight_smile:

yes - good point.

i think most people would agree that TrueClass and FalseClass and two sides of
the same coin though?

> Mmmm. I think that it's more common to encounter a nil variable (e.g.,
> unset) than one that is randomly false or true.

i'm running into the latter alot lately:

   config = <<-yaml
     key : ~
   yaml

   conf = YAML::load config

   unless conf['key']
     if conf['key'] == false
       ...
     end
     if conf['key'].nil?
       ...
     end
   else
     ...
   end

eg. both cases. i think the above is just too heavy for ruby. i'd really
like to see something better - maybe

   case conf['key'].truth
     when true
     when false
     when nil
   end

--
Mohammad

i dunno... saying "if it is false and 'false' or it is false and 'nil'" is
just ... heavy.

> I disagree on the commonality. I think that #nil? is a common enough
> operation, but I personally rarely use explicit Boolean values.

think hashes:

   h = {
     :key => false,
   }

i end up using #has_key? alot in these conditions... maybe i use hashes too
much :wink:

anyway - i'm not hung up on it but do think it's a normal expectation to have
true? and false? when we have nil? and zero?. after all, how common is zero?
? (sheesh there a too many ? marks here!). also, i really feel the
'asignment vs. comparison' argument is strong.

so now you know my two cents - for all that they are worth. it's great that
we can complain about things like this instead of 'triple contruction upon
insert into the stl::map' or something horrible like that eh? :wink:

cheers.

-a
--

> EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
> PHONE :: 303.497.6469
> When you do something, you should burn yourself completely, like a good
> bonfire, leaving no trace of yourself. --Shunryu Suzuki

Shouldn't that be:

def solar_elev_file=(value)
  @solar_elev_file =
    case value
    when String
      value
    when true
      1
    when false
      0
    when Fixnum
      raise ArgumentError unless [0, 1].include?(value)
      value
    else
      raise TypeError, "solar_elev_file <#{ value.class }> "
    end
end

This way, your gen_command never needs to see true or false values.

i actually coded it that way up front and hated it. the reason is that the
actual value set was lost. it made debugging really hard since i could not
tell if

a) original input was bad
b) i created bad bad input

Hmm. Alternatively:

  class SolarElevFile
    def initialize(value)
  # your normal check...
      @value = value
    end

    def to_s
      case @value
      when String
  ",solar_elev_file='#{@value}'"
      when true
  ",solar_elev_file=1"
      when false
  ",solar_elev_file=0"
      when Fixnum
  ",solar_elev_file=#{@value}"
      end
    end
  end

Also note that your original gen_command wouldn't work:
  def gen_command
    command = "%s,'%s','%s'" % [program, olsfile, flagfile]

    if solar_elev_file
      case solar_elev_file
      ...
      when FalseClass
  command << ",solar_elev_file=0"
      ...
      end
    end

This is because the "if solar_elev_file" test would fail if it were
false. Perhaps your test would have better been "unless
solar_elev_file.nil?" :slight_smile:

Using the class, it would be:

  def solar_elev_file=(value)
    @solar_elev_file = SolarElevFile.new(value)
  end

  def solar_elev_file
    @solar_elev_file
  end

  ...

  def gen_command
    command = "%s,'%s','%s" % [ program, olsfile, flagfile ]

    ...
    command << solar_elev_file.to_s if solar_elev_file
    ...
  end

I think that there's a bit of OOness that could be applied to your
code here.

yes - good point.

i think most people would agree that TrueClass and FalseClass and
two sides of the same coin though?

Mmmm. As I said, I don't know that I agree anymore with that
position. They are inverse values of one another, but they aren't
necessarily descendants of the same class. More to the point, the
issue is more like:

  require 'uninheritable'

  class BooleanClass; end
  class TrueClass < BooleanClass; end
  true = TrueClass.new
  class FalseClass < BooleanClass; end
  false = FalseClass.new
  class BooleanClass
    extend Uninheritable
    undef_method :new
  end

The real issue becomes a matter of the value (or rather, what I view
as the lack thereof) of having to do the above. You don't want any
other instances of either TrueClass, or FalseClass -- and you don't
want an instance of BooleanClass, because it has no meaningful or
useful value. So you'd be introducing BooleanClass solely for the
use of true#ancestors and the like.

Mmmm. I think that it's more common to encounter a nil variable
(e.g., unset) than one that is randomly false or true.

i'm running into the latter alot lately:

config = <<-yaml
  key : ~
yaml

...

Maybe that's something that can be changed with the way that YAML
handles truth values. I'm not sure.

I disagree on the commonality. I think that #nil? is a common
enough operation, but I personally rarely use explicit Boolean
values.

think hashes:

h = {
:key => false,
}

i end up using #has_key? alot in these conditions... maybe i use hashes too
much :wink:

I donno. Ruwiki uses hashes heavily :slight_smile:

-austin

···

On Tue, 2 Nov 2004 08:03:50 +0900, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

On Tue, 2 Nov 2004, Austin Ziegler wrote:

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

mark sparshatt wrote:

then they'll be surprised when something like

re = /./
if re.match("a").true? then
puts "match"
end

never prints match

don't you think would suprise most newbies too?

  harp:~ > cat a.rb
  re = /./
  if re.match("a") == true
    puts "match"
  end

  harp:~ > ruby a.rb
  (nothing)

The same way when a newbie working in C is surprised when comparing against true sometimes fails.

Which is why I thought the create response when seeing someone writing

                              ^^^^^^

Should be correct. :-[

···

Ara.T.Howard@noaa.gov wrote:

On Tue, 2 Nov 2004, mark sparshatt wrote:

if a == true

was to hit them round the head with a clue stick and to say, don't do that, do this

if a

:wink:

But if we add in a true? method then it'll be harder to explain that this is the wrong thing to do.

Not that I'm against the idea. I'm just pointing out a potential problem.

--
Mark Sparshatt

i don't think there is anyway around that the fact that newbies must learn that
true (in ruby) is a singleton object and that fact can bite you many ways - and
this is not limited to only #true?

--
Mark Sparshatt

Won't work. Read up on case and #===. Frankly, I strongly suggest
that you ignore TrueClass, FalseClass, and NilClass. The only values
that matter here are true, false, and nil.

-austin

···

On Tue, 2 Nov 2004 08:12:14 +0900, Mohammad Khan <mkhan@lextranet.com> wrote:

case conf['key'].class
when TrueClass : true
when FalseClass : false
when NilClass : nil
else : Klass
end

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

This is because the "if solar_elev_file" test would fail if it were false.
Perhaps your test would have better been "unless solar_elev_file.nil?" :slight_smile:

ah yes - that bug is actually fixed in a bunch of similar code - in reality it
has no effect since having 'solar_elev_file=0' in the command is the same as
not having it, but it's a bug nonetheless... good catch for just reading email
though!

Using the class, it would be:

def solar_elev_file=(value)
   @solar_elev_file = SolarElevFile.new(value)
end

def solar_elev_file
   @solar_elev_file
end

...

def gen_command
   command = "%s,'%s','%s" % [ program, olsfile, flagfile ]

   ...
   command << solar_elev_file.to_s if solar_elev_file
   ...
end

which, lol, fails for the same reason as my code :wink:

i __do__ like your AttributeClass approach though. i'd quickly have

   BooleanAttributeClass < AttributeClass
   StringAttributeClass < AttributeClass
   FloatAttributeClass < AttributeClass

etc. essentially mappings of many ruby types to one idl type... food for
thought.

I think that there's a bit of OOness that could be applied to your code
here.

yes - probably. funny you should mention really - i've been thinking about
this set of classes alot. the snippets are from a class hierarchy that has
about 50 classes already, with lots of inheritence. i started out making
classes for attributes and backed off - probably because i have about 30
classes that generate commands, each with 20-40 attributes and the 'attribute
classes' are not easy to auto-generate or share code via modules/inheritence.
in any case i've got plenty of other classes in there doing classy types of
things... so - this code has been in production for a while and i'm finding
any of the classes hard to change - i used inheritence too much (i'm starting
to think 'at all' == 'too much') i think. anyhow, my current style is moving
back towards lots of hashes and fewer classes because it ends up being much
easier to change or break depending on your perspective, but remember i'm in a
research environment where absolutely NOTHING is stable for > week. in
summary i find a 'good' class design to be more important for languages that
are hard to debug - but less so for ruby. i think this is backwards from what
most people are finding - that ruby encourages good class design. in some
ways i think it does because doing good design is possible so easily, but
coding and debugging is also relatively effortless temping me to be a bit more
lax in the design phase...

thought you might find that interesting.

-a

···

On Tue, 2 Nov 2004, Austin Ziegler wrote:
--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
When you do something, you should burn yourself completely, like a good
bonfire, leaving no trace of yourself. --Shunryu Suzuki

===============================================================================

This is because the "if solar_elev_file" test would fail if it
were false. Perhaps your test would have better been "unless
solar_elev_file.nil?" :slight_smile:

ah yes - that bug is actually fixed in a bunch of similar code -
in reality it has no effect since having 'solar_elev_file=0' in
the command is the same as not having it, but it's a bug
nonetheless... good catch for just reading email though!

:slight_smile:

Using the class, it would be:

def solar_elev_file=(value)
  @solar_elev_file = SolarElevFile.new(value)
end

def solar_elev_file
  @solar_elev_file
end

...

def gen_command
  command = "%s,'%s','%s" % [ program, olsfile, flagfile ]
  ...
  command << solar_elev_file.to_s if solar_elev_file
  ...
end

which, lol, fails for the same reason as my code :wink:

Actually, not at all. By using SolarElevFile, the value of
#solar_elev_file will either be +nil+ or an instance of
SolarElevFile. Thus, it uses Ruby's normal boolean test behaviour
and does exactly what it's supposed to...

i __do__ like your AttributeClass approach though. i'd quickly
have

BooleanAttributeClass < AttributeClass
StringAttributeClass < AttributeClass
FloatAttributeClass < AttributeClass

etc. essentially mappings of many ruby types to one idl type...
food for thought.

Well, it's usable for that.

-austin

···

On Tue, 2 Nov 2004 10:14:00 +0900, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

On Tue, 2 Nov 2004, Austin Ziegler wrote:

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca
: as of this email, I have [ 5 ] Gmail invitations