#define alternative for Ruby

I know it but imagine you must do it 100 times?
I'd rather write:
set_default(var1, 15)
set_default(myvar1, "string")
...
set_default(lastvar, myhash)

In your case I must use "var" twice. Don't you think it is too much?

···

On Mar 12, 4:07 pm, ara.t.how...@noaa.gov wrote:

On Mon, 12 Mar 2007, Michael Strelnikov wrote:
>> I would be interested in hearing what you want to do with text substitution
>> that you cannot already do with standard Ruby metaprogramming techniques.

> Easy.
> Let's we have following function:
> * set_default(var, val)
> -- if variable "var" is not defined (not existed) then assign value "val"
> else do nothing.

> The variable could be ANY type including "Fixnum".

> Try to implement it using standard techniques.

     harp:~ > cat a.rb
     unless defined? var
       var = 42
     end

     p var

     harp:~ > ruby a.rb
     42

-a
--
be kind whenever possible... it is always possible.
- the dalai lama

Just try to implement:
set_default(var, val)
-- if variable "var" is not defined (not existed) then assign value
"val"

···

On Mar 12, 7:47 pm, Brian Candler <B.Cand...@pobox.com> wrote:

On Mon, Mar 12, 2007 at 05:16:08PM +0900, Sebastian Hungerecker wrote:
> ara.t.how...@noaa.gov wrote:
> > On Mon, 12 Mar 2007, Mike wrote:
> > > I was talking more about macros rather then constants. But I agree that
> > > constant are convenient way to substitute "#define myconst 15". But can
> > > you substitute "#define myfunc(x) (sin(x)*cos(x)*exp(x))"? You should
> > > know that "x" could be as much other functions as a constant/variable.

> > perhaps i'm being dense, but i fail to see how the above example is none
> > other than a simple function in ruby:

> Imagine you would call the function with rand() as parameter. With #define
> rand would be called three times, with def it would be called once and its
> value would be used three times.

???

irb(main):001:0> def myfunc(x); Math.sin(x)*Math.cos(x)*Math.exp(x); end
=> nil
irb(main):002:0> p myfunc(rand)
0.44720293351854
=> nil
irb(main):003:0> p myfunc(rand)
1.07121692170638
=> nil
irb(main):004:0> p myfunc(rand)
1.01827292445777
=> nil

Now, if you *store* the value of rand within the function, that's a
different case. But Ruby has different idioms for deferred execution: one of
those is

class Foo
  def initialize(&blk)
    @gen = blk
  end
  def value
    @gen.call
  end
end

a = Foo.new { rand }
puts a.value
puts a.value
puts a.value

Although I am against macros it might be worth pointing out that of
course it can be done

#define MYDEFINE var val \
var = val unless defined? var

forgive me if the syntax is incorrect.
The Ruby interpreter will not see the macro and vice versa.

BTW on Linux I guess you can always use gcc to preprocess files anyway, but
STAY AWAY FROM THIS.

Sorry for shouting, but I wanted to be heared :wink:
Cheers
Robert

···

On 3/12/07, Timothy Hunter <TimHunter@nc.rr.com> wrote:

Mike wrote:
> Just try to implement:
> set_default(var, val)
> -- if variable "var" is not defined (not existed) then assign value
> "val"
>

I'd like to point out that you can't do that with #define, since C
macros are processed before the compiler runs, and whether or not "var"
is defined is not known until the compiler runs.

--
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important things.
-Anonymous

   harp:~ > cat a.rb
   def myfunc *a, &b
     x = a.shift || b.call
     Math.sin(x) * Math.cos(x) * Math.exp(x)
   end

That's got the same problem - rand will only be evaluated once, what you
were no doubt after is:

def myfunc *a, &b
  b ||= proc { a.first }
  Math.sin(b.call) * Math.cos(b.call) * Math.exp(b.call)
end

But the point remains, anything macros do, functions or metaprogramming
do better.

Dan.

I think we have a stuck record here :slight_smile:

For this particular example, the code you are looking for is:

  var ||= val

with no method call at all. This is a tiny pattern and not worth
abstracting.

Local variables are *static*. Local variables are not intended to be handled
in the way you are asking. The language provides other facilities (i.e. not
local variables) when you want to be more dynamic.

"Doctor, it hurts when I do this."
"Then don't do that!"

Try the following if you don't understand what I mean by local variables
being "static".

  def x
    "This method is never called"
  end

  if false
    x = "Local variable"
  end

  puts x

This code prints "nil". Reflect on why this is the case.

Regards,

Brian.

···

On Mon, Mar 12, 2007 at 06:05:25PM +0900, Mike wrote:

> > Imagine you would call the function with rand() as parameter. With #define
> > value would be used three times.
>
> ???
>
> irb(main):001:0> def myfunc(x); Math.sin(x)*Math.cos(x)*Math.exp(x); end
> => nil
> irb(main):002:0> p myfunc(rand)
> 0.44720293351854
> => nil
> irb(main):003:0> p myfunc(rand)
> 1.07121692170638
> => nil
> irb(main):004:0> p myfunc(rand)
> 1.01827292445777
> => nil
>
> Now, if you *store* the value of rand within the function, that's a
> different case. But Ruby has different idioms for deferred execution: one of
> those is
>
> class Foo
> def initialize(&blk)
> @gen = blk
> end
> def value
> @gen.call
> end
> end
>
> a = Foo.new { rand }
> puts a.value
> puts a.value
> puts a.value

Just try to implement:
set_default(var, val)
-- if variable "var" is not defined (not existed) then assign value
"val"

OK, if you *really* insist:

---- 8< -------------------------------------------------
require 'rubygems'
require 'active_support/binding_of_caller'

def set_default(var, val)
  Binding.of_caller do |binding|
    eval("#{var} ||= #{val}", binding)
  end
end

var1 = nil # <<<<<<< A
set_default("var1", 5)
set_default("var1", 15)
puts var1 # <<<<<<< B (prints 5)
---- 8< -------------------------------------------------

This works as written; but you'll find you get bitten by the static nature
of local variables if you remove line "A". It then fails.

This is because of the ambiguity in line B: "puts var1" could be referring
to a method call - puts self.var1() - or a local variable. This ambiguity is
resolved at *parse* time, before any code has been executed at all, simply
based on whether a statement of the form "var1 = xxx" has been seen earlier
in the file.

If you remove line A, then line B is already resolved as puts self.var1()
*before* any code has been executed.

Now, macros would be fine here - but only if these macros were expanded at
parse time. That makes them very static, and not very useful in a dynamic
language like Ruby.

As others have said before: provide a *real* example of where you would need
macros, not a noddy "var ||= val" replacement, and we'll show you how
Rubyists would handle this case.

Regards,

Brian.

···

On Mon, Mar 12, 2007 at 06:00:21PM +0900, Mike wrote:

I know it but imagine you must do it 100 times?
I'd rather write:
set_default(var1, 15)
set_default(myvar1, "string")
...
set_default(lastvar, myhash)

Robert Dober wrote:

···

On 3/12/07, Timothy Hunter <TimHunter@nc.rr.com> wrote:

Although I am against macros it might be worth pointing out that of
course it can be done

#define MYDEFINE var val \
var = val unless defined? var

forgive me if the syntax is incorrect.
The Ruby interpreter will not see the macro and vice versa.

BTW on Linux I guess you can always use gcc to preprocess files anyway,
but
STAY AWAY FROM THIS.

Sorry for shouting, but I wanted to be heared :wink:
Cheers
Robert

Perhaps we are discussing different kinds of variables. Your macro tests
if a given preprocessor symbol is defined or not. Such a symbol must be
defined (or not) when the preprocessor runs. Probably the closest analog
in Ruby is a global constant. I was talking about variables such as
automatics or statics, much closer to Ruby's variables.

--
Posted via http://www.ruby-forum.com/\.

in that case i'd probably just use

   var1 ||= 15

or instance variables. there a so many ways to skin that cat. you could do
something subversive like this if yoiu really wanted to

   harp:~ > cat a.rb
   require 'binding_of_caller'

   def set_default a, &b
     @set_default = b
     Binding.of_caller do |binding|
       eval "
         class << self
           define_method '#{ a }', &@set_default
         end
       ", binding
     end
   end

   100.times{|i| set_default(:x){ i + 1 } }

   p x #=> 100

i guess i see that there are times when a macro might make things faster to
write, but the tradeoff, as we all know, it that they are then slower to
debug. in the end you cannot do anything you coulnd't without one and it can
substantially confuse debugging when text substitution, dynamic scoping, and
closures are mixed. consider

   later = Queue.new

   #define now( x ) later.push(lambda{ x })

   x = 40
   now(x += 2)

   p x #=> 40

   sleep rand

   p x #=> 42

regards.

-a

···

On Mon, 12 Mar 2007, Mike wrote:

I know it but imagine you must do it 100 times?
I'd rather write:
set_default(var1, 15)
set_default(myvar1, "string")
...
set_default(lastvar, myhash)

In your case I must use "var" twice. Don't you think it is too much?

--
be kind whenever possible... it is always possible.
- the dalai lama

The "local variables" is exactly what confuses me. Why can't I use
variables (read/set) inside of function that is at the same hierarchy as
variable is?

···

On 3/12/07, Brian Candler <B.Candler@pobox.com> wrote:

On Mon, Mar 12, 2007 at 06:05:25PM +0900, Mike wrote:
> > > Imagine you would call the function with rand() as parameter. With
#define
> > > value would be used three times.
> >
> > ???
> >
> > irb(main):001:0> def myfunc(x); Math.sin(x)*Math.cos(x)*Math.exp(x);
end
> > => nil
> > irb(main):002:0> p myfunc(rand)
> > 0.44720293351854
> > => nil
> > irb(main):003:0> p myfunc(rand)
> > 1.07121692170638
> > => nil
> > irb(main):004:0> p myfunc(rand)
> > 1.01827292445777
> > => nil
> >
> > Now, if you *store* the value of rand within the function, that's a
> > different case. But Ruby has different idioms for deferred execution:
one of
> > those is
> >
> > class Foo
> > def initialize(&blk)
> > @gen = blk
> > end
> > def value
> > @gen.call
> > end
> > end
> >
> > a = Foo.new { rand }
> > puts a.value
>
> Just try to implement:
> set_default(var, val)
> -- if variable "var" is not defined (not existed) then assign value
> "val"

I think we have a stuck record here :slight_smile:

For this particular example, the code you are looking for is:

  var ||= val

with no method call at all. This is a tiny pattern and not worth
abstracting.

Local variables are *static*. Local variables are not intended to be
handled
in the way you are asking. The language provides other facilities (i.e.
not
local variables) when you want to be more dynamic.

"Doctor, it hurts when I do this."
"Then don't do that!"

Try the following if you don't understand what I mean by local variables
being "static".

  def x
    "This method is never called"
  end

  if false
    x = "Local variable"
  end

  puts x

This code prints "nil". Reflect on why this is the case.

Regards,

Brian.

Please note that
    var ||= val
is not the same than
   var = val unless defined? var

Very often it is preferable of course.
Robert

<snip>

···

On 3/12/07, Brian Candler <B.Candler@pobox.com> wrote:

On Mon, Mar 12, 2007 at 06:05:25PM +0900, Mike wrote:
> > > Imagine you would call the function with rand() as parameter. With #define
> > > value would be used three times.
> >
> > ???
> >
> > irb(main):001:0> def myfunc(x); Math.sin(x)*Math.cos(x)*Math.exp(x); end
> > => nil
> > irb(main):002:0> p myfunc(rand)
> > 0.44720293351854
> > => nil
> > irb(main):003:0> p myfunc(rand)
> > 1.07121692170638
> > => nil
> > irb(main):004:0> p myfunc(rand)
> > 1.01827292445777
> > => nil
> >
> > Now, if you *store* the value of rand within the function, that's a
> > different case. But Ruby has different idioms for deferred execution: one of
> > those is
> >
> > class Foo
> > def initialize(&blk)
> > @gen = blk
> > end
> > def value
> > @gen.call
> > end
> > end
> >
> > a = Foo.new { rand }
> > puts a.value
>
> Just try to implement:
> set_default(var, val)
> -- if variable "var" is not defined (not existed) then assign value
> "val"

I think we have a stuck record here :slight_smile:

For this particular example, the code you are looking for is:

  var ||= val

Robert Dober wrote:
>>
> Although I am against macros it might be worth pointing out that of
> course it can be done
>
> #define MYDEFINE var val \
> var = val unless defined? var
>
> forgive me if the syntax is incorrect.
> The Ruby interpreter will not see the macro and vice versa.
>
> BTW on Linux I guess you can always use gcc to preprocess files anyway,
> but
> STAY AWAY FROM THIS.
>
> Sorry for shouting, but I wanted to be heared :wink:
> Cheers
> Robert

Perhaps we are discussing different kinds of variables. Your macro tests
if a given preprocessor symbol is defined or not. Such a symbol must be
defined (or not) when the preprocessor runs. Probably the closest analog
in Ruby is a global constant. I was talking about variables such as
automatics or statics, much closer to Ruby's variables.

Sorry I was focused on the original idea, I understand your remark now,
thx for clarifying.
Robert

···

On 3/12/07, Tim Hunter <rmagick@gmail.com> wrote:

> On 3/12/07, Timothy Hunter <TimHunter@nc.rr.com> wrote:

--
Posted via http://www.ruby-forum.com/\.

--
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important things.
-Anonymous

Because each 'def' starts a brand new scope for local variables, and local
variables outside that scope are not visible.

Doing this has several advantages:

(1) Much more efficient to implement.

- When you refer to a local variable "x" it can only be within your own
stack frame, at a known offset; no need to hunt outside.

- It enables the parse-time decision as to whether "x" is a local variable
or method call. Otherwise this decision could only be made a run-time, and
performance would suck even for simple statements like "x = y"

(2) Makes it much harder to introduce unforeseen side effects by affecting
local variables outside of the method you are defining.

So, you may be used to writing something like

  x = ...

  def myfunc(a)
    .. stuff which uses x and a
  end

in another language, but if so you'll need to think slightly differently in
Ruby.

When you define "functions" at the "top level" of your program, you are
really defining methods inside an object called 'main'. As soon as you
introduce your own objects, these problems tend to vanish, because instance
variables are the de-rigeur:

class Myclass
  def initialize(x)
    @x = x
  end

  def myfunc(a)
    .. stuff which uses @x and a
  end
end

All but the most trivial of Ruby programs declare classes like this. And
there are plenty of ways of doing reflection on methods and instance
variables. The simplest example is

class Myclass
  attr_accessor :foo
end

which creates methods equivalent to the following:

class Myclass
  def foo=(val)
    @foo = val
  end
  def foo
    @foo
  end
end

You can write your own analogue to attr_accessor which also sets a default
value for an attribute, should you so wish, although this is usually done
inside the 'initialize' method of your class. An if you're making objects
with lots of attributes which vary at runtime, you'd probably be better off
looking at Struct or OpenStruct as a starting point.

Regards,

Brian.

···

On Mon, Mar 12, 2007 at 06:31:02PM +0900, Michael Strelnikov wrote:

The "local variables" is exactly what confuses me. Why can't I use
variables (read/set) inside of function that is at the same hierarchy as
variable is?

Indeed - it will set values when var == nil or var == false as well.

However, calling a run-time 'defined?' method is usually redundant, since in
almost all cases you can tell statically whether it's defined or not:

    if false
      var = 123
    end
    puts defined? var # redundant, var is *always* defined here

But in some cases you might want

   var = val if var.nil?

(e.g. if you are dealing with a boolean variable)

···

On Mon, Mar 12, 2007 at 07:44:49PM +0900, Robert Dober wrote:

>For this particular example, the code you are looking for is:
>
> var ||= val
Please note that
   var ||= val
is not the same than
  var = val unless defined? var

Very often it is preferable of course.