Wow, you're meddling in some pretty interesting things here. I don't
think Ruby is that fit for them, however.

Forth is a language without arguments. You just have a stack shared by
all. It's elegant as hell and I love it, and it's first on my list of
things to meddle with seriously.

Forth code looks like this:

: fib-iter ( n -- f ) ( things in braces are comments )
  0 1 rot 0 ?do over + swap loop drop ;

Here's an explanation:
http://en.literateprograms.org/Fibonacci_numbers_(Forth)#chunk%20def:fib-iter

Ask Ed Borasky. He's very enthusiastic about it.


Your later ideas sound to me a bit like Haskell monads, of which I've
read a very good explanation recently that I've forgot the link for
(there's a whole industry of trying to explain what monads are).

Aur

On 6/17/07, Trans <transfire / gmail.com> wrote:
>
>
> On Jun 16, 3:52 am, "Erwin Abbott" <erwin.abb... / gmail.com> wrote:
> > On 6/16/07, Trans <transf... / gmail.com> wrote:
> >
> >
> >
> > > Thanks Erwin, that helps. I was toying with not having any methd
> > > arguments. It's interesting, in that it can be done. However, in a
> > > case like the above it requires intantiaing a new object for dealing
> > > with type.
> >
> > >   class X
> > >     ...
> > >     def go
> > >       @ary.each { |x|
> > >         TypeRunner.new(x).run
> > >       }
> > >     end
> > >   end
> >
> > >    class TypeRunner
> > >      ...
> > >    end
> >
> > >    X.new(['a', 'b', 'c']).go
> >
> > > Am I right about this being thread safe(r) where the first version was
> > > not?
> >
> > Yes, this is thread safe... each thread that calls #go gets its own
> > set of objects (TypeRunners) that are separate from the objects in the
> > other threads.
> >
> > > Also, I was thinking. If it's thread safe to just pass type as an
> > > argument, one would think there could be a way to define a "locked"
> > > instance var that is essentially the same thing but without all the
> > > overhead.
> >
> > It seems like it should be simple, but there's a lot of complexity
> > when programming multithreaded code. In your example you're not
> > changing the state of anything, so that's why you can simplify
> > things... but things get out of hand fast. See my comments past the
> > end of the code below.
> >
> > Here's my attempt at a very *simple* way to do what you're talking
> > about... I had trouble getting the methods put in the right namespace,
> > so maybe my module code isn't the most elegant but it does what I want
> > it to do.
> >
> > require 'thread'
> >
> > module Locker
> >   def self.included mod
> >     (class << mod; self; end).instance_eval do
> >
> >       define_method(:attr_locked) do |*names|
> >         class_eval do
> >           @@locks ||= {}
> >
> >           names.each do |name|
> >             # make a lock for each attribute
> >             @@locks[name] = Mutex.new
> >
> >             # getter
> >             define_method(name) do
> >               @@locks[name].synchronize do
> >                 instance_variable_get("@#{name}")
> >               end
> >             end
> >
> >             # setter
> >             define_method("#{name}=") do |value|
> >               @@locks[name].synchronize do
> >                 instance_variable_set("@#{name}", value)
> >                 sleep 5
> >               end
> >             end
> >
> >           end
> >
> >         end # class_eval
> >       end # attr_locked
> >
> >     end # instance_eval
> >   end
> > end
> >
> > class DooWop
> >   include Locker
> >   attr_locked :chord, :name
> >
> >   def initialize name, chord
> >     @name, @chord = name, chord
> >   end
> > end
> >
> > x = DooWop.new('The Platters', 'Fmaj6/9')
> >
> > $stdout.sync = true
> > def tprint string
> >   print "#{Thread.current} #{string}\n"
> > end
> >
> > Thread.new{ tprint "1. #{x.name}" }
> >
> > # this will block access to x.name for 5 seconds
> > Thread.new{ tprint "2. setting name"; x.name = 'The Orioles' }
> >
> > # this will wait for the above thread to finish
> > Thread.new{ sleep 1; tprint "3. #{x.name}" }
> >
> > # this isn't blocked
> > Thread.new{ tprint "4. #{x.chord}" }
> >
> > # this will block access to x.chord for 5 seconds
> > Thread.new do
> >   tprint "5. setting chord"
> >   x.chord = 'Dm7b5'
> >   tprint "5. #{x.chord}"
> > end
> >
> > # this could be indeterminite, we didn't wait for the writer to finish
> > Thread.new{ tprint "6. unsafe: #{x.instance_eval{@name}}" }
> >
> > sleep 0.5 until Thread.list.size == 1 # should be joining here instead
> >
> > This is helpful only in the simplest cases. First it blocks everyone
> > while in the getter or setter... ideally we shouldn't make the getters
> > wait for the other getters to finish. Next, if you try to read the
> > variable more than once in a method, you can still end up with
> > different values.
> >
> > You'd need to wrap the section of code that involves the var in a
> > #synchronize block... but wrap the *least* amount of code necessary
> > because you want to hurry up and let the other threads do their work.
> > There's no way to "automate" that. The code above is only useful in
> > the most simple applications.
> >
> > Further, we've only been talking about one variable at a time.  Often
> > you'll need to lock several variables, like maybe we are going to look
> > up on Google which songs by @name have the chord @chord.  We'll need
> > to get those values at the *same time* because if we read chord,
> > (another thread interrupts here and changes @name), then read name...
> > that's a problem, and our "locked" variables can't do anything to
> > help.
> >
> > There was a thread on this list a few days ago with a title like
> > "synchronized attr", I only skimmed it but I think they were talking
> > about why you can't really boil thread synchronization down to a
> > one-size-fits-all solution. There are a few data structures (Monitor,
> > ConditionVariable, Queue, etc) that really help out, but there's no
> > way to just call some method to magically make your code thread
> > safe... yet?
>
> I was thinking more along the lines of "transparent arguments". Here's
> the idea in pseudo-code. I'll represent these "transparent arguments"
> via an underscore.
>
>   class Q
>
>     def f
>       _t = "world"
>       g("hello")
>     end
>
>     def g(x)
>       puts x + ' ' + _t
>       h("goodbye")
>     end
>
>     def h(x)
>       puts x + ' ' + _t
>     end
>   end
>
>   Q.new.f
>
> produces
>
>   hello world
>   goodbye world
>
> In effect, _t is being tacked on to the arguments of every call, and
> is thus getting passed around just like any other argument, but
> without need to explicitly "slot" for it in the method interface. In
> effect, transparent arguments are a sort of symbiosis of instance var
> and argument. Now, I know that some will see this and think it a
> violation of the very purpose of functions, ie. the isolation of name
> spaces. However, one should see these as a form of instance var, not
> argument --they differ only in that they piggy back on the argument
> passing mechanism.
>
> T.
>
>
>