Check if no arguments passed

arguments, ruby

Solution

There are three ways in general use. One way is to use the default value to set another variable indicating whether or not the default value was evaluated:

def f(p1 = (no_argument_passed = true; nil))
  'no arguments passed' if no_argument_passed
end

f      # => 'no arguments passed'
f(nil) # => nil

The second way is to use some object that is only known inside the method as default value, so that it is impossible for an outsider to pass that object in:

-> {
  undefined = BasicObject.new
  define_method(:f) do |p1 = undefined|
    'no arguments passed' if undefined.equal?(p1)
  end
}.()

f      # => 'no arguments passed'
f(nil) # => nil

Of these two, the first one is more idiomatic. The second one (actually, a variation of it) is used inside Rubinius, but I have never encountered it anywhere else.

A third solution would be to take a variable number of arguments using a splat:

def f(*ps)
  num_args = ps.size
  raise ArgumentError, "wrong number of arguments (#{num_args} for 0..1)" if num_args > 1
  'no arguments passed' if num_args.zero?
end

f      # => 'no arguments passed'
f(nil) # => nil

Note that this requires you to re-implement Ruby's arity checking by hand. (And we still haven't gotten it right, because this raises the exception inside the method, whereas Ruby would raise it at the call site.) It also requires you to manually document your method signature because automated documentation generators such as RDoc or YARD will infer an arbitrary number of parameters instead of a single optional one.

Problem

Here's some code: ``` $ cat 1.rb #!/usr/bin/env ruby def f p1 = nil unless p1 # TODO puts 'no parameters passed' end end f f nil $ ./1.rb no parameters passed no parameters passed ``` The question is, is there a way to distinguish between no arguments and one `nil` argument passed? UPD I decided to add a use case in `javascript` to make things hopefully clearer: ``` someProp: function(value) { if (arguments.length) { this._someProp = value; } return this._someProp; } ```

Original source