Externally scoped variables in IronPython delegates - delegates

In IronPython, I can't seem to get a variable from outside a delegate's scope to change (or even appear) inside its scope. This is contrary to what I can do in both C# and Python.
In C#, I could do the following (contrived) example:
public delegate bool Del(int index);
public static void Main() {
int itemTally = 0;
Del d = delegate (int index) {
itemTally += 3;
return true;
};
for (int i = 4; i < 6; i++) {
d.Invoke(i);
}
Console.WriteLine(itemTally); // prints 6
}
I can do the same thing in Python:
item_tally = 0
def delegate(index):
global item_tally
item_tally += 3
for x in range(4, 6):
delegate(x)
print(item_tally) # prints 6
but changing a Python variable in a Python delegate called by C# will crash:
public class BatchProcessor {
public delegate bool Del(int index);
public static int ProcessBatches(Del the_delegate) {
int batchTally = 0;
for (int i = 4; i < 6; i++) {
the_delegate(i);
batchTally++;
}
return batchTally;
}
}
import BatchProcessor
item_tally = 0
def delegate(index):
global item_tally
item_tally += 3 # "global name 'total_count' is not defined"
return True
batch_tally = BatchProcessor.ProcessBatches(BatchProcessor.Del(delegate))
print(item_tally)
Is there a way to increment total_count in the Python delegate without changing any C#?

Adding an extra global line to the IronPython in the scope outside the delegate got it working. That line wasn't necessary in the Python-only version:
public class BatchProcessor {
public delegate bool Del(int index);
public static int ProcessBatches(Del the_delegate) {
int batchTally = 0;
for (int i = 4; i < 6; i++) {
the_delegate(i);
batchTally++;
}
return batchTally;
}
}
import BatchProcessor
global item_tally # Adding this line made it work.
item_tally = 0
def delegate(index):
global item_tally # You need to keep this line, too.
item_tally += 3
return True
batch_tally = BatchProcessor.ProcessBatches(BatchProcessor.Del(delegate))
print(item_tally) # prints 6

Related

ORA-06575: Package or function BUBBLESORT is in an invalid state

I've written a bubble sort algorithm in Java and I'm trying to get it to run on Oracle 21c and I get ORA-06575: Package or function BUBBLESORT is in an invalid state
I'll state below the steps that I took in order to get to this error.
The BubbleSort.java file has this contents
public class BubbleSort {
public static void main() {
int[] nums = new int[10000];
for (int i = 0; i < nums.length; i++) {
nums[i] = (int) (Math.random() * 10000);
}
boolean swapped;
int tmp;
do {
swapped = false;
for (int i = 1; i < nums.length; ++i) {
if (nums[i - 1] > nums[i]) {
tmp = nums[i];
nums[i] = nums[i - 1];
nums[i - 1] = tmp;
swapped = true;
}
}
} while (swapped);
}
}
I've loaded it with loadjava and got the following response
loading : class BubbleSort
resolving: class BubbleSort
Classes Loaded: 1
Resources Loaded: 0
Sources Loaded: 0
Published Interfaces: 0
Classes generated: 0
Classes skipped: 0
Synonyms Created: 0
Errors: 0
After that I made a procedure using this statement
create or replace procedure BubbleSort
as language java name 'BubbleSort.main()';
/
When I try to call it using the call BubbleSort(); statement, it throws a ORA-06575: Package or function BUBBLESORT is in an invalid state
As a first debugging step I looked in user_errors and got this
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
;
The symbol ";" was substituted for "end-of-file" to continue.
What should I do to solve this error?
Change the method name to something other than main:
CREATE AND COMPILE JAVA SOURCE NAMED BubbleSortJava AS
public class BubbleSort {
private static final int ARRAY_SIZE = 10000;
public static void sort() {
int[] nums = new int[ARRAY_SIZE];
for (int i = 0; i < ARRAY_SIZE; i++) {
nums[i] = (int) (Math.random() * 10000);
}
boolean swapped;
int tmp;
do {
swapped = false;
for (int i = 1; i < ARRAY_SIZE; ++i) {
if (nums[i - 1] > nums[i]) {
tmp = nums[i];
nums[i] = nums[i - 1];
nums[i - 1] = tmp;
swapped = true;
}
}
} while (swapped);
}
}
/
Then:
CREATE PROCEDURE BubbleSort
as language java name 'BubbleSort.sort()';
/
Then:
SELECT * FROM USER_ERRORS;
Shows no errors, and:
BEGIN
BubbleSort();
END;
/
Works
If you want to pass in an array to sort then:
CREATE TYPE number_list AS TABLE OF NUMBER;
and:
CREATE AND COMPILE JAVA SOURCE NAMED BubbleSortJava2 AS
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Array;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.driver.OracleDriver;
public class BubbleSort2 {
public static Array sort(Array p_values) throws SQLException
{
BigDecimal[] values = (BigDecimal[]) p_values.getArray();
boolean swapped;
BigDecimal tmp;
do {
swapped = false;
for (int i = 1; i < values.length; ++i) {
if (
values[i - 1] != null
&& (values[i] == null || values[i - 1].compareTo(values[i]) == 1)
)
{
tmp = values[i];
values[i] = values[i - 1];
values[i - 1] = tmp;
swapped = true;
}
}
} while (swapped);
OracleConnection conn = (OracleConnection) new OracleDriver().defaultConnection();
return conn.createOracleArray("NUMBER_LIST", values);
}
}
/
CREATE FUNCTION BubbleSort2(p_values IN number_list) RETURN number_list
AS LANGUAGE JAVA NAME 'BubbleSort2.sort(java.sql.Array) return java.sql.Array';
/
Then:
SELECT *
FROM TABLE(BubbleSort2(number_list(3,5,4,2,1)));
Outputs:
COLUMN_VALUE
1
2
3
4
5
fiddle

unable to create second deck from same code for a queue

I have to set up a queue class that implements from a deque class. I need to use this to set up two deck cards with a random order. I have the code below, it works when the first deck is created but for some reason it does not work with the second deck, its the same code that im reusing.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at prog.pkg4.Deque.insertOnBack(Prog4.java:93)
at prog.pkg4.Queue.insert(Prog4.java:153)
at prog.pkg4.Prog4.createDeck(Prog4.java:465)
at prog.pkg4.Prog4.topTrump(Prog4.java:444)
at prog.pkg4.Prog4.main(Prog4.java:287)
initiates the two decks
Queue player = new Queue();
Queue computer = new Queue();
player = createDeck(player, cards);
computer = createDeck(computer, cards);
code to create random deck
public static Queue createDeck(Queue queue, GreekHero[] cards){
Random rand = new Random();
int temp = 0;
int r;
for(int i = 0; i < 30; i++){
r = rand.nextInt(30);
cards[temp] = cards[i];
cards[i] = cards[r];
cards[r] = cards[temp];
}
for(int i = 0; i < 29; i++){
queue.insert(cards[i]);
System.out.println(queue.insertions());
System.out.println(queue);
}
return queue;
}
class Queue{
private Deque queue;
public Queue(){
queue = new Deque();
}
public void insert(Object o){
queue.insertOnBack(o);
}
public Object delete(){
return queue.deleteFromFront();
}
public boolean isEmpty(){
return queue.isEmpty();
}
public String toString(){
return queue.toString();
}
public int insertions(){
return queue.getInsertions();
}
}
i've tested out the deque code several times i know it works, as demonstrated by the first deck that is created, im just not sure what could be causing the problem for the second deck.
EDIT: I've added the Deque class code below, the way i have this set up is that if the number of insertions equals the size of the array, it should double in size, as mentioned before it works with the first deque but on the second deque it stops at size of array - 1. I've increased the size to test out and I could make it bigger to satisfy this project but I need to create a deque with an increasing array.
class Deque{
private Object[] arrayObject;
private int beggining; //tracks first element in array
private int insertions; //counts the items in the array
private static int SIZE = 30; //size of array
public Deque(){
arrayObject = new Object[SIZE];
beggining = 0;
insertions = 0;
}
// displays position of first element in circular array
public Object getBeggining(){
int temp = beggining + 1;
if(temp == SIZE)
temp = 0;
return temp;
}
public int getInsertions(){
return insertions;
}
public Object indexOne(){
int temp = beggining + 1;
if(temp == SIZE)
temp = 0;
return arrayObject[temp];
}
public String toString(){
if(isEmpty())
return "Empty";
int temp = beggining + 1;
if( temp >= SIZE)
temp = 0;
String s = "Current Index:\n[("+arrayObject[temp]+")";
int loops = 0;
for(int i = temp + 1; loops < insertions - 1; i++){
if(i >= SIZE)
i = 0;
s += ", ("+arrayObject[i]+")";
loops++;
}
s += "]";
return s;
}
public String toStore(){
String s = "Store Index:\n[(1: "+arrayObject[1]+")";
for(int i = 1; i <= SIZE - 1; i++)
s += ", ("+(i+1)+": "+arrayObject[i]+")";
s += "]";
return s;
}
public void insertOnFront(Object o){
if(insertions == SIZE)
arrayObject = increaseArray();
arrayObject[beggining] = o;
beggining--;
if(beggining < 0)
beggining = SIZE - 1;
insertions++;
}
public Object deleteFromFront(){
if(isEmpty())
return null;
int count = beggining + 1;
if(count >= SIZE)
count = 0;
Object temp = arrayObject[count];
beggining += 1;
insertions--;
if(insertions > 0)
insertions = 0;
return temp;
}
public void insertOnBack(Object o){
int temp = beggining + insertions + 1;
if(insertions == SIZE - 1)
arrayObject = increaseArray();
if(temp >= SIZE)
temp = 0 + (temp - SIZE);
arrayObject[temp] = o;
insertions++;
}
public Object deleteFromBack(){
if(isEmpty())
return null;
int count = beggining + insertions;
Object temp = arrayObject[count];
insertions--;
if(insertions >= 0)
insertions = 0;
return temp;
}
public boolean isEmpty(){
if(insertions > 0)
return false;
else
return true;
}
public Object[] increaseArray(){
SIZE *= 2;
int loops = 0;
int j = beggining;
Object[] newArray = new Object[SIZE];
for(int i = j; loops <= SIZE/2; i++){
if(j >= SIZE/2)
j = 0;
newArray[i] = arrayObject[j];
loops++;
j++;
}
return newArray;
}
}
I solved the issue by moving the SIZE variable as an instance variable of the class and removed static from it. I don't know why the issue popped in on the second iteration rather than on the first try, ill look it up later, if anyone knows please post it here.

Unable to use super command

I have the following class extension:
public class Compute1 extends Compute_node{
private static final Long[] P = new Long[18];
// Constructor, string key.
public Compute1( String keyStr )
{
super( 0, 8 );
setKey( keyStr );
}
public void setKey( integer key )
{
integer i, j, k;
long data;
integer N = 16;
// Initialize P and S.
for ( i = 0; i < N + 2; ++i ){
P[i] = Pinit[i];
}
// XOR the key into P.
j = 0;
for ( i = 0; i < N + 2; ++i )
{
data = 0;
for ( k = 0; k < 4; ++k )
{
data = ( data << 8 ) ;
++j;
}
P[i] ^= data;
}
}
private static final long[] Pinit = new Long[] {
604135516L, 2242044355L, 320440478L , 57401183L,
2732047618L, 698298832L, 137296536L , 3964563569L,
1163258022L, 954160567L, 3193502383L, 887688400L,
3234508543L, 3380367581L, 1065660069L, 3041631479L,
2420952273L, 2306437331L
};
}
but im getting an error:
Error: Compile Error: Method does not exist or incorrect signature: [Compute_node].(Integer, Integer) at line 11 column 5
at:
super( 0, 8 );
why cant I use the super keyword here?
I am using an extension!
And I do have a Compute_node class!
Thanks
The super() keyword borrows its parent class' constructor. You need to look at Compute_node's constructor and make sure that its parameters match the ones you are passing through super(). For instance, if your constructor in Compute_node is
public Compute_node(int a) {
//code
}
Then you will absolutely get an error saying that the method Compute_node(Integer, Integer) doesn't exist. For a better answer, edit your question with the source to Compute_node.

array assignment issue

I am getting a incompatible types required int found:void on this line
--> moneyCount = countDemoninations(change, denomination[i]). trying to understand why?
public class Change {
int [] denomination = {1,2,5,10,20,50,100,200,500,1000,2000,5000};
int moneyCount = 0;
public void catagorizeChange(int change){
for (int i = 0; i < denomination.length; i++){
moneyCount = countDemoninations(change, denomination[i]);
}
}
public void countDemoninations(int change, int denomination){
int moneyCount =0;
while (change >= denomination){
moneyCount = moneyCount++;
change = change - denomination;
}
}
}
I'm a new java student, I want to know if the following edited code below in a good practice i.e have one method used in another where both belong to the same class?
public void countChangedenominations (int change){
for (int i = 0; i < moneyValuearray.length; i++){
moneyCountarray[i] = countDemonination(change, moneyValuearray[i]);
}
}
public int countDemonination(int change, int denomination){
while (change >= denomination){
moneyCount = ++moneyCount;
change = change - denomination;
}
return moneyCount;
The source of the problem with the line:
moneyCount = countDemoninations(change, denomination[i]);
is that countDemoninations is of type void, whereas moneyCount is of type int.
To solve the issue, change your countDemoninations method signature to return int instead of void, then return moneyCount as the last statement in your method:
public int countDemoninations( int change, int denomination ) {
int moneyCount = 0;
while ( change >= denomination ) {
moneyCount = moneyCount++;
change = change - denomination;
}
return moneyCount;
}

Performance of Mass-Evaluating Expressions in IronPython

In an C#-4.0 application, I have a Dictionary of strongly typed ILists having the same length - a dynamically strongly typed column based table.
I want the user to provide one or more (python-)expressions based on the available columns that will be aggregated over all rows. In a static context it would be:
IDictionary<string, IList> table;
// ...
IList<int> a = table["a"] as IList<int>;
IList<int> b = table["b"] as IList<int>;
double sum = 0;
for (int i = 0; i < n; i++)
sum += (double)a[i] / b[i]; // Expression to sum up
For n = 10^7 this runs in 0.270 sec on my laptop (win7 x64). Replacing the expression by a delegate with two int arguments it takes 0.580 sec, for a nontyped delegate 1.19 sec.
Creating the delegate from IronPython with
IDictionary<string, IList> table;
// ...
var options = new Dictionary<string, object>();
options["DivisionOptions"] = PythonDivisionOptions.New;
var engine = Python.CreateEngine(options);
string expr = "a / b";
Func<int, int, double> f = engine.Execute("lambda a, b : " + expr);
IList<int> a = table["a"] as IList<int>;
IList<int> b = table["b"] as IList<int>;
double sum = 0;
for (int i = 0; i < n; i++)
sum += f(a[i], b[i]);
it takes 3.2 sec (and 5.1 sec with Func<object, object, object>) - factor 4 to 5.5. Is this the expected overhead for what I'm doing? What could be improved?
If I have many columns, the approach chosen above will not be sufficient any more. One solution could be to determine the required columns for each expression and use only those as arguments. The other solution I've unsuccessfully tried was using a ScriptScope and dynamically resolve the columns. For that I defined a RowIterator that has a RowIndex for the active row and a property for each column.
class RowIterator
{
IList<int> la;
IList<int> lb;
public RowIterator(IList<int> a, IList<int> b)
{
this.la = a;
this.lb = b;
}
public int RowIndex { get; set; }
public int a { get { return la[RowIndex]; } }
public int b { get { return lb[RowIndex]; } }
}
A ScriptScope can be created from a IDynamicMetaObjectProvider, which I expected to be implemented by C#'s dynamic - but at runtime engine.CreateScope(IDictionary) is trying to be called, which fails.
dynamic iterator = new RowIterator(a, b) as dynamic;
var scope = engine.CreateScope(iterator);
var expr = engine.CreateScriptSourceFromString("a / b").Compile();
double sum = 0;
for (int i = 0; i < n; i++)
{
iterator.Index = i;
sum += expr.Execute<double>(scope);
}
Next I tried to let RowIterator inherit from DynamicObject and made it to a running example - with terrible performance: 158 sec.
class DynamicRowIterator : DynamicObject
{
Dictionary<string, object> members = new Dictionary<string, object>();
IList<int> la;
IList<int> lb;
public DynamicRowIterator(IList<int> a, IList<int> b)
{
this.la = a;
this.lb = b;
}
public int RowIndex { get; set; }
public int a { get { return la[RowIndex]; } }
public int b { get { return lb[RowIndex]; } }
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (binder.Name == "a") // Why does this happen?
{
result = this.a;
return true;
}
if (binder.Name == "b")
{
result = this.b;
return true;
}
if (base.TryGetMember(binder, out result))
return true;
if (members.TryGetValue(binder.Name, out result))
return true;
return false;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (base.TrySetMember(binder, value))
return true;
members[binder.Name] = value;
return true;
}
}
I was surprised that TryGetMember is called with the name of the properties. From the documentation I would have expected that TryGetMember would only be called for undefined properties.
Probably for a sensible performance I would need to implement IDynamicMetaObjectProvider for my RowIterator to make use of dynamic CallSites, but couldn't find a suited example for me to start with. In my experiments I didn't know how to handle __builtins__ in BindGetMember:
class Iterator : IDynamicMetaObjectProvider
{
IList<int> la;
IList<int> lb;
public Iterator(IList<int> a, IList<int> b)
{
this.la = a;
this.lb = b;
}
public int RowIndex { get; set; }
public int a { get { return la[RowIndex]; } }
public int b { get { return lb[RowIndex]; } }
public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new MetaObject(parameter, this);
}
private class MetaObject : DynamicMetaObject
{
internal MetaObject(Expression parameter, Iterator self)
: base(parameter, BindingRestrictions.Empty, self) { }
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
switch (binder.Name)
{
case "a":
case "b":
Type type = typeof(Iterator);
string methodName = binder.Name;
Expression[] parameters = new Expression[]
{
Expression.Constant(binder.Name)
};
return new DynamicMetaObject(
Expression.Call(
Expression.Convert(Expression, LimitType),
type.GetMethod(methodName),
parameters),
BindingRestrictions.GetTypeRestriction(Expression, LimitType));
default:
return base.BindGetMember(binder);
}
}
}
}
I'm sure my code above is suboptimal, at least it doesn't handle the IDictionary of columns yet. I would be grateful for any advices on how to improve design and/or performance.
I also compared the performance of IronPython against a C# implementation. The expression is simple, just adding the values of two arrays at a specified index. Accessing the arrays directly provides the base line and theoretical optimum. Accessing the values via a symbol dictionary has still acceptable performance.
The third test creates a delegate from a naive (and bad by intend) expression tree without any fancy stuff like call-side caching, but it's still faster than IronPython.
Scripting the expression via IronPython takes the most time. My profiler shows me that most time is spent in PythonOps.GetVariable, PythonDictionary.TryGetValue and PythonOps.TryGetBoundAttr. I think there's room for improvement.
Timings:
Direct: 00:00:00.0052680
via Dictionary: 00:00:00.5577922
Compiled Delegate: 00:00:03.2733377
Scripted: 00:00:09.0485515
Here's the code:
public static void PythonBenchmark()
{
var engine = Python.CreateEngine();
int iterations = 1000;
int count = 10000;
int[] a = Enumerable.Range(0, count).ToArray();
int[] b = Enumerable.Range(0, count).ToArray();
Dictionary<string, object> symbols = new Dictionary<string, object> { { "a", a }, { "b", b } };
Func<int, object> calculate = engine.Execute("lambda i: a[i] + b[i]", engine.CreateScope(symbols));
var sw = Stopwatch.StartNew();
int sum = 0;
for (int iteration = 0; iteration < iterations; iteration++)
{
for (int i = 0; i < count; i++)
{
sum += a[i] + b[i];
}
}
Console.WriteLine("Direct: " + sw.Elapsed);
sw.Restart();
for (int iteration = 0; iteration < iterations; iteration++)
{
for (int i = 0; i < count; i++)
{
sum += ((int[])symbols["a"])[i] + ((int[])symbols["b"])[i];
}
}
Console.WriteLine("via Dictionary: " + sw.Elapsed);
var indexExpression = Expression.Parameter(typeof(int), "index");
var indexerMethod = typeof(IList<int>).GetMethod("get_Item");
var lookupMethod = typeof(IDictionary<string, object>).GetMethod("get_Item");
Func<string, Expression> getSymbolExpression = symbol => Expression.Call(Expression.Constant(symbols), lookupMethod, Expression.Constant(symbol));
var addExpression = Expression.Add(
Expression.Call(Expression.Convert(getSymbolExpression("a"), typeof(IList<int>)), indexerMethod, indexExpression),
Expression.Call(Expression.Convert(getSymbolExpression("b"), typeof(IList<int>)), indexerMethod, indexExpression));
var compiledFunc = Expression.Lambda<Func<int, object>>(Expression.Convert(addExpression, typeof(object)), indexExpression).Compile();
sw.Restart();
for (int iteration = 0; iteration < iterations; iteration++)
{
for (int i = 0; i < count; i++)
{
sum += (int)compiledFunc(i);
}
}
Console.WriteLine("Compiled Delegate: " + sw.Elapsed);
sw.Restart();
for (int iteration = 0; iteration < iterations; iteration++)
{
for (int i = 0; i < count; i++)
{
sum += (int)calculate(i);
}
}
Console.WriteLine("Scripted: " + sw.Elapsed);
Console.WriteLine(sum); // make sure cannot be optimized away
}
Although I don't know all the specific details in your case, a slowdown of only 5x for doing anything this low level in IronPython is actually pretty good. Most entries in the Computer Languages Benchmark Game show a 10-30x slowdown.
A major part of the reason is that IronPython has to allow for the possibility that you've done something sneaky at runtime, and thus can't produce code of the same efficiency.

Resources