#define alternative for Ruby

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)

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 3/12/07, Brian C. [email protected] wrote:

=> nil
Now, if you store the value of rand within the function, that’s a
end
“val”
Local variables are static. Local variables are not intended to be

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

Regards,

Brian.

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 C. [email protected] wrote:

=> nil

puts a.value
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.
Robert

On Mon, Mar 12, 2007 at 06:31:02PM +0900, Michael S. 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?

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 07:44:49PM +0900, Robert D. 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.

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 3/12/07, Timothy H. [email protected] 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

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.

Robert D. wrote:

On 3/12/07, Timothy H. [email protected] 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.

On 3/12/07, Tim H. [email protected] wrote:

forgive me if the syntax is incorrect.
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 Mon, 12 Mar 2007, Sebastian H. wrote:

[email protected] 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.

absolutely. but that’s generally considered a problem with macros, not
a
feature. besides, that’s easy too

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

x as function

def x() 42 end
p myfunc(x)

x as constant

X = 42
p myfunc(X)

x as variable

x = 42
p myfunc(x)

x as rand

p myfunc{ rand }

regards.

-a

set_default(var, val)
– if variable “var” is not defined (not existed) then assign value
“val”

require ‘binding_of_caller’ # google for this, you need call_stack
# or equiv for ruby >= 1.8.5
def set_default( var, val )
Binding.of_caller do |b|
eval("#{var} = #{val} unless #{var}", b)
end
end

set_default( “a”, “7” )

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?

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

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.