ruby picture

RCR 233: pathname literal and builtin pathname class

Submitted by akr (Thu Mar 25 19:03:45 UTC 2004)

Abstract

Introduce %-literal for pathnames and make Pathname class builtin.

Problem

Ruby uses a string as a pathname. This makes difficult to use it polymorphic.

For example, A pathname and URI are both openable. They should be polymorphic and they should have open method in duck type sense. But open method for String class is not appropriate.

Since Ruby (and various scripting language) uses files frequently, pathnames should be able to describe succinctly. But Pathname.new('...') is too long to use it frequently.

Proposal

Analysis

Currently Pathname class is implemented in pathname.rb. It must be builtin to introduce %-literal for pathname.

If we have pathname builtin, we can obsolete most of class methods in File and Dir.

Implementation

pathname.rb

%p'...' is not available, though.

ruby picture
Comments Current voting

This change would affect file related programming style in Ruby too much, I'm afraid. Our familiar style using "open" will no longer be

Instead of making this change, how about the idea of that Kernel#open calls some callback method (e.g. "to_open") if it's available for the first argument?

  def open(arg, *rest)
    if defined? arg.to_open
      return arg.to_open(*rest)
    end
    ...
   end

By this change, Kernel#open can handle URL, Pathname, etc.

--matz.


to_open is good idea to preserve the style for open. But it cannot treat other kind of polymorphic operation: mkdir, rename, delete, etc. Since introducing to_mkdir, to_rename, to_delete, etc is ugly, the conversion and the actual operations may be splitted:

  def open(arg, *rest)
    if defined? arg.to_filename
      return arg.to_filename.open(*rest)
    end
    ...
  end  def Dir.mkdir(arg, *rest)
    if defined? arg.to_filename
      return arg.to_filename.mkdir(*rest)
    end
    ...
  end  def File.read(arg, *rest)
    if defined? arg.to_filename
      return arg.to_filename.read(*rest)
    end
    ...
  end  ...  class String; def to_filename() Pathname.new(self) end end
  class Pathname; def to_filename() self end end
  class URI::HTTP; def to_filename() self end end
  class URI::FTP; def to_filename() self end end

This makes possible to Dir.mkdir(uri), File.read(uri). But it may be confusing because URI::HTTP and URI::FTP is not implemented by Dir or File.

So I don't want to encourage polymorphic Dir.mkdir, etc. I want to encourage file operations in OOP style over class methods on File and Dir.

The encouragement means that the notation in OOP style should be shorter than current notation in most cases. Unfortunately, without %p literal, Dir.xxx and File.xxx are the shortest notation:

  %p'...'.mkdir
  Dir.mkdir('...')
  '...'.to_open.mkdir
  '...'.to_filename.mkdir  %p'...'.read
  File.read('...')
  '...'.to_open.read
  '...'.to_filename.read

So, %p'...' is needed to encourage the OOP style.

This is why I proposed %p literal, instead of extending open-uri to treat File.read etc.

--akr


I believe file system operation has some kind of procedural mental model, so that most of use prefer:

  mkdir path

to

  path.mkdir

This is the reason why I'm not attracted by the idea of pathname literals. I prefer the idea of VFS (Virtual File System) module with proper set of callback methods, for example:

  module VFS
    def mkdir(path, *args)
       if defined? path.create_directory
          return path.create_directory(*args)
       end
       process "mkdir" with string path.
    end
  end

to keep procedural mental model.

-- matz.


Strongly opposed 0
Opposed 3
Neutral 2
In favor 0
Strongly advocate 0
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .