public static Delegate defun(Object[][] args, DelegateBody body) {
		final NonLocalClosure<Object[][]> arguments = closeOverNonLocal(args);
		final NonLocalClosure<DelegateBody> fn = closeOverNonLocal(body);
		return new DynamicDelegateBase() {
			
			Hashtable<Integer, String> reference;
			
			@Override
			protected void initVariables() {
				reference = new Hashtable<Integer, String>();
				Object[][] a = arguments.getActualValue();
				for (int i = 0; i < a.length; i++) {
					reference.put(i, getDynamicVariableName(a[i]));
				}
				let(this, arguments.getActualValue());
			}
			@Override
			public DynamicDelegate copy() {
				return (DynamicDelegate)clone();
			}
			@Override
			public Object clone() {
				DynamicDelegateBase bn = (DynamicDelegateBase) this;
				final Closure<DynamicDelegateBase> _fn = closeOver(bn);
				return new DynamicDelegateBase(this) {
					
					@Override
					protected void initVariables() {
						//nothing special to init as that is handled by the copy method
					}
					
					@Override
					public DynamicDelegate copy() {
						return _fn.getValue().copy(); //elegant hack
						//we have the outer scope copy instance called from the inner
						//scope to prevent infinite loops. This may seem like an infinite
						//loop would occur but the reality is that copy will only be called once
						//but the same function will be provided, this has the side effect of preventing
						//recursive class calls as well.
					}
					@Override
					public Object clone() {
						return _fn.getValue().clone();
					}
					
					public Object invoke(DynamicDelegate localVariables, Object[] input) {
						return _fn.getValue().invoke(localVariables, input);
					}
					
					public Object invoke(DynamicDelegate localVariables) {
						return _fn.getValue().invoke(localVariables);
					}
					
					public Object invoke() {
						return invoke(this);
					}
					
					public Object invoke(Object[] input) {
						return invoke(this, input);
					}
					
					public void run() {
						_fn.getValue().run();
					}
					
					public void run(DynamicDelegate localVariables) {
						_fn.setValue(this);
					}
				};
			}
			
			public Object invoke(DynamicDelegate localVariables, Object[] input)
			{
				try {
					DynamicDelegate body = copy();
					for (int i = 0; i < input.length; i++) {
						body.setDynamicVariable(reference.get(i), input[i]);
					}
					return body.invoke(body);
				} catch (DynamicVariableReadonlyException d) {
					return null;
				}
			}
			
			public Object invoke(DynamicDelegate localVariables) {
				return fn.getActualValue().invoke(localVariables);
			}
			
			public Object invoke() {
				return invoke(this);
			}
			
			public Object invoke(Object[] input) {
				return invoke(this, input);
			}
			
			public void run() {
				run(this);
			}
			
			public void run(DynamicDelegate localVariables) {
				fn.getActualValue().run(localVariables);
			}
		};
	}