Error while accessing private array inside class - swift4.1

I am getting an error message when I try to access the private array (arr) inside the class (MyArray). What I am trying to achieve is to create a closure for reversing the array contents and this closure can be called from outside the class using instance variables. I am not able to understand this error. Can someone please help !!
public class MyArray {
private var arr: [Int] = []
internal static var instance: MyArray?
public var reverse = { () -> [Int] in
var returnArray : [Int] = []
var counter = arr.count - 1 // Error: Instance member 'arr' cannot be used on type 'MyArray'
for _ in (0...arr.count - 1) { // Error: Instance member 'arr' cannot be used on type 'MyArray'
returnArray.append(arr[counter])
counter -= 1
}
return returnArray
}
private init() {}
public static func getInstance() -> MyArray {
if self.instance == nil {
self.instance = MyArray()
}
return self.instance!
}
}

Use a lazy property to be able to access a variable that was declared outside the closure.
sooo...
• change this public var reverse = to this public lazy var reverse =
• then add self. in front of every variable that's defined outside a closure.
Please read this: understand the lazy property
Lazy rules:
You can’t use lazy with let .
You can’t use it with computed properties .
Because, a computed property returns the value every time we try to access it after executing the code inside the computation block.
You can use lazy only with members of struct and class .
Lazy variables are not initialised atomically and so is not thread safe.

Related

Work with external array

I would like to write a method that will returns an object and puts it to external array,but array index should be increase after a method was fulfilled.
On next time, when I call method once againe,an object should wrote to neighboring cell in external array.Can you advice me any ideas or show me any examples?Thank you.
If I have correctly understood you question, you should use List<T> type for your "external array". It has Add(T item) method that allows you to add items exactly the same way as you've described. Let's say your object is of type Foo:
public void Test()
{
var externalArray = new List<Foo>();
var foo1 = MyMethod(externalArray);
var foo2 = MyMethod(externalArray);
}
public Foo MyMethod(List<Foo> list)
{
var item = new Foo();
list.Add(item);
return item;
}

Groovy: Is there a better way of handling #Immutable objects than copyWith method

I am looking for a flexible way of "modifying" (copying with some values changed) immutable objects in groovy. There is a copyWith method but it allows you only to replace some properties of the object. It doesn't seem to be convenient enough.
Let's say we have a set of classes representing a domain design of some system:
#Immutable(copyWith = true)
class Delivery {
String id
Person recipient
List<Item> items
}
#Immutable(copyWith = true)
class Person {
String name
Address address
}
#Immutable(copyWith = true)
class Address {
String street
String postalCode
}
Let's assume I need to change street of delivery recipient. In case of regular mutable object it is just fine to perform:
delivery.recipient.address.street = newStreet
or (perhaps useful in some cases):
delivery.with {recipient.address.street = newStreet}
When it comes to do the same with immutable objects the best way according to my knowledge would be:
def recipient = delivery.recipient
def address = recipient.address
delivery.copyWith(recipient:
recipient.copyWith(address:
address.copyWith(street: newStreet)))
It is actually needed for Spock integration test code so readability and expressiveness matters. The version above cannot be used "on the fly" so in order to avoid creating tons of helper methods, I have implemented my own copyOn (since copyWith was taken) method for that which makes it possible to write:
def deliveryWithNewStreet = delivery.copyOn { it.recipient.address.street = newStreet }
I wonder however if there is an ultimate solution for that, present in groovy or provided by some external library. Thanks
For the sake of completeness I provide my implementation of copyOn method. It goes as follows:
class CopyingDelegate {
static <T> T copyOn(T source, Closure closure) {
def copyingProxy = new CopyingProxy(source)
closure.call(copyingProxy)
return (T) copyingProxy.result
}
}
class CopyingProxy {
private Object nextToCopy
private Object result
private Closure copyingClosure
private final Closure simplyCopy = { instance, property, value -> instance.copyWith(createMap(property, value)) }
private final def createMap = { property, value -> def map = [:]; map.put(property, value); map }
CopyingProxy(Object nextToCopy) {
this.nextToCopy = nextToCopy
copyingClosure = simplyCopy
}
def propertyMissing(String propertyName) {
def partialCopy = copyingClosure.curry(nextToCopy, propertyName)
copyingClosure = { object, property, value ->
partialCopy(object.copyWith(createMap(property, value)))
}
nextToCopy = nextToCopy.getProperties()[propertyName]
return this
}
void setProperty(String property, Object value) {
result = copyingClosure.call(nextToCopy, property, value)
reset()
}
private void reset() {
nextToCopy = result
copyingClosure = simplyCopy
}
}
It is then just a matter of adding the delegated method in Delivery class:
Delivery copyOn(Closure closure) {
CopyingDelegate.copyOn(this, closure)
}
High level explanation:
First of all it is required to notice that the code of: delivery.recipient.address.street = newStreet is interpreted as:
Accessing recipient property of delivery object
Accessing address of what was the result of the above
Assigning property street with the value of newStreet
Of course the class CopyingProxy does not have any of those properties, so propertyMissing method will be involved.
So as you can see it is a chain of propertyMissing method invocations terminated by running setProperty.
Base case
In order to implement the desired functionality we maintain two fields: nextToCopy (which is delivery at the beginning) and copyingClosure (which is initialised as a simple copy using copyWith method provided by #Immutable(copyWith = true) transformation).
At this point if we had a simple code like delivery.copyOn { it.id = '123' } then it would be evaluated as delivery.copyWith [id:'123'] according to simplyCopy and setProperty implementations.
Recursive step
Let's now see how would it work with one more level of copying: delivery.copyOn { it.recipient.name = 'newName' }.
First of all we will set initial values of nextToCopy and copyingClosure while creating CopyingProxy object same way as in the previous example.
Let's now analyse what would happen during first propertyMissing(String propertyName) call. So we would capture current nextToCopy (delivery object), copyingClosure (simple copying based on copyWith) and propertyName (recipient) in a curried function - partialCopy.
Then this copying will be incorporated in a closure
{ object, property, value -> partialCopy(object.copyWith(createMap(property, value))) }
which becomes our new copyingClosure. In the next step this copyingClojure is invoked in the way described in Base Case part.
Conclusion
We have then executed: delivery.recipient.copyWith [name:'newName']. And then the partialCopy applied to the result of that giving us delivery.copyWith[recipient:delivery.recipient.copyWith(name:'newName')]
So it's basically a tree of copyWith method invocations.
On top of that you can see some fiddling with result field and reset function. It was required to support more than one assignments in one closure:
delivery.copyOn {
it.recipient.address.street = newStreet
it.id = 'newId'
}

Haxe / hscript - Prevent exposing certain methods to scripts

So, I've created "interface class" with all static methods, which I want to expose to hscript scripts. It looks like this:
package com.application.interfaces.Terrain;
import com.application.TerrainCore
class Terrain {
private static var terrain:TerrainCore;
public static function _init(inTerrain:TerrainCore):Void {
terrain = inTerrain;
}
public static function test(s:Int):Void {
terrain.test(s);
}
}
The problem is, that I need to set terrain object somehow, but I don't want it to be exposed to scripts. I expose whole classes with
var interp = new Interp();
var module = Type.resolveClass("com.application.interfaces.Terrain");
interp.variables.set("Terrain", module)
The idea was to override method call in hscript.Interp so it doesn't execute any method named _init, but I don't know how to do that. Original call method looks like this:
function call( o : Dynamic, f : Dynamic, args : Array<Dynamic> ) : Dynamic {
return Reflect.callMethod(o,f,args);
}
Can you use a class instance of Terrain instead of using static members? Eg:
interp.variables.set("Terrain", new Terrain(new TerrainCore()));
Script users wont know if they are using static or instance methods as it will still be access via:
Terrain.test(123);
in script.
Another option (based on clemos), is to use rtti to work out what is allowed (instead of maintaining a list of it), eg:
Terrain._init(new TerrainCore());
_init is a private function now, so you need to #:allow it from your calling class (see below), also, you need to annotate with #:rtti so you can grab info about the functions at runtime, so Terrain now looks like:
#:rtti
class Terrain {
private static var terrain:TerrainCore;
#:allow(test.hscript.demo.Main)
private static function _init(inTerrain:TerrainCore):Void {
terrain = inTerrain;
}
public static function test(s:Int):Void {
terrain.test(s);
}
}
Finally, the script interp fcall now honours whether a field is public or private, ie:
public override function fcall(o:Dynamic, f:String, args:Array<Dynamic>):Dynamic
var rtti = haxe.rtti.Rtti.getRtti(o);
for (field in rtti.statics) {
if (field.name == f && field.isPublic == false) {
error(EInvalidAccess(f));
}
}
return super.fcall(o, f, args);
}
Its worth noting that I used statics rather than fields for obvious reasons. Im also not sure what overhead this would cause with the loop and the rtti.
I believe it's fcall you should override, as call is used for toplevel calls only :
https://github.com/HaxeFoundation/hscript/blob/master/hscript/Interp.hx#L328-L331
It should be easy to filter f argument like :
if ( FORBIDDEN_FIELDS.indexOf( f ) > -1 ) throw EInvalidAccess( f );
or
if ( f.indexOf('_') == 0 ) throw EInvalidAccess( f );

intercepting LOCAL property access in groovy

I am running into a problem while trying to use property access in Groovy. Take the following class:
class Foo {
Map m = [:]
String bar
void getProperty(String name) {
m.get name
}
def setProperty(String name, value) {
m.set name, value
}
String getBarString() {
return bar // local access, does not go through getProperty()
}
}
It overrides the getter and setter to simply place the values into a Map rather than into the object's normal property space. In the abstract this is a bit silly, but imagine that instead of placing the data into a map we were persisting it to a DB or something else useful.
Unfortunately, the following code now won't work:
foo = new Foo()
foo.bar = "blerg" // using foo.bar invokes the setProperty interceptor
assert foo.bar == "blerg" // this will work fine as foo.bar here uses the getProperty interceptor
assert foo.getBarString() == "blerg" // explosion and fire! getBarString accesses bar locally without going through the getProperty interceptor so null will actually be returned.
Certainly there are workarounds for this, setProperty could set both the MetaProperty and the Map value, etc. However, all of the strategies I've thought of require a lot of extra caution from the programmer to make sure they are accessing class properties in the exact way that they mean to.
Furthermore, some of the built in awesome stuff in Groovy (like #Delegate for example) uses direct MetaProperty access rather than going through getProperty so the following would never work:
class Meep {
String getMyMeep() {
return "MEEP!!!"
}
}
class Foo {
Map m = [:]
String bar
#Delegate Meep meep
void getProperty(String name) {
m.get name
}
def setProperty(String name, value) {
m.set name, value
}
String getBarString() {
return bar
}
}
foo = new Foo()
foo.meep = new Meep() // uses setProperty and so does not place the Meep in the Map m
foo.getMyMeep()
A null pointer exception is thrown on the last line as #Delegate uses MetaProperty direct access (effectively this.meep.getMyMeep() rather than the getProperty interceptor. Unfortunately 'meep' is null, though getProperty('meep') would not be.
In short what I'm looking for is a strategy to solve the following criteria:
intercept property read/write to enable automatic alternative data storage
transparent or near-transparent interface for other developers (I don't want to make other folks' lives significantly harder)
allow for local access of variables using the MetaProperty/this/etc. access methods
Thanks in advance!
You could use
foo.#meep = new Meep()
in order to directly access properties bypassing setProperty method.
That doesn't completely solves your problem though as the foo.meep still triggers set/getProperty.
Another way you could go about is by using getter and setter of the meet directly, i.e.
foo.setMeep(new Meep())
So, one unified way would be to define all of the variables as private and use get/set*PropertyName*
By using an AST Transformation I can do the following:
walk a class's structure and rename all local fields to something like x -> x.
add a getter/setter for each renamed field like this
def get_x_() {
x
}
...in order to access x as a field rather than as a Groovy property
- now apply the transformation on the following class
class Foo {
def x
def y
Map m = [:]
#Delegate Date date // for testing if non-local fields work
def getProperty(String name) {
if (this.respondsTo("get__${name}__")) // if this is one of our custom fields
return "get__${name}__"()
"get${Verifier.capitalize(name)}"() // pass to specific getter method
}
void setProperty {
if (this.respondsTo("set__${name}__")) {
"set__${name}__"(value)
m[name] = value
if (name == "x") y = x + 1
return
}
"set${Verifier.capitalize(name)}"(value)
}
}
now run a testing method like this:
public void testAST() {
def file = new File('./src/groovy/TestExample.groovy')
GroovyClassLoader invoker = new GroovyClassLoader()
def clazz = invoker.parseClass(file)
def out = clazz.newInstance()
out.x = 10
assert out.y == 11
out.y = 5
assert out.y == 5
out.x = 2
assert out.m.containsKey('x')
assert out.m.x == 2
assert out.m.y == 3
out.date = new Date()
assert out.time && out.time > 0
}
And everything should work out including m getting updated, date delegate method time getting accessed properly, etc.
-Glenn

How to populate a List in the domain class in grails?

Hi folks
I have a map in my bootstrap.groovy, how can use this map to populate another map in my domain class?
here is the code
bootstrap.groovy
def data = [ x:'45.5',
y:'7',
z:[ z0:'2.5', z1:'3.5', z2:'4.0', z3:'3.5', z4:'5.0']
]
what code should I write here?
//some code
domain class
class target implements Serializable{
//Just for the time being
List list = new ArrayList()
}
any ideas would be appreciated
First thing is your question asks how to populate one map with another map, but you define a list in your domain. So if I'm understanding you correctly, your domain would more likely be:
class Target implements Serializable {
Map data = [:]
}
// BootStrap.groovy
import package.name.Target
class BootStrap {
def grailsApplication
def init = { servletContext ->
// no need to quote your map keys in this case
Map data = [x:"45.5", y:"7", z:[z0 :"2.5", z1:"3.5", z2:"4.0", z3:"3.5", z4:"5.0"]
Target targ = new Target()
targ.data = data.z // set Target data map to nested portion of map above
targ.data = data // set equal (could add to ctor [data:"$data"] instead)
data.each{k,v->
// do some calc that changes local map values and applies to target data map
}
// if you are unable to get a reference to Target domain, you can try
def inst = grailsApplication.getClassForName("package.name.Target").newInstance()
inst.data = data
// etc.
}
}
I believe it's better to use Grails configuration and update Config.groovy.

Resources