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;
}
You can test it this way: int main(int argc, char *argv[]) { if (argc < 2) { printf("error: missing command line arguments\n"); return 1; } ... }
Running this code in Pytest gives an error def two_fer(name=None): if name == 'Alice' or name == 'Bob': return ('One for ' + str(name) + ", one for me.") elif name == False: return ('One for you, one for me. ')
You can get the number of arguments from the special parameter $# . Value of 0 means "no arguments". $# is read-only. When used in conjunction with shift for argument processing, the special parameter $# is decremented each time Bash Builtin shift is executed.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With