Value provided for argument with default value - how to check inside method?

Is there an equivalent of block_given? to check if the caller provided a
value to an argument that had a default value?

Or do I have to use some sentinel value?

Thanks!

itsme213 wrote:

Is there an equivalent of block_given? to check if the caller provided a
value to an argument that had a default value?

Or do I have to use some sentinel value?

AFAIK, you either have to use

   def foo(*args)

and count args, or use hash arguments, which let you test with #key? :

   def foo(h={})
     if h.key?(:bar)
       puts "You passed :bar=>#{h[:bar]}"
     else
       h[:bar] = DEFAULT_BAR
     end
   end

"itsme213" <itsme213@hotmail.com> schrieb im Newsbeitrag
news:mXCid.17442$tL5.16841@fe2.texas.rr.com...

Is there an equivalent of block_given? to check if the caller provided a
value to an argument that had a default value?

Or do I have to use some sentinel value?

I'm unsure what you're at. Normally the idea of having a default value is
that you don't have to worry about where it came from:

def foo(x=10)
  puts x
end

Care to unveil a bit more detail why you would need that piece of
information?

Kind regards

    robert

Is there an equivalent of block_given? to check if the caller provided a
value to an argument that had a default value?

Or do I have to use some sentinel value?

I remember Nobu had a solution for this... I can't seem to find it though. I think it was something like this:

> def foo(x=(nil; a=true))
> puts a
> end
=> nil
> foo()
true
=> nil
> foo('value')
nil
=> nil

You can replace nil with the default value you want. a will be set to true if a value is passed in, nil otherwise.

-Charlie

···

On Nov 4, 2004, at 8:03 PM, itsme213 wrote:

In this case, I want to use foo() and foo(x) as getter and setter
respectively i.e. some form of overloading.

···

"Robert Klemme" <bob.news@gmx.net> wrote

I'm unsure what you're at. Normally the idea of having a default value is
that you don't have to worry about where it came from:

def foo(x=10)
  puts x
end

Care to unveil a bit more detail why you would need that piece of
information?

you may also use something like

   def foo arg, opts = {}
     if opts.has_key? 'x'
       ...
     end
     opts.update defaults
     ...
   end

-a

···

On Sat, 6 Nov 2004, Charles Mills wrote:

On Nov 4, 2004, at 8:03 PM, itsme213 wrote:

Is there an equivalent of block_given? to check if the caller provided
a
value to an argument that had a default value?

Or do I have to use some sentinel value?

I remember Nobu had a solution for this... I can't seem to find it
though. I think it was something like this:

> def foo(x=(nil; a=true))
> puts a
> end
=> nil
> foo()
true
=> nil
> foo('value')
nil
=> nil

You can replace nil with the default value you want. a will be set to
true if a value is passed in, nil otherwise.

-Charlie

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
When you do something, you should burn yourself completely, like a good
bonfire, leaving no trace of yourself. --Shunryu Suzuki

===============================================================================

Is there an equivalent of block_given? to check if the caller provided a
value to an argument that had a default value?

Or do I have to use some sentinel value?

I remember Nobu had a solution for this... I can't seem to find it though. I think it was something like this:

> def foo(x=(nil; a=true))
> puts a
> end
=> nil
> foo()
true
=> nil
> foo('value')
nil
=> nil

You can replace nil with the default value you want.

a will be set to true if a value is passed in, nil otherwise.

···

On Nov 5, 2004, at 9:54 AM, Charles Mills wrote:

On Nov 4, 2004, at 8:03 PM, itsme213 wrote:

                                     -----
I meant "unless a value is passed in"

Hi,

At Sat, 6 Nov 2004 02:54:51 +0900,
Charles Mills wrote in [ruby-talk:119266]:

> def foo(x=(nil; a=true))

  def foo(x=(a=true; nil))

···

--
Nobu Nakada

itsme213 wrote:

I'm unsure what you're at. Normally the idea of having a default value is
that you don't have to worry about where it came from:

def foo(x=10)
puts x
end

Care to unveil a bit more detail why you would need that piece of
information?

In this case, I want to use foo() and foo(x) as getter and setter
respectively i.e. some form of overloading.

You can always do something like the following. Create a constant and initialize it to a unique object instance. Then, use that instance as the default value to your method:

   VALUE_NOT_SPECIFIED = Object.new
   def foo( x = VALUE_NOT_SPECIFIED )
     case x
       when VALUE_NOT_SPECIFIED
         @x
       else
         @x = x
     end
   end

Of course, someone could still explicitly pass the argument VALUE_NOT_SPECIFIED to the method, but then they would obviously be trying pretty hard to do what they aren't supposed to do...

- Jamis

···

"Robert Klemme" <bob.news@gmx.net> wrote

--
Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck.org/jamis

how about something like this

   harp:~ > cat a.rb
   class C
     DEFAULT_X = 42
     class << self
       def init
         @x = DEFAULT_X
       end
       def x arg = @x
         @x = arg
       end
     end
     self.init
     def initialize
       @x = self.class.x
     end
     def x arg = @x
       @x = arg
     end
   end

   c0 = C::new
   p c0.x
   c0.x 'forty-two'
   p c0.x

   C::x 'forty-two' # configure the class
   c1 = C::new
   p c1.x
   c1.x 42
   p c1.x

   harp:~ > ruby a.rb
   42
   "forty-two"
   42

regards.

-a

···

On Fri, 5 Nov 2004, itsme213 wrote:

"Robert Klemme" <bob.news@gmx.net> wrote

I'm unsure what you're at. Normally the idea of having a default value is
that you don't have to worry about where it came from:

def foo(x=10)
  puts x
end

Care to unveil a bit more detail why you would need that piece of
information?

In this case, I want to use foo() and foo(x) as getter and setter
respectively i.e. some form of overloading.

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
When you do something, you should burn yourself completely, like a good
bonfire, leaving no trace of yourself. --Shunryu Suzuki

===============================================================================

Something like:

  def foo(*x)
    if x.empty?
      defined?(@x) ? @x : @x=10
    else
      @x = x.pop
    end
  end

Should do the trick.

T.

···

On Friday 05 November 2004 10:08 am, itsme213 wrote:

"Robert Klemme" <bob.news@gmx.net> wrote

> I'm unsure what you're at. Normally the idea of having a default value
> is that you don't have to worry about where it came from:
>
> def foo(x=10)
> puts x
> end
>
> Care to unveil a bit more detail why you would need that piece of
> information?

In this case, I want to use foo() and foo(x) as getter and setter
respectively i.e. some form of overloading.

"Jamis Buck" <jgb3@email.byu.edu> schrieb im Newsbeitrag
news:418B9D5A.4090704@email.byu.edu...

itsme213 wrote:
>
>>I'm unsure what you're at. Normally the idea of having a default

value is

>>that you don't have to worry about where it came from:
>>
>>def foo(x=10)
>> puts x
>>end
>>
>>Care to unveil a bit more detail why you would need that piece of
>>information?
>
>
> In this case, I want to use foo() and foo(x) as getter and setter
> respectively i.e. some form of overloading.

For getters and setters there's a convention in Ruby already. IMHO in
this case it's better to stick with foo/foo= instead of creating a new
convention.

There are some solutions for the general case of overloading, see here for
example:

You can always do something like the following. Create a constant and
initialize it to a unique object instance. Then, use that instance as
the default value to your method:

   VALUE_NOT_SPECIFIED = Object.new
   def foo( x = VALUE_NOT_SPECIFIED )
     case x
       when VALUE_NOT_SPECIFIED
         @x
       else
         @x = x
     end
   end

Of course, someone could still explicitly pass the argument
VALUE_NOT_SPECIFIED to the method, but then they would obviously be
trying pretty hard to do what they aren't supposed to do...

I'm sure we could find a way to make VALUE_NOT_SPECIFIED private. One can
also do this:

def foo(*a)
  @foo = a[0] unless a.empty?
  @foo
end

But as I said, my main concern is that this introduces a different pattern
for state access while Ruby has such a pattern already.

Kind regards

    robert

···

> "Robert Klemme" <bob.news@gmx.net> wrote

Robert Klemme wrote:

But as I said, my main concern is that this introduces a different pattern
for state access while Ruby has such a pattern already.

It has, but it breaks down in certain situations. Consider:

   class T
     def initialize( &block )
       instance_eval &block
     end
     def v
       @v
     end
     def v=( x )
       @v = x
     end
   end

   t = T.new do
     v = 5
   end

Does T#v= get called? Nope. v is interpreted as a local variable. As it should be--I'm not arguing for it to do otherwise. All I'm saying is that there are times where it is useful to have the setter be like the OP requested. There is even code in Ruby's stdlib that does it that way (tk, for instance).

Ruby is known for it's position on TMTOWTDI. Let's not discourage people from exploring these other avenues. If an approach turns out to be cumbersome, it won't be adopted. If it works well, people will use it.

- Jamis

···

--
Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck.org/jamis

Hi --

Ruby is known for it's position on TMTOWTDI.

Hmmmm.... I always thought that a slogan for Perl, and at most an
incidental state of things in Ruby :slight_smile:

Let's not discourage people
from exploring these other avenues. If an approach turns out to be
cumbersome, it won't be adopted. If it works well, people will use it.

I think Robert was saying he finds it cumbersome and would not adopt
it :slight_smile: I'm not against experimentation either, but I wouldn't want to
discourage critiques from experienced Rubyists either.

David

···

On Sat, 6 Nov 2004, Jamis Buck wrote:

--
David A. Black
dblack@wobblini.net

"Jamis Buck" <jgb3@email.byu.edu> schrieb im Newsbeitrag
news:418BAC7C.2010201@email.byu.edu...

Robert Klemme wrote:

> But as I said, my main concern is that this introduces a different

pattern

> for state access while Ruby has such a pattern already.

It has, but it breaks down in certain situations. Consider:

   class T
     def initialize( &block )
       instance_eval &block
     end
     def v
       @v
     end
     def v=( x )
       @v = x
     end
   end

   t = T.new do
     v = 5
   end

Does T#v= get called? Nope. v is interpreted as a local variable. As it
should be--I'm not arguing for it to do otherwise. All I'm saying is
that there are times where it is useful to have the setter be like the
OP requested. There is even code in Ruby's stdlib that does it that way
(tk, for instance).

I didn't think of this situation, thanks for the reminder! For the
initialization I prefer this idiom:

   class T
     DEFAULT_VALUES = {
        :v => 10
     }.freeze

     def initialize( values = {} )
       DEFAULT_VALUES.merge(values).each do |k,v|
         send("#{k}=",v)
       end
     end
     def v
       @v
     end
     def v=( x )
       @v = x
     end
   end

   t = T.new(
     :v => 5
   )

Advantage of this variant over the one with the block is, that you can
easily determine which values were provided by the caller. That's more
difficult with the block.

Ruby is known for it's position on TMTOWTDI. Let's not discourage people
from exploring these other avenues. If an approach turns out to be
cumbersome, it won't be adopted. If it works well, people will use it.

Of course everybody is free to do what they like. My point is, that it
might cause hazzle if someone uses a different pattern for something so
basic like attribute assignment where there is a well established
different pattern for this. While we should not follow conventions
slaverishly, conventions are in fact important and do have their benefits.

Kind regards

    robert

"David A. Black" <dblack@wobblini.net> schrieb im Newsbeitrag
news:Pine.LNX.4.44.0411050855240.28112-100000@wobblini...

Hi --

> Ruby is known for it's position on TMTOWTDI.

Hmmmm.... I always thought that a slogan for Perl, and at most an
incidental state of things in Ruby :slight_smile:

> Let's not discourage people
> from exploring these other avenues. If an approach turns out to be
> cumbersome, it won't be adopted. If it works well, people will use it.

I think Robert was saying he finds it cumbersome and would not adopt
it :slight_smile: I'm not against experimentation either, but I wouldn't want to
discourage critiques from experienced Rubyists either.

David, thanks for the "translation". :slight_smile:

    robert

···

On Sat, 6 Nov 2004, Jamis Buck wrote: