Comment on this RCR (edit wiki page) | RCRchive home

RCR 250: absolute __FILE__

submitted by neoneye on Sat May 01 2004 03:01:30 AM -0700

Status: pending


Abstract

Make __FILE__ an absolute path. Currently __FILE__ reflects the path which the program were invoked with. It's always easy get a relative path from an absolute one, but not the other way!

Problem

__FILE__ is vulnerable to chdir. Many people make global variables containing the expanded path, before they start doing file manipulation. Thats kludgy, however if they didn't do anything they would have a fragile program.

Proposal

Make __FILE__ robust, so that one can rely on that it always contains a absolute path.

Analysis

This will break the widespread 'if $0 == __FILE__' ideom, see [] for discussion of $0 and __FILE__. It will for sure break many other places, which assumes the old concept.

Implementation

I don't know what to write here.

Vote for this RCR

Strongly opposed [1]
Opposed [1]
Neutral [1]
In favor [0]
Strongly advocate [0]

Change the status of this RCR to:

accepted

rejected

withdrawn


I'm one of the people who does write code that stores the expanded path (hopefully) before another library calls chdir. I do find this to be a kludge, and I wish there were a better way.

However, breaking existing code is not an acceptable solution, especially when there are alternatives. One such alternative is to use a different variable, perhaps__EXPANDED_FILE__.

Also, regarding the if $0 == __FILE__' idiom, this idiom tends to confuse newcomers to Ruby and imo it should be done away with in favor of something a little cleaner. Something I've been playing with:

  require 'caller_helpers'
  require 'realpath'  def main
    file, lineno, method = parse_caller(caller[0])
    caller_file = caller_file_pathname(file)
    if realpath(caller_file) == realpath($0) then
      yield
    end
  end

(for this to work you will need caller_helpers.rb and realpath.rb from http://www.rubystuff.org/treasures/RubyTreasures-0.5/lib/hacks/). Now I can write:

  require 'main'
  #  
  main do
    puts "This is only executed if the file is run from the command line, not if"
    puts "it is required from another script."
  end

I think the implementation of the main() method is even kludgier than the if $0 == __FILE__' idiom, but the implementation could be replaced if a new version of the interpreter had support for implementing it a better way. The implementation given here can then be used only on older versions of the interpreter, if a program or library needs to be backward-compatible.

I haven't bothered to submit an RCR for this, because I don't yet know if I like the name of the method (my co-workers have had to get me to explain what the code does, which is a hint that it's not sufficiently self-documenting).

-- Paul Brannan


Two thoughts:
- changing __FILE__ will break a lot of code
- __FILE__ is ugly anyway.

Why not just abandon __FILE__ and stick the stuff in a module? This was suggested by someone else on ruby-talk:

System.current_file     # same as __FILE__
System.current_filepath # expanded version

Many other useful methods/constants could be stuck in the System module; and we'd be another step of the way towards getting rid of Ruby's "Perl compatibility layer". :)

--Mark Hubbart


Add comments here


Back to RCRchive.


RCR Submission page and RCRchive powered by Ruby, Apache, RuWiki (modified), and RubLog