ruby picture

RCR 310: Tighter Support for Symbolic Parameters

Submitted by transami (Wed Aug 10 01:18:48 UTC 2005)

Abstract

Symbols often make good parameters for controlling variant behavior within a method. There are some minor limitations in Ruby's syntax that could be improved to make symbolic parameters even more convenient to use.

Problem

When creating convenience methods, among other things, I have often come across a need to supply a symbol flag as the first parameter of the method to guide the method in its proccessing. Here's one potential example, using Numeric for information measure:

  class Numeric
    def kilo(type=nil)
      case type
      when :bit, bits
        self * 1024
      when :byte, :bytes
        self * 1024 * 8
      else
        self * 1000
      end
    end
  end

This works great, as one can then type things like:

  1.kilo       #=> 1000
  1.kilo:bit   #=> 1024
  1.kilo:byte  #=> 8192

But a problem arises when using this in a method chain:

  1.kilo:byte.between?(1,1000)
  #=> NoMethodError: undefined method `between?' for :byte:Symbol

This error renders an otherwise very useful notation nearly useless.

Proposal

There are two possible solutions. The more elborate of the two is the creation of a new flag-parameters system, like that for *args and **keys. The exact notation yet to be determined, but a pseudo:

  def kilo(*:flags)
    case flags[0]
    ...
  end

Methods could then have multiple flags. They could also be made more readable by allowing a space between the flags and the remaining parameters. Eg.

  def foo(::flags,x)
    flags.collect { |f|
      "#{f}#{x}"
    end
  end
  foo:bar:boo "!!!"  #=> ["bar!!!","boo!!!"]

The alternative proposal is just to allow an initial symbol parameter which is pressed directly up against the method name to be tightly bound to it. So,

  1.kilo:bytes.even?   #=> true
  1.kilo :bytes.even?  #=> ERROR

Analysis

The change simply makes for additional convenience in the creation and use of methods using symbolic prameters. The two possible solutions I propose, as far as can tell are really the only ones possible.

Implementation

At the discretion of the Ruby core developers.
ruby picture
Comments Current voting
Hi --

I'm not getting why the argument's being a symbol is grounds for this:

   1.kilo:bits.between?(1,1000)

being automatically parsed like this:

   (1.kilo:bits).between?(1,1000)

or this:

   1.kilo(:bits).between?(1,1000)

I can see, of course, that it saves on parentheses. But it would introduce a major exception to the way method calls are parsed, based on the class of the argument (assuming you're not suggesting that this extend generally to all method calls). I'm not seeing a need that would justify that.

David Black


David--

Yet, presently it is the later parsing. I realize that the minor alternate solution is dependent on the type of the first prarmeter --and thus would apply to all methods. But us that really that major a change. There is already a difference with regards to the binding (is that the word?) of blocks when using { vs. do. Would it not be simple enough to set a flag if the 1st argument butted up againt the method name?

trans.


Sorry, "But us that really that major a change." should read "But is that really such a major change?"


I see no need for this, where we can type

  1.kilo_bytes

or even

  1.kilo.bytes

works pretty well.

-matz.


Matz,

That's exactly the problem!

  def kilo ; self * 1024 ; end

or shoud it be SI

  def kilo ; self * 1000 ; end

And kilo_bytes means A LOT more methods:

  mega_bytes, mega_byte, giga_bytes, giga_bits, milli_seconds, micro_seconds, ... ad infinitum.

trans.


mega:bytes etc. require internal branching anyway. If infinitum happens with mega_bytes, it would happen with mega:bytes as well.

you can even generate combination methods like mega_bytes using metaprogramming feature.

besides that, I'd rather preserve colons inside the identifiers for some other purpose, such as namespace thingy, though I have no concrete idea yet.

-matz.


trans:

  kilo should always be 1000. If you want to refer to 1024, you need to use the SI prefix kibi. A kilobyte is 1000 bytes; a kibibyte is 1024 bytes. (1 Kb = 1000 b; 1 Kib = 1024 b). Aside from that, I quite agree with matz.

-austin


austin,

  While you and I know of kibi, the world at large isn't so formal or even aware.


We learned in school here that kilo = 1000.

I believe we should stick to kilo meaning 1000, else more confusion is spread. The 1024 of it in computer area is a bad idea to ever associate kilo with it, it leads to unneeded confusion. If people would use kibibyte more, others probably would adapt it too.


Strongly opposed 6
Opposed 1
Neutral 0
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 .