We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpProcessing Implementations › ruby-processing environment
Page Index Toggle Pages: 1
ruby-processing environment (Read 6096 times)
ruby-processing environment
Mar 30th, 2009, 3:28pm
 
Hi,
I'm going through the processing tutorials, first in java, then doing the translation to ruby.  I stumbled upon a processing environment scope translation problem doing the OOP tutorial.

lets say in java-processing you create a class, this class has access to the processing global scope methods like stroke, fill, width, etc.
(like the Car class in the tutorial)

translate this in ruby-processing... the processing methods are now instance methods of your RubyClass < Processing::App class.  How can you then create an other accessory class (the Car in the tutorial) to use which would also have access to the processing methods like stroke, fill, width, etc.
The way I found is to pass a binding to my accessory class, then use methods on this binding's self... pretty ugly!!
what am I not seeing in here  Undecided
thanks!
L-P
Re: ruby-processing environment
Reply #1 - Mar 30th, 2009, 5:47pm
 
Hi L-P.

This is the one portion of the current API that I'm quite conflicted about. Here's the backstory:

The Processing methods (stroke, fill, width, etc) are not actually global functions ... it's simply that the magic of Java's inner classes give all inner classes access to the methods defined in the enclosing instance. Ruby does not work this way in the slightest.  Inner classes in Ruby are just ordinary classes that happened to be scoped to the enclosing class. They have no special access to variables or methods outside of themselves.

So, this presents us with two alternatives, the first -- what Ruby-Processing currently does -- is to do nothing, preserving the traditional Ruby-way of doing things. The other option would be to do something fancy with method_missing to forward all method calls that hit the top scope on to the current Processing sketch. The unruby-ness and performance implications of this approach make me reluctant to implement it. So, for now, if you want to call methods on the sketch from another class, the easiest thing is just to use the convenient global variable, $app, to do it.

I'll take a peek at how slow the method_missing alternative is, and maybe we'll get that in 1.0.6. If anyone has a better idea of how to implement it ... please chime in.
Re: ruby-processing environment
Reply #2 - Mar 30th, 2009, 8:50pm
 
what do you think of implementing it with mixins?  its ruby's answer to many programming puzzle, one of ruby's strenght that is.  Something like:

module ProcessingApiRuby
     CENTER = Processing::App::CENTER
     
     def rectMode(mode)
           $app.rectmode(mode)
     end
       # and else... method mapping example
end

wrapping all the Processing api, then only needing:

include ProcessingApiRuby

in your class to be able to call all Processing methods locally:

class Car
 include ProcessingApiRuby
 def display
   stroke 0
   fill @c
   rectMode CENTER
   rect @xpos, @ypos, 20, 10
 end
end

isn't that nice?

Re: ruby-processing environment
Reply #3 - Mar 30th, 2009, 9:20pm
 
a simple way to build over the $app var could be to play with eval like this:

module ProcessingApiRuby
 %w[stroke fill rectMode rect].each do |generic|
 eval("def #{generic}(*args); $app.#{generic}(*args); end\n")
end
# this is not a complete working example again,
# but its working code..

Re: ruby-processing environment
Reply #4 - Mar 31st, 2009, 8:53am
 
That automatic eval might work pretty nicely. I'll play around with trying to get something like that to work for every inner class (we can detect them). Thanks.
Re: ruby-processing environment
Reply #5 - Mar 31st, 2009, 9:17am
 
would be nice to have some for 1.0.6!!!
btw, ruby-processing really rocks!!
Thanks!
Re: ruby-processing environment
Reply #6 - Apr 1st, 2009, 7:56pm
 
Yo L-P.

I've got an implementation of faux inner classes working, but before I even think about releasing a 1.0.6, I'd like you to take a look. Check out:

http://github.com/jashkenas/ruby-processing/blob/7fa347f188591ba25aa4a6441a7b16bebfef3e84/lib/ruby-processing/app.rb

Towards the bottom you'll find the Processing::Proxy module, which is used by mix_proxy_into_inner_classes method a little higher up inside the App. Give it a spin if you'd like, and let me know what you think.
Re: ruby-processing environment
Reply #7 - Apr 2nd, 2009, 10:12am
 
pretty clever hack!!
I didn't knew about this "included" method, and truly I'll need to read more about it before I really understand what it's doing...

so, here are the cues I can give you as a tester:

First, It worked!!, but not all methods seems to be present? (this may be intentionnal I don't know) like, I had a rectMode in my small test and I needed to call it from $app for it to work, but other methods like stroke, fill, rect all worked fine.

Second, constants like CENTER, kinda cutted the impression my nested class had access to the nesting class scope, because I still needed to access them with the fully qualified name Processing::App::CENTER.

Last, I really like the way this makes nested class behave like it would in the Java Processing API.  Transparent and natural to the user, really a great gain!!!

My only remaining question was about building classes as generic external widgets libraries...  I then realized I could simply "include Processing::Proxy" in my external class and voilà!  That simple trick would make it Processing aware, allowing sketch independent classes to be built and used as libraries.

Remarkable step I think,
Big cheer for Jashkenas!

p.s. my test was on a really simple example, involving only one nested class, then moved it to be an external required class... so it cannot be considered really extensive testing, I would doubt more complex scenarios would break the hack, but I will try to break it anyway when I get more time to do so later today.
Re: ruby-processing environment
Reply #8 - Apr 2nd, 2009, 7:25pm
 
Thanks for the testing, L-P.

In the version you tried, I was only proxying the rubyish under_scored method names, and not their camelCased cousins. That why rectMode didn't work, but rect_mode would have. You're right, though, and if we're going to support them at all, it should be in both places, and proxying all of them as well only adds a fraction of a second to start-up time, so they are in now, along with the rest.

Good point about the constants. I added a method that proxies all of the constants into the Processing::Proxy as well. You can use CENTER, P3D, RETURN, PVector, and the rest now.

Is there anything we're still missing?
Re: ruby-processing environment
Reply #9 - Apr 5th, 2009, 11:17am
 
Okay, 1.0.6 is out, with inner classes and a couple of other patches. Thanks for helping make it happen.
Re: ruby-processing environment
Reply #10 - Apr 5th, 2009, 4:12pm
 
great it's out!! Thanks!!!

I was coming back in here to tell you about some more testing I finally had time to do, seems like I come too late... damn, why have I been so lazy to wait that long to test!!! seems like there are still a couple of methods missing, the one I was able to identify were 'height' and 'width'... but there may be more, as I am still not a processing power-user...

L-P
Re: ruby-processing environment
Reply #11 - Apr 5th, 2009, 10:35pm
 
very nice indeed. in case anyone else is wondering what this is about, here's a most simple example:

Code:

# Inner Test

class InnerTest < Processing::App

def setup
@test = Test.new
end

def draw
@test.drawTest
end

class Test
# the inner class Test, which now can call
# the outer PApplets "rect" function

def drawTest
rect 20, 20, 100, 100
end

end

end


InnerTest.new :title => "Inner Test"


F
Re: ruby-processing environment
Reply #12 - Apr 8th, 2009, 9:44am
 
to add to what you said, using the same example, you can also alternately do the magic with mixins, with the class in a separate file like this:

class in separate file:
Code:

# test.rb

class Test
 include Processing::Proxy
 # the include bring the Processing methods as mixins
 
    def drawTest
rect 20, 20, 100, 100
    end
 
 end


main Processing:
Code:

require 'test'
class MixinsTest < Processing::App

 def setup
   @test = Test.new
 end
 
 def draw
   @test.drawTest
 end
 
end

MixinsTest.new :title => "Inner Test"



L-P
Re: ruby-processing environment
Reply #13 - Apr 8th, 2009, 1:40pm
 
If either of you notice any more methods that should be available on the proxy (besides width and height), post 'em to this thread, and they'll make it in the next release.
Re: ruby-processing environment
Reply #14 - Apr 22nd, 2009, 6:48pm
 
Okay. 1.0.7 is out, and with it, proxied width and height methods.
Page Index Toggle Pages: 1