Is anyone using -w?

I've been wanting to use -w ... However, I found out that quite a few
high-profile gems out there are not clean under -w (e.g. pry), meaning that
I have a hard time using -w myself.

How many people actually *do* use -w ? Is this really a "best practice" in
the ruby world these days ?

Sylvain

FWIW, both tenderlove and I have all our libraries -w clean. Many of us do, but it only takes one bad apple to ruin it for all your work. :confused:

We started warningfree · GitHub to try to address this, but we could really use contributions (Sadly, there are way more of them than there are of us).

···

On Jun 23, 2014, at 4:30, Sylvain Joyeux <sylvain.joyeux@polytechnique.org> wrote:

I've been wanting to use -w ... However, I found out that quite a few high-profile gems out there are not clean under -w (e.g. pry), meaning that I have a hard time using -w myself.

How many people actually *do* use -w ? Is this really a "best practice" in the ruby world these days ?

I do not attempt to write "-w clean" code, or even use `-w`, because:

     wayne@mercury:~$ irb -w
     2.1.1 :001 > class Foo
     2.1.1 :002?> private
     2.1.1 :003?> attr_accessor :bar
     2.1.1 :004?> end
     (irb):3: warning: private attribute?

There is occasionally a valid reason to make a private accessor/reader/writer, and no harm that I know of.

I think the only good choices are "-w clean" or don't use -w. If I used "-w" and then ignored some warnings, I would get so used to seeing the warnings that I soon wouldn't notice it when a warning I cared about popped up. It would also send a strange message to someone running tests on my code: "why does this test turn on -w and yet emit warnings? Does this guy just not care?"

- Wayne Conrad

···

On 06/23/2014 04:30 AM, Sylvain Joyeux wrote:

How many people actually *do* use -w ? Is this really a "best practice" in the ruby world these days ?

Here's one reason I avoid -w:

class PointOnTimeline
   def initialize time
     @t0 = time # might be Time or something else
   end

   def do_something_with_other_time time
     time < @t0 # fail fast if time and @t0 are not comparable
     return "something"
   end
end

The code is generic with respect to the objects used as times. We don't want to assert that they are Time instances, only that they can be compared.

However:

$ ruby -w t.rb
t.rb:7: warning: possibly useless use of < in void context

Yep, we called #< without using the result. So, what to do? Assign it to an unused local? That's a warning. Wrap it in `if ... end`? Ok, no warning, but that looks strange. Is there a missing `then` clause?

Maybe the best -w clean version is:

time.send(:<, @t0)

But that doesn't really make the intent clearer, and in fact it suggests a different intent: that we're trying to call a private method.

···

On 06/23/2014 04:30 AM, Sylvain Joyeux wrote:

I've been wanting to use -w ... However, I found out that quite a few
high-profile gems out there are not clean under -w (e.g. pry), meaning
that I have a hard time using -w myself.

How many people actually *do* use -w ? Is this really a "best practice"
in the ruby world these days ?

Hi guys,

what is -w? It's incredible hard to Google :slight_smile:

···

On 23 June 2014 22:05, Ryan Davis <ryand-ruby@zenspider.com> wrote:

On Jun 23, 2014, at 4:30, Sylvain Joyeux <sylvain.joyeux@polytechnique.org> > wrote:

> I've been wanting to use -w ... However, I found out that quite a few
high-profile gems out there are not clean under -w (e.g. pry), meaning that
I have a hard time using -w myself.
>
> How many people actually *do* use -w ? Is this really a "best practice"
in the ruby world these days ?

FWIW, both tenderlove and I have all our libraries -w clean. Many of us
do, but it only takes one bad apple to ruin it for all your work. :confused:

We started warningfree · GitHub to try to address this, but we
could really use contributions (Sadly, there are way more of them than
there are of us).

--
== If you're doing it alone, you're probably doing it wrong ==

How many people actually *do* use -w ? Is this really a "best practice"
in the ruby world these days ?

I do not attempt to write "-w clean" code, or even use `-w`, because:

    wayne@mercury:~$ irb -w
    2.1.1 :001 > class Foo
    2.1.1 :002?> private
    2.1.1 :003?> attr_accessor :bar
    2.1.1 :004?> end
    (irb):3: warning: private attribute?

There is occasionally a valid reason to make a private
accessor/reader/writer, and no harm that I know of.

There are definitely valid reasons for wanting private/protected accessors
– I'm not sure why ruby gives a warning there, but it may just be that it's
easy to add the accessor in the wrong place – or it can be non-obvious to a
reader that it is private.

If you definitely want a private accessor/reader/writer, you can tell ruby
like this:

class Foo
  attr_accessor :bar
  private :bar
end

... and that is warning clean.

···

On Wed, Jun 25, 2014 at 12:44 PM, Wayne Conrad <kf7qga@gmail.com> wrote:

On 06/23/2014 04:30 AM, Sylvain Joyeux wrote:

I think the only good choices are "-w clean" or don't use -w. If I used
"-w" and then ignored some warnings, I would get so used to seeing the
warnings that I soon wouldn't notice it when a warning I cared about popped
up. It would also send a strange message to someone running tests on my
code: "why does this test turn on -w and yet emit warnings? Does this guy
just not care?"

- Wayne Conrad

--
/tooky

This is a bit my problem as well. Maybe there is a need to be able to turn
some warnings on or off depending on the application (as most compilers
allow these days).

Sylvain

···

2014-06-25 13:44 GMT+02:00 Wayne Conrad <kf7qga@gmail.com>:

On 06/23/2014 04:30 AM, Sylvain Joyeux wrote:

How many people actually *do* use -w ? Is this really a "best practice"
in the ruby world these days ?

I do not attempt to write "-w clean" code, or even use `-w`, because:

    wayne@mercury:~$ irb -w
    2.1.1 :001 > class Foo
    2.1.1 :002?> private
    2.1.1 :003?> attr_accessor :bar
    2.1.1 :004?> end
    (irb):3: warning: private attribute?

There is occasionally a valid reason to make a private
accessor/reader/writer, and no harm that I know of.

I think the only good choices are "-w clean" or don't use -w. If I used
"-w" and then ignored some warnings, I would get so used to seeing the
warnings that I soon wouldn't notice it when a warning I cared about popped
up. It would also send a strange message to someone running tests on my
code: "why does this test turn on -w and yet emit warnings? Does this guy
just not care?"

- Wayne Conrad

Not true. You can't call a private writer (without send) because private means you can't use a receiver.

···

On Jun 25, 2014, at 4:44, Wayne Conrad <kf7qga@gmail.com> wrote:

On 06/23/2014 04:30 AM, Sylvain Joyeux wrote:

How many people actually *do* use -w ? Is this really a "best practice" in the ruby world these days ?

I do not attempt to write "-w clean" code, or even use `-w`, because:

   wayne@mercury:~$ irb -w
   2.1.1 :001 > class Foo
   2.1.1 :002?> private
   2.1.1 :003?> attr_accessor :bar
   2.1.1 :004?> end
   (irb):3: warning: private attribute?

There is occasionally a valid reason to make a private accessor/reader/writer, and no harm that I know of.

You can assign to _:

  _ = time <=> @t0

You can wrap it in a function call to make it more obvious what you're doing (I certainly can't tell WHY you're doing that):

  assert(time <=> @t0)

(I think <=> makes more sense in both cases since that's what you really want)

You can write less clever code. I prefer this one, personally. Having it fail on actual usage is a hell of a lot more clear / understandable / debuggable than some quippy line at the top of the method (yes, even with the comment). I shouldn't have to think to decipher your intent.

  raise ArgumentError, "..." unless time.comparable_with? @t0

1) a good exception message saying what went wrong.
2) code that describes what it is doing AND why.
3) no warnings.

we all win.

···

On Jun 26, 2014, at 17:28, Joel VanderWerf <joelvanderwerf@gmail.com> wrote:

On 06/23/2014 04:30 AM, Sylvain Joyeux wrote:

I've been wanting to use -w ... However, I found out that quite a few
high-profile gems out there are not clean under -w (e.g. pry), meaning
that I have a hard time using -w myself.

How many people actually *do* use -w ? Is this really a "best practice"
in the ruby world these days ?

Here's one reason I avoid -w:

class PointOnTimeline
def initialize time
   @t0 = time # might be Time or something else
end

def do_something_with_other_time time
   time < @t0 # fail fast if time and @t0 are not comparable
   return "something"
end
end

The code is generic with respect to the objects used as times. We don't want to assert that they are Time instances, only that they can be compared.

However:

$ ruby -w t.rb
t.rb:7: warning: possibly useless use of < in void context

Yep, we called #< without using the result. So, what to do? Assign it to an unused local? That's a warning. Wrap it in `if ... end`? Ok, no warning, but that looks strange. Is there a missing `then` clause?

% ruby -h
Usage: ruby [switches] [--] [programfile] [arguments]
  -0[octal] specify record separator (\0, if no argument)
  -a autosplit mode with -n or -p (splits $_ into $F)
  -c check syntax only
  -Cdirectory cd to directory before executing your script
  -d set debugging flags (set $DEBUG to true)
  -e 'command' one line of script. Several -e's allowed. Omit [programfile]
  -Eex[:in] specify the default external and internal character encodings
  -Fpattern split() pattern for autosplit (-a)
  -i[extension] edit ARGV files in place (make backup if extension supplied)
  -Idirectory specify $LOAD_PATH directory (may be used more than once)
  -l enable line ending processing
  -n assume 'while gets(); ... end' loop around your script
  -p assume loop like -n but print line also like sed
  -rlibrary require the library before executing your script
  -s enable some switch parsing for switches after script name
  -S look for the script using PATH environment variable
  -T[level=1] turn on tainting checks
  -v print version number, then turn on verbose mode
  -w turn warnings on for your script
  -W[level=2] set warning level; 0=silence, 1=medium, 2=verbose
  -x[directory] strip off text before #!ruby line and perhaps cd to directory
  -h show this message, --help for more info

···

On Jun 23, 2014, at 23:27, Adam Wenham <adamwenham64@gmail.com> wrote:

Hi guys,

what is -w? It's incredible hard to Google :slight_smile:

Thanks Ryan. I have 3 few follow-up questions if you have time:

What does it mean to make your library -w clean?
What are the benefits/drawbacks of doing so?
I would like start contributing to OS, and your warningfree project looks

like something I might be interested in. I might need a little guidance to
get started. (I consider myself to be an advanced beginner/competent
Rubyist (http://en.wikipedia.org/wiki/Dreyfus_model_of_skill_acquisition\).) Do
you think this might be something I could help out with?

Thanks in advance for your advice.
Adam

···

On 24 June 2014 08:01, Ryan Davis <ryand-ruby@zenspider.com> wrote:

On Jun 23, 2014, at 23:27, Adam Wenham <adamwenham64@gmail.com> wrote:

> Hi guys,
>
> what is -w? It's incredible hard to Google :slight_smile:
>

% ruby -h
Usage: ruby [switches] [--] [programfile] [arguments]
  -0[octal] specify record separator (\0, if no argument)
  -a autosplit mode with -n or -p (splits $_ into $F)
  -c check syntax only
  -Cdirectory cd to directory before executing your script
  -d set debugging flags (set $DEBUG to true)
  -e 'command' one line of script. Several -e's allowed. Omit
[programfile]
  -Eex[:in] specify the default external and internal character
encodings
  -Fpattern split() pattern for autosplit (-a)
  -i[extension] edit ARGV files in place (make backup if extension
supplied)
  -Idirectory specify $LOAD_PATH directory (may be used more than once)
  -l enable line ending processing
  -n assume 'while gets(); ... end' loop around your script
  -p assume loop like -n but print line also like sed
  -rlibrary require the library before executing your script
  -s enable some switch parsing for switches after script name
  -S look for the script using PATH environment variable
  -T[level=1] turn on tainting checks
  -v print version number, then turn on verbose mode
  -w turn warnings on for your script
  -W[level=2] set warning level; 0=silence, 1=medium, 2=verbose
  -x[directory] strip off text before #!ruby line and perhaps cd to
directory
  -h show this message, --help for more info

--
== If you're doing it alone, you're probably doing it wrong ==

I wondered what it would be like if Ruby had something like C++ #pragma directives to enable/disable specific warnings. I imagine library writer A suppressing one warning, and library writer B suppressing another. Now I use library A and B, and now get two warnings suppressed for _my code_, warnings that I wanted to see. This kind of effect makes me think that, to be of any use, a #pragma-like ability would have to be lexically scoped ("this file has these pragmas"). But that just seems ugly. Imagine every file in some library having this block of pragmas at the top. *Every file*. So that doesn't seem like a win.

I think the best approach is to not rely upon "-w" at all, but use a lint-like tool. I think there are some of these out there for Ruby. You pick the lint you like, you configure its warnings to your liking, and you run it. Since lint-like tools are not semantically scoped, but file-scoped, you don't have to worry about your lint tool bothering you with warnings about some library that your program is using. You can put it in your gem's rakefile, or in a git commit hook. This, I think, is the winning approach. Do not burden each Ruby implementation with knowledge of policies and opinions which are (1) not universal, and (2) subject to change as personal and community standards evolve over time. Instead, decentralize warnings, putting them in separate tools.

- Wayne Conrad

···

On 06/25/2014 04:53 AM, Sylvain Joyeux wrote:

This is a bit my problem as well. Maybe there is a need to be able to turn some warnings on or off depending on the application (as most compilers allow these days).

because that's only the reader.

···

On Jun 25, 2014, at 5:46, Steve Tooke <steve.tooke@gmail.com> wrote:

If you definitely want a private accessor/reader/writer, you can tell ruby like this:

class Foo
  attr_accessor :bar
  private :bar
end

... and that is warning clean.

Excellent point! I don't know what I was smoking. I just checked, and no warning is issued for a private attr_reader.

Wayne Conrad

···

On 06/25/2014 02:20 PM, Ryan Davis wrote:

On Jun 25, 2014, at 4:44, Wayne Conrad <kf7qga@gmail.com> wrote:

There is occasionally a valid reason to make a private accessor/reader/writer, and no harm that I know of.

Not true. You can't call a private writer (without send) because private means you can't use a receiver.

Hmm; that doesn't seem to be the case at least in 2.1.1:

    class Foo
      private
      attr_accessor :bar

      public
      def set_bar(b)
        self.bar = b
      end

      def get_bar
        bar
      end
    end

    f = Foo.new
    f.set_bar(42) # no warning except under -w
    puts f.get_bar # outputs 42

Perhaps I misunderstand you, and you meant that using self as a receiver
for a private method merely triggers a warning under -w.

···

On Wed, Jun 25, 2014, Ryan Davis wrote:

On Jun 25, 2014, at 4:44, Wayne Conrad <kf7qga@gmail.com> wrote:

> On 06/23/2014 04:30 AM, Sylvain Joyeux wrote:
>>
>> How many people actually *do* use -w ? Is this really a "best practice" in the ruby world these days ?
>>
> I do not attempt to write "-w clean" code, or even use `-w`, because:
>
> wayne@mercury:~$ irb -w
> 2.1.1 :001 > class Foo
> 2.1.1 :002?> private
> 2.1.1 :003?> attr_accessor :bar
> 2.1.1 :004?> end
> (irb):3: warning: private attribute?
>
> There is occasionally a valid reason to make a private accessor/reader/writer, and no harm that I know of.

Not true. You can't call a private writer (without send) because private means you can't use a receiver.

...

class PointOnTimeline
  def initialize time
    @t0 = time # might be Time or something else
  end

  def do_something_with_other_time time
    time < @t0 # fail fast if time and @t0 are not comparable
    return "something"
  end
end

...

   assert(time <=> @t0)

That's not bad at all. Spaceship returns truthy, unless incomparable, and this will work for any Comparable.

···

On 06/26/2014 05:39 PM, Ryan Davis wrote:

On Jun 26, 2014, at 17:28, Joel VanderWerf <joelvanderwerf@gmail.com> wrote:

Thanks Ryan. I have 3 few follow-up questions if you have time:
> What does it mean to make your library -w clean?

A number of specific things:

+ Methods aren't redefined accidentally.
+ Variables are initialized before they're used.
+ Variables (all sorts) are used at least once after initialization.
+ Variables (all sorts) don't shadow outer variables.
+ Regexps have clean ranges & escapes.
+ Format strings match their args.

There might be more. I'm tired and don't remember.

> What are the benefits/drawbacks of doing so?

The benefits should be pretty clear:

+ I can use your library in my app and my tests will still run clean with -w (which means MY code can be -w). IOW, nobody is pissing in the public pool.

+ You get certain assurances about a library that you know is warning free: instance variables are assigned before being used, block variables aren't shadowing, code has been cleaned up and/or typos are fixed, etc... IOW, the author(s) cared about and paid attention to the design and quality of their code.

+ A warning-free library is a better ruby citizen.

The drawbacks?

Honestly, I don't care. I'll pay the price to put out cleaner code. I think it is well worth it.

Some have claimed that there are speed benefits to writing sloppier code. I have yet to see anything truly rigorous and definitive.

> I would like start contributing to OS, and your warningfree project looks like something I might be interested in. I might need a little guidance to get started. (I consider myself to be an advanced beginner/competent Rubyist (http://en.wikipedia.org/wiki/Dreyfus_model_of_skill_acquisition\).) Do you think this might be something I could help out with?

Fixing up messy libraries is pretty tedious and doesn't teach much as a skill (other than what not to do). It does provide the ability to read through some popular libraries and study their guts... So that really depends on what you're looking for.

···

On Jun 24, 2014, at 0:37, Adam Wenham <adamwenham64@gmail.com> wrote:

Thanks Ryan, that actually sounds pretty interesting to me. I don't really
know where to start though, so how could I get involved?

···

On 24 June 2014 10:17, Ryan Davis <ryand-ruby@zenspider.com> wrote:

On Jun 24, 2014, at 0:37, Adam Wenham <adamwenham64@gmail.com> wrote:

> Thanks Ryan. I have 3 few follow-up questions if you have time:
> > What does it mean to make your library -w clean?

A number of specific things:

+ Methods aren't redefined accidentally.
+ Variables are initialized before they're used.
+ Variables (all sorts) are used at least once after initialization.
+ Variables (all sorts) don't shadow outer variables.
+ Regexps have clean ranges & escapes.
+ Format strings match their args.

There might be more. I'm tired and don't remember.

> > What are the benefits/drawbacks of doing so?

The benefits should be pretty clear:

+ I can use your library in my app and my tests will still run clean with
-w (which means MY code can be -w). IOW, nobody is pissing in the public
pool.

+ You get certain assurances about a library that you know is warning
free: instance variables are assigned before being used, block variables
aren't shadowing, code has been cleaned up and/or typos are fixed, etc...
IOW, the author(s) cared about and paid attention to the design and quality
of their code.

+ A warning-free library is a better ruby citizen.

The drawbacks?

Honestly, I don't care. I'll pay the price to put out cleaner code. I
think it is well worth it.

Some have claimed that there are speed benefits to writing sloppier code.
I have yet to see anything truly rigorous and definitive.

> > I would like start contributing to OS, and your warningfree project
looks like something I might be interested in. I might need a little
guidance to get started. (I consider myself to be an advanced
beginner/competent Rubyist (
http://en.wikipedia.org/wiki/Dreyfus_model_of_skill_acquisition\).) Do you
think this might be something I could help out with?

Fixing up messy libraries is pretty tedious and doesn't teach much as a
skill (other than what not to do). It does provide the ability to read
through some popular libraries and study their guts... So that really
depends on what you're looking for.

--
== If you're doing it alone, you're probably doing it wrong ==

True!

But this also runs without warnings:

class Foo
  attr_accessor :x

  private :x, :x=
end

It's a good point that a private writer is useless, but I think Ruby is
doing the check for private when you create the attr [1].

[1]:

···

On Wed, Jun 25, 2014 at 10:21 PM, Ryan Davis <ryand-ruby@zenspider.com> wrote:

On Jun 25, 2014, at 5:46, Steve Tooke <steve.tooke@gmail.com> wrote:

> If you definitely want a private accessor/reader/writer, you can tell
ruby like this:
>
> class Foo
> attr_accessor :bar
> private :bar
> end
>
> ... and that is warning clean.

because that's only the reader.

--
/tooky

Oh that's interesting, I would expect you to get a NoMethodError for
`self.bar = b` - I've created a gist[1] based on this[2] post by Jamis
Buck, that shows what I thought should happen. For some reason method
visibility seems different with the = operator.

[1]: visibility_test.rb · GitHub
[2]: Buckblog: Method visibility in Ruby

···

On Thu, Jun 26, 2014 at 7:14 AM, Eric Christopherson <echristopherson@gmail.com> wrote:

On Wed, Jun 25, 2014, Ryan Davis wrote:
>
> You can't call a private writer (without send) because private means you can't use a receiver.

Hmm; that doesn't seem to be the case at least in 2.1.1:

    class Foo
      private
      attr_accessor :bar

      public
      def set_bar(b)
        self.bar = b
      end

      def get_bar
        bar
      end
    end

    f = Foo.new
    f.set_bar(42) # no warning except under -w
    puts f.get_bar # outputs 42

Perhaps I misunderstand you, and you meant that using self as a receiver
for a private method merely triggers a warning under -w.

--
/tooky