The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Dynamic Variables in Ruby

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Christian Neukirchen

Posts: 188
Nickname: chris2
Registered: Mar, 2005

Christian Neukirchen is a student from Biberach, Germany playing and hacking with Ruby.
Dynamic Variables in Ruby Posted: Apr 24, 2005 6:19 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Christian Neukirchen.
Original Post: Dynamic Variables in Ruby
Feed Title: chris blogs: Ruby stuff
Feed URL: http://chneukirchen.org/blog/category/ruby.atom
Feed Description: a weblog by christian neukirchen - Ruby stuff
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Christian Neukirchen
Latest Posts From chris blogs: Ruby stuff

Advertisement

Many Lisps provide dynamically scoped or special variables additionally to lexically scoped ones. Some (for example Elisp or ye olde MacLisp) even soley provide dynamically scoped variables. In fact, Scheme was the first language to make lexical scoping popular.

Now, what’s the difference between dynamic and lexical scoping? Lexical scoping should be known to every Rubyist, as this is the usual (and the only one provided by default) way of scoping. Lexical scoping has the major advantage of enabling closures, that is, pieces of code that save their lexical environment. For example, in Ruby you can write:

def adder(n)
  v = 0                         # v is lexically scoped here
  lambda { v += n }             # v and n are accessed from the closure
end

add1 = adder(10)
p add1.call  #=> 10
p add1.call  #=> 20
p add1.call  #=> 30

add2 = adder(5)
p add2.call  #=> 5
p add2.call  #=> 10
p add2.call  #=> 15

But you already knew that. Not so with dynamic scope, and that’s why dynamic scope is usually avoided. However, there is one important and useful usage for dynamic scope: Providing contexts. For example, let’s say you write a currency converter in Elisp:

(defvar +eur2usd-factor+ 1.3068)    ; 24apr2005

(defun eur2usd (euro)
  (* +eur2usd-factor+ euro))

(eur2usd 10)                ; => 13.068
(eur2usd 0.77)              ; => 1.006236

Ok, that was easy. But not, let’s say we would like to know what our Euros would have been worth last year. Of course, we could globally change the factor, but that would be icky and we would need to be careful to change it back, so rather let’s dynamically rebind the value:

(let ((+eur2usd-factor+ 0.9267))    ; last year, maybe
  (eur2usd 10)              ; => 9.267
  (eur2usd 0.77))           ; => 0.713559

This may surprise you, but eur2usd looks up the dynamic value of +eur2usd-factor+, not the lexical value (which would have been 1.3068). let redefines the value during the execution of his body, so when eur2usd is called, +eur2usd-factor+ is actually 0.9267. However, after the let, everything is as it has been before:

(eur2usd 10)                ; => 13.068

Now, how can we translate this behavior into Ruby. I decided to go the way of using a thread-local variable (a Hash, actually) and add convenience functions to define and change and rebind them. Let’s see how above code looks in Ruby:

require 'dynamic'

Dynamic.variable :eur2usd_factor => 1.3068

def eur2usd(euro)
  euro * Dynamic.eur2usd_factor
end

p eur2usd(10)               # => 13.068
p eur2usd(0.77)             # => 1.006236

Dynamic.let :eur2usd_factor => 0.9267 do
  p eur2usd(10)             # => 9.267
  p eur2usd(0.77)           # => 0.713559
end

p eur2usd(10)               # => 13.068

Now, that was pretty easy. You basically just need to prefix your variable with Dynamic. to look it up. It’s also a nice sample how to extend Ruby to add new language features, by definining some convenient methods alone.

As you should use dynamic variables as globals only, it does no harm that Dynamic is implemented using a singleton. Dynamic is thread-safe however, in that you can’t change other thread’s environment, and get a new copy of the main thread’s environment.

Now, go ahead and grok the code. Happy hacking.

NP: The Distillers—Gypsy Rose Lee

Read: Dynamic Variables in Ruby

Topic: Cross-domain XMLHttpRequest Previous Topic   Next Topic Topic: Rails 0.12.1: No major update without a bit of pain

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use