Hi!
What’s the best way of checking if an argument has been given or not?
That is, what’s the best way of achieving
class A
ArgumentMissing = Object.new.freeze
def b(c = ArgumentMissing)
if ArgumentMissing.equal? c
puts 'no argument was given'
else
puts c
end
end
end
A.new.b # => no argument was given
A.new.b 1 # => 1
? I remember seeing something that didn’t require a constant like
this, but I can’t seem to find it. (Note: I don’t want to use nil for
this particular case. I would preferably use a value that is
inaccessible outside of A.)
...probably not the *best* way, but this works:
class A
def initialize(arg = "NO ARGUMENT")
if arg == "NO ARGUMENT"
puts "no argument given"
else
puts arg
end
end
end
A.new
A.new("foo")
=> no argument given
=> foo
- j
···
--
Posted via http://www.ruby-forum.com/ .
Perhaps I wasn’t clear enough. It shouldn’t be possible for the
caller to actually pass in an argument that will match.
A.new('NO ARGUMENT') # => no argument given
···
On Fri, Oct 14, 2011 at 15:07, jake kaiden <jakekaiden@yahoo.com > wrote:
...probably not the *best* way, but this works:
class A
def initialize(arg = "NO ARGUMENT")
if arg == "NO ARGUMENT"
puts "no argument given"
else
puts arg
end
end
end
11142
(-- --)
14 October 2011 13:29
4
You can use this syntax, too. "args" becomes an array of all arguments given.
def foo *args
if args.length==0
puts 'no argument was given'
else
puts args[0]
end
end
If you only allow one argument, you should do some checking whether
there are too many.
-- Matma Rex
Your suggestion is valid. though it seems I underspecified my question
in yet another way. Until Ruby gets a rb_scan_args equivalent, I’d
rather not complicate my argument processing unnecessarily by
destructuring an argument array by hand.
···
On Fri, Oct 14, 2011 at 15:29, Bartosz Dziewoński <matma.rex@gmail.com > wrote:
You can use this syntax, too. "args" becomes an array of all arguments given.
def foo *args
if args.length==0
puts 'no argument was given'
else
puts args[0]
end
end
If you only allow one argument, you should do some checking whether
there are too many.
Chris6
(Chris)
14 October 2011 13:51
6
You could do it as a wrapper:
def foo_argchek *args
if args.len == 0
"no args given"
else
real_foo(*args)
end
end
def real_foo(arg1, arg2)
#do stuff
end
How is this a solution (to anything)?
One can, of course, use define_method (in 1.9), but it’s not ideal, as
you can’t pass a block to A#a in that case.
class A
missing = Object.new
define_method :a do |b = missing|
if b == missing
puts 'no argument given'
else
puts b
end
end
end
A.new.a
A.new.a 1
···
On Fri, Oct 14, 2011 at 15:51, Chris Hulan <chris.hulan@gmail.com > wrote:
You could do it as a wrapper:
def foo_argchek *args
if args.len == 0
"no args given"
else
real_foo(*args)
end
end
def real_foo(arg1, arg2)
#do stuff
end
Chris6
(Chris)
14 October 2011 14:15
8
You said you didn't want to manually do it, this lets the interpreter
do it for you.
Maybe a more realistic example would clarify why having to do some
work to achieve this seems
too much effort?
Hmm, if you really don't want to use the splat *args, you could create a
new instance of A and extend it with a #missing ? method, and pass that
instance as the default value for the method. That way, the instance
won't be available across classes and you can just check if the argument
responds_to :missing?
class A
missing_arg = new
class << missing_arg
def missing?
true
end
end
def a(arg=missing_arg)
...
end
end
Hope this helps,
-Luke
···
--
Posted via http://www.ruby-forum.com/ .
luke gruber [2011-10-14 17:15]:
That way, the instance won't be available across classes and you
can just check if the argument responds_to :missing?
or you can just do this:
class A
def b(c = d = true) # or some other truthy value
if d
puts 'no argument was given'
else
puts c
end
end
end
can't remember where i first saw it, but it works perfectly
cheers
jens
What's the situation this code is going to be used in?
What's wrong with rescuing?
def foo(a, b); [a, b]; end
begin; foo(); rescue(ArgumentError); "More, please."; end
=> "More, please."
Yes, of course! That’s the trick I saw too; checking if the optional
argument’s default value was evaluated.
Here’s a more general solution that allows you to set d to a value
independent of the desired default value for the argument:
def m(a = (d = true; nil))
# d will be true if argument a wasn’t specified
end
One easily forgets how expressive Ruby can be. Or how easily it is to abuse it.
Thanks!
···
On Fri, Oct 14, 2011 at 17:31, Jens Wille <jens.wille@uni-koeln.de > wrote:
class A
def b(c = d = true) # or some other truthy value
if d
puts 'no argument was given'
else
puts c
end
end
end
can't remember where i first saw it, but it works perfectly
7rans
(7rans)
14 October 2011 16:13
13
That's pretty cleaver, although it reads perhaps a bit too strangely.
What I have always done is.... obviously, if `nil` is not a valid
argument, then just use that.
def b(a=nil)
if a
...
end
But if `nil` is valid then use `ArgumentError`, as that won't be a
valid argument in 99.99% (or so) cases anyway.
def b(a=ArgumentError)
if a == ArgumentError
...
end
For the most robust solution, Ruby Facets defines a toplevel constant
called `NA`, the sole purpose of which is to fill in for cases such as
this.
def b(a=NA)
if a == NA
...
end
That's my favorite, but it require's a dependency on Facets or copy
and pasting the extra code to one's project.
(hmm... it occurs to me that global `$NA` variable would be good to
have too so there's no namespace issues such as in a BasicObjcet
subclass)
···
On Oct 14, 11:31 am, Jens Wille <jens.wi...@uni-koeln.de > wrote:
luke gruber [2011-10-14 17:15]:> That way, the instance won't be available across classes and you
> can just check if the argument responds_to :missing?
or you can just do this:
class A
def b(c = d = true) # or some other truthy value
if d
puts 'no argument was given'
else
puts c
end
end
end
can't remember where i first saw it, but it works perfectly
The downside to this approach is that you use "true" to say something
is "false".
···
On Fri, Oct 14, 2011 at 5:31 PM, Jens Wille <jens.wille@uni-koeln.de > wrote:
luke gruber [2011-10-14 17:15]:
That way, the instance won't be available across classes and you
can just check if the argument responds_to :missing?
or you can just do this:
class A
def b(c = d = true) # or some other truthy value
if d
puts 'no argument was given'
else
puts c
end
end
end
--
Phillip Gawlowski
gplus.to/phgaw | twitter.com/phgaw
A method of solution is perfect if we can forsee from the start,
and even prove, that following that method we shall attain our aim.
-- Leibniz
7rans
(7rans)
14 October 2011 16:18
15
> class A
> def b(c = d = true) # or some other truthy value
> if d
> puts 'no argument was given'
> else
> puts c
> end
> end
> end
> can't remember where i first saw it, but it works perfectly
Yes, of course! That’s the trick I saw too; checking if the optional
argument’s default value was evaluated.
Here’s a more general solution that allows you to set d to a value
independent of the desired default value for the argument:
def m(a = (d = true; nil))
# d will be true if argument a wasn’t specified
end
One easily forgets how expressive Ruby can be. Or how easily it is to abuse it.
Thanks!
Well shit, that might be my new favorite too.
def m(a=(na=true))
p a, na
end
> m
true
true
> m('foo')
"foo"
nil
So, is there a downside to this?
···
On Oct 14, 12:11 pm, Nikolai Weibull <n...@bitwi.se > wrote:
On Fri, Oct 14, 2011 at 17:31, Jens Wille <jens.wi...@uni-koeln.de > wrote:
11142
(-- --)
14 October 2011 21:23
16
Nothing stops him from using `false` in there? You'd just have to
change the condition later (to d==false, not !d, of course).
-- Matma Rex
···
2011/10/14 Phillip Gawlowski <cmdjackryan@gmail.com >:
The downside to this approach is that you use "true" to say something
is "false".
Nikolai Weibull [2011-10-14 18:11]:
Here’s a more general solution that allows you to set d to a
value independent of the desired default value for the argument:
def m(a = (d = true; nil))
# d will be true if argument a wasn’t specified
end
exactly! but i hardly ever have a use case for this. i usually don't
care about the value of 'a' when i'm in the default case.
it reminds me of another useful technique, though:
seen = Hash.new { |h, k| h[k] = true; false }
[1, 2, 3, 2, 3, 4].each { |i| p i unless seen[i] }
contrived example, i know. but comes in handy at times.
One easily forgets how expressive Ruby can be. Or how easily it
is to abuse it.
so true
Phillip Gawlowski [2011-10-14 23:11]:
The downside to this approach is that you use "true" to say
something is "false".
well, i guess that depends on your point of view you seem to read
it as "argument given? => false"; i read it as "apply default case?
=> true". which is why i always name that variable 'default' to
begin with.
11142
(-- --)
14 October 2011 20:12
19
class A
def b(c = d = true) # or some other truthy value
if d
puts 'no argument was given'
else
puts c
end
end
end
I have to admit that's kinda cool.
···
2011/10/14 Jens Wille <jens.wille@uni-koeln.de >:
2011/10/14 Intransition <transfire@gmail.com >:
So, is there a downside to this?
Unreadability if you don't know what it does? Possibly barfing of
code-munging tools? I think that's it. I'd use it
-- Matma Rex