cbuschka / beanshell2

Automatically exported from code.google.com/p/beanshell2
0 stars 0 forks source link

Namespaces can't be properly chained #74

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
It turns out that BeanShell2 doesn't allow me to create arbitrary namespace 
chains. I'm using multiple Interpreter instances, but I can't for instance 
construct namespace chain with 3 nodes. It seems I'm only able to create a 
local/function and a global namespace and link them together, but I need to 
create three chained namespaces: A global namespace, a "per image" namespace 
and the "function" namespace. The API seems to allow arbitrarily chained 
namespaces (I can write the code I need) but when investigating the resulting 
namespace chain, it has been rechained to two levels only. Are you able to fix 
this? It would open up the ability to significantly accelerate album builds in 
jAlbum as I will then be able to execute multiple scripts simultaneously.

I've been using the most current version of BeanShell2 on Mac OSX (Java 1.6)

Original issue reported on code.google.com by david@jalbum.net on 21 Aug 2012 at 4:30

GoogleCodeExporter commented 8 years ago
Can I have feedback on this please.

Original comment by david@jalbum.net on 31 Aug 2012 at 9:24

GoogleCodeExporter commented 8 years ago
Could you provide your test/example code?

Original comment by pejob...@gmail.com on 31 Aug 2012 at 12:38

GoogleCodeExporter commented 8 years ago
Sure. The attached beanshell script will demonstrate the error. It first sets 
up a convenience function that creates "child" interpreters that have a 
namespace who's parent is the namespace of the passed in argument.

The example then sets up two interpreters, a "root" and a "child" interpreter.

Then a global "bar=42;" is evaluated with the root interpreter and a local 
"bar=4711;" is evaluated with the child interpreter

Then, a foo() function is declared within using the root interpreter. This 
function simply prints bar and also prints the name of the current and parent 
namespace

Finally, foo() is called both via the root interpreter and via the child 
interpreter. When called via the root interpreter, foo() correctly prints 42, 
but when called via the child interpreter it should print 4711, but actually 
prints 42. The following debug printout explains the mystery, the function's 
namespace has been parented to the root instead of being parented with the 
namespace where it was called (child's namespace).

I simply wish for the namespaces of functions to be parented with the namespace 
where they are called from instead of being hard coded to be parented to the 
root's namespace.

With this change, I will be able to have multithreaded script execution and 
speed up our jAlbum application considerably, where each thread has its own 
interpreter and local scope for image specific variables and the ability to 
call functions, originally declared via the root interpreter, but with the 
ability to refer to image specific variables in the local scope. I hope what 
I'm saying makes sense. In my sample code  we should end up with a 3 level deep 
namespace chain: The root namespace, the image specific namespace and the 
method/function namespace. Compare to the "method", "class" and "global" 
namespace levels when doing OO in BeanShell - it's not a unique concept at all 
and BeanShell's namespaces allow for arbitrary depths already so I think this 
just requires a minimal change to the code that sets up the namespace for 
functions

Regards
/David

Original comment by david@jalbum.net on 1 Sep 2012 at 10:21

Attachments:

GoogleCodeExporter commented 8 years ago
Any comments on this?

Original comment by david@jalbum.net on 7 Sep 2012 at 1:25

GoogleCodeExporter commented 8 years ago
I'm not soure your expectation is correct. Do you see a regression from 
original beanshell? If so i didn't spot the difference..

If it's not a regression: Could you explain your use-case in more detail?

Original comment by pejob...@gmail.com on 9 Sep 2012 at 3:08

GoogleCodeExporter commented 8 years ago
No, BeanShell2 behaves just like classic BeanShell. I just wish to see a change 
in how the parent namespace of methods is picked so it uses the namespace of 
the _caller_ instead of the namespace where the method is _declared_. That 
would make BeanShell a truly dynamic late-binding interpreted language. Now 
it's a mix of late and early binding (namespaces are early-bound while 
variables are late-bound)

Original comment by david@jalbum.net on 10 Sep 2012 at 12:36

GoogleCodeExporter commented 8 years ago
I can't spot the "mix". The method you define sees the variables of the 
namespace it's defined in (and the variables of parent namespaces of course). 
If you want global defined methods operating on locally defined variables you 
should pass these variables as arguments.

Perhaps you could find an alternative solution to your problem when looking at 
the source of provided commands which fiddle with namespaces (i.e. "bind.bsh", 
"eval.bsh", or "extend.bsh")?

Anyway, altering the way binding works would break existing beanshell code. So 
I change the status to 'invalid' for now. If there are any new arguments I'm 
happy to change this, so don't be discouraged adding further comments.

Original comment by pejob...@gmail.com on 10 Sep 2012 at 1:21

GoogleCodeExporter commented 8 years ago
We have 10 years of existing 3:rd party BeanShell code in jAlbum skins that are 
made by our open source community. Many of these skins refer to image specific 
variables within functions (i.e. not passed as arguments). These skins would 
break if we try to implement multi threaded script processing using multiple 
interpreter objects due to the current design of BeanShell (which is the 
classic design for a statically bound language). It works today with one 
interpreter as we simulate image specific namespaces by adding and removing 
image specific variables to the one single global namespace as we iterate 
through images in one thread. Apart from being a rather ugly approach, it also 
limits us to using one interpreter object as it would create a mess to add and 
remove variables from multiple threads in one single interpreter's namespace.

If we started with a clean slate, the design could be made different. One could 
then declare support functions that need to refer to image specific variables 
in a certain way, but we don't have the luxury to rewrite skins produced over a 
10 year span just to enjoy multi threaded script processing. However, with this 
proposed change to BeanShell that would make it fully dynamic, we can keep 
compatibility with legacy code AND enjoy multi threaded script processing.

(Passing local variables as parameters can be a hazzle as these support 
functions usually refer to A LOT of image specific variables - usually camera 
specific EXIF data)

Original comment by david@jalbum.net on 10 Sep 2012 at 1:56