Forum: Ruby Fwd: Is anyone using -w ?

934180817a3765d132193a5428f99051?d=identicon&s=25 Sylvain Joyeux (Guest)
on 2014-06-23 13:31
(Received via mailing list)
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
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2014-06-23 23:06
(Received via mailing list)
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. :/

We started https://github.com/warningfree to try to address this, but we
could really use contributions (Sadly, there are way more of them than
there are of us).
919809f815e7501a83848e34942a3b72?d=identicon&s=25 Adam Wenham (Guest)
on 2014-06-24 08:28
(Received via mailing list)
Hi guys,

what is -w? It's incredible hard to Google :)
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2014-06-24 09:02
(Received via mailing list)
On Jun 23, 2014, at 23:27, Adam Wenham <adamwenham64@gmail.com> wrote:

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

% 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
919809f815e7501a83848e34942a3b72?d=identicon&s=25 Adam Wenham (Guest)
on 2014-06-24 09:37
(Received via mailing list)
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_skil...).) Do
you think this might be something I could help out with?

Thanks in advance for your advice.
Adam
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2014-06-24 11:18
(Received via mailing list)
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_skil...).) 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.
919809f815e7501a83848e34942a3b72?d=identicon&s=25 Adam Wenham (Guest)
on 2014-06-25 09:02
(Received via mailing list)
Thanks Ryan, that actually sounds pretty interesting to me. I don't
really
know where to start though, so how could I get involved?
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2014-06-25 10:21
(Received via mailing list)
On Jun 25, 2014, at 0:01, 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?

Run your tests with -w. Do something when they don't run clean. Start
with simple pull requests.
Fa719143f8b0a84e85975806c1deec44?d=identicon&s=25 Wayne Conrad (wayneconrad)
on 2014-06-25 13:45
(Received via mailing list)
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
934180817a3765d132193a5428f99051?d=identicon&s=25 Sylvain Joyeux (Guest)
on 2014-06-25 13:54
(Received via mailing list)
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>:
Ee7052b87b82257740f232a958c3d49e?d=identicon&s=25 Steve Tooke (stevetooke)
on 2014-06-25 14:47
(Received via mailing list)
On Wed, Jun 25, 2014 at 12:44 PM, Wayne Conrad <kf7qga@gmail.com> wrote:

>     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.
Fa719143f8b0a84e85975806c1deec44?d=identicon&s=25 Wayne Conrad (wayneconrad)
on 2014-06-25 14:51
(Received via mailing list)
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).
>
>
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
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2014-06-25 23:21
(Received via mailing list)
On Jun 25, 2014, at 4:44, Wayne Conrad <kf7qga@gmail.com> wrote:

>    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.
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2014-06-25 23:22
(Received via mailing list)
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.
Fa719143f8b0a84e85975806c1deec44?d=identicon&s=25 Wayne Conrad (wayneconrad)
on 2014-06-25 23:25
(Received via mailing list)
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.
>
>
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
Ee7052b87b82257740f232a958c3d49e?d=identicon&s=25 Steve Tooke (stevetooke)
on 2014-06-25 23:46
(Received via mailing list)
On Wed, Jun 25, 2014 at 10:21 PM, Ryan Davis <ryand-ruby@zenspider.com>
wrote:

> >
> > ... and that is warning clean.
>
> because that's only the reader.
>
>
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]:
https://github.com/ruby/ruby/blob/e99ee55abcdbd305...
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2014-06-26 00:19
Ryan Davis wrote in post #1150753:
> On Jun 25, 2014, at 4:44, Wayne Conrad <kf7qga@gmail.com> wrote:
>
>>    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 Dog
  attr_reader :x

  def x=(str)
    @x = str.capitalize
  end

  private :x=

  def do_stuff
    self.x = 'hello'
  end
end

d = Dog.new
d.do_stuff
puts d.x
d.x = "Goodbye"


--output:--
Hello
1.rb:18:in `<main>': private method `x=' called for
#<Dog:0x00000100909740 @x="Hello"> (NoMethodError)
Abdb670e1c130f96f947a94d03c02efa?d=identicon&s=25 Eric Christopherson (echristopherson)
on 2014-06-26 08:14
(Received via mailing list)
On Wed, Jun 25, 2014, Ryan Davis wrote:
> >    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.
>
>

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.
Ee7052b87b82257740f232a958c3d49e?d=identicon&s=25 Steve Tooke (stevetooke)
on 2014-06-26 10:05
(Received via mailing list)
On Thu, Jun 26, 2014 at 7:14 AM, Eric Christopherson
<echristopherson@gmail.com> wrote:
>
>     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.


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]: https://gist.github.com/tooky/5673afd4599b02aef0eb
[2]: http://weblog.jamisbuck.org/2007/2/23/method-visib...
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2014-06-26 11:59
(Received via mailing list)
On Thu, Jun 26, 2014 at 10:04 AM, Steve Tooke <steve.tooke@gmail.com>
wrote:
>>       private
>>     end
> `self.bar = b`
Why would you?  bar= _is_ defined.

Btw. 1.9.3 also did not choke with this.

Kind regards

robert
Ee7052b87b82257740f232a958c3d49e?d=identicon&s=25 Steve Tooke (stevetooke)
on 2014-06-26 13:03
(Received via mailing list)
On Thu, Jun 26, 2014 at 10:58 AM, Robert Klemme
<shortcutter@googlemail.com> wrote:
>
> Why would you?  bar= _is_ defined.

That's how ruby responds when you try to call a private method using
the explicit self receiver:

class Foo
  def use_bar_explicit_self
    self.bar
  end

  private
  def bar
    'bar'
  end
end

foo = Foo.new
foo.use_bar_explicit_self

# ~> -:3:in `use_bar_explicit_self': private method `bar' called for
#<Foo:0x007fe9c982cd68> (NoMethodError)
# ~>     from -:13:in `<main>'

This works in exactly the same way when you pass a variable to a method:

class Foo
  def use_bar_explicit_self(var)
    self.bar(var)
  end

  private
  def bar(var)
    'bar'
  end
end

foo = Foo.new
foo.use_bar_explicit_self(:a_var)

# ~> -:3:in `use_bar_explicit_self': private method `bar' called for
#<Foo:0x007fdfea828a30> (NoMethodError)
# ~>     from -:13:in `<main>'

But the same rules don't seem to follow when using the `=` operator

class Foo
  def value
    @bar
  end

  def use_bar_explicit_self=(var)
    self.bar=(var)
  end

  private
  def bar=(var)
    @bar = var
  end
end

foo = Foo.new
foo.use_bar_explicit_self = :a_var
foo.value # => :a_var

I'm guessing that the `=` operator essentially results in doing a send
to `"#{method_name}=` and therefore is bypassing ruby's usual method
visibility rules.

> Btw. 1.9.3 also did not choke with this.

Yep - also 1.8.7 and rubinius 2.2.2 - so I guess this is expected
behaviour. It just surprised _me_ :)
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2014-06-26 14:23
(Received via mailing list)
On Thu, Jun 26, 2014 at 1:02 PM, Steve Tooke <steve.tooke@gmail.com>
wrote:
> On Thu, Jun 26, 2014 at 10:58 AM, Robert Klemme
> <shortcutter@googlemail.com> wrote:
>>
>> Why would you?  bar= _is_ defined.
>
> That's how ruby responds when you try to call a private method using
> the explicit self receiver:

Oh right.  I thought it was another error.  I just looked at the
message. I'm sorry.

> But the same rules don't seem to follow when using the `=` operator

Right.  Apparently that is handled specially.  That makes sense if you
consider that there is no other way to invoke assignment methods other
than prefixing with "self.".

> I'm guessing that the `=` operator essentially results in doing a send
> to `"#{method_name}=` and therefore is bypassing ruby's usual method
> visibility rules.

I don't think it necessarily needs to go through #send to allow this
to happen.  There just needs to be a different call chain for things
like "self.{identifier}={expression}".  But we can test:

$ ruby xx.rb
42
SEND
43
$ cat xx.rb
class Foo
  def send(*x) puts "SEND"; super end

  private
  attr_accessor :bar

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

  def set_bar_2(b)
    send("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
f.set_bar_2(43)
puts f.get_bar # outputs 43


Voilá!


>> Btw. 1.9.3 also did not choke with this.
>
> Yep - also 1.8.7 and rubinius 2.2.2 - so I guess this is expected
> behaviour. It just surprised _me_ :)

I also was not aware. Learn something new every day. :-)

Kind regards

robert
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2014-06-26 17:31
> Yep - also 1.8.7 and rubinius 2.2.2 - so I guess this is expected
> behaviour. It just surprised _me_ :)

Yes.  It arises because of the need to differentiate between local
variable assignment and the call to a setter:

class Dog
  def x=(val)
    @x = val.capitalize
  end

  def do_stuff
     x = 10  #local variable assignment
     self.x = "hello"  #call to setter
     puts x
     puts @x
  end

end

Dog.new.do_stuff

--output:--
10
Hello

Now if you make the setter private, you can't write:

  def do_stuff
     ...
     x = 'hello'
     ...
  end

and expect ruby to interpret that as:

   self.x=('hello')

because that assignment once again creates a local variable.  Hence, the
exception to the 'no explicit receivers for private methods' rule.
David Black might have discussed this in "The Well Grounded Rubyist".
David?
0e6ac58dab6125c1cd2e7ac645076b6f?d=identicon&s=25 Joel VanderWerf (Guest)
on 2014-06-27 02:29
(Received via mailing list)
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?

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.
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2014-06-27 02:40
(Received via mailing list)
On Jun 26, 2014, at 17:28, Joel VanderWerf <joelvanderwerf@gmail.com>
wrote:

> class PointOnTimeline
> 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?

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.
0e6ac58dab6125c1cd2e7ac645076b6f?d=identicon&s=25 Joel VanderWerf (Guest)
on 2014-06-27 06:18
(Received via mailing list)
On 06/26/2014 05:39 PM, Ryan Davis wrote:
>
> On Jun 26, 2014, at 17:28, Joel VanderWerf <joelvanderwerf@gmail.com> wrote:
...
>> 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.
14b5582046b4e7b24ab69b7886a35868?d=identicon&s=25 Joel Pearson (virtuoso)
on 2014-06-29 19:55
Adam Wenham wrote in post #1150594:
> Hi guys,
>
> what is -w? It's incredible hard to Google :)

FYI, if you're having trouble Googling special symbols you can try
http://www.symbolhound.com/
B18389c80879bd863a4cab2e8c3a4fb8?d=identicon&s=25 Adi Ali (adil_83)
on 2014-06-30 09:22
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.