Do people feel that StructNew( 'weak' ) and StructNew( 'soft' ) could also benefit from clearer aliases? I’m not sure, but thought I’d put it out there.
(either way - the aliases above should be documented)
I think - unfortunately - the implementation itself needs a rethink. “weak” and “soft” are not types of structs (or, indeed types of data structures of any sort), they refer to the volatility of the reference to the data structure.
There are potentially different sorts of struct: default, ordered, sorted, etc. Those make sense to implement using the structNew() (maybe with a constant for the variation, not a string though? Different thread, I guess) variations you mention.
However one could have a weak ordered struct, or a soft array, or [whatever]. Those two are closer to access modifiers than they are to types (that is not to say they are equivalent to access modifiers; they’re just closer to those than types).
A better and more CFML-ish sort of syntax would just be to go the OO route perhaps:
myWeaklyReferencedOrderedStruct = new WeakReference({[first="one", second="two"]});
// or
myWeaklyReferencedOrderedStruct = new WeakReference(new OrderedStruct());
myWeaklyReferencedOrderedStruct.first = "one";
myWeaklyReferencedOrderedStruct.second = "two";
I realise this is not an answer to your question, but it’s perhaps something to think about in conjunction.
To comment more directly only your question: I think you should pick one alias for each construct to persist with, and document the rest, but mark them all as “deprecated” (or “not recommended”, whatever). It benefits no-one having these different variations around, IMO.
I’d be more inclined to only document the ones that we want people to use (or are compelled to support for CFML compatibility) and deprecate all the others.
By the sounds of things it might be an idea to deprecate weak and soft while we are at it.
many of the options in the source code are aliases, mostly due to typos/misspelling at first, and then correction, e.g. syncronized vs synchronized, so sure, only the ones that we want people to use should be documented.
I wouldn’t deprecate these two unless we add a Cache Type as I suggested above. even though it’s not ideal to implement in CFML, it is convenient and easy to so at times.
Well what is the act of “deprecating” if not documenting it? Either way, there needs to be a page someone can land on from a Google search when they ask themselves “WTF is this thing I am looking at in this code I have inherited?”. Even if that is SEOed sufficiently that it points to the same page as the “supported” syntax, then that’s an undertaking to be… um… under…erm…took. Undertooken. [cough].
Bottom line: whatever is currently in Lucee’s CFML needs to be documented. What shape that documentation takes, and the message it delivers is something else.
Let’s not conflate these two things. They’re not the same.
There must’ve been a reason that they were added to the language in the first place. Perhaps the planning that went into that can be shared, so we can see what the basis for the work was. I presume there was a good reason for it. But either way: this thread is not the correct context for that discussion.
We are talking about something that has been dug out of the Lucee core code. This is not something that has been publicised in anyway. Lets agree not to “deprecate” nor to “document” things which are unknown, and unwanted.
There’s little point spending our precious time documenting the unknown to let people know that which they didn’t know is now not to be known
Nah, fair cop. I didn’t look too closely at the aliases Dom plucked out of the source code, and they all look a bit pointless to me: allowing for spelling variations (some of which are spelling mistakes, as Igal points out) and the like. They probably should never have been in there in the first place.
That said: in the time we’ve spent discussing it, any one of us could have edited the relevant docs page, listed the aliases, and said “don’t use these: they’re there for internal reasons and not intended for public consumption”. That’s about the level of documentation I was talking about.
I didn’t want to do this myself as I didn’t want to make the decision as to the future of these things. If we’re agreed though, I’m happy to make that update, then we can move on and disagree about something else instead.
i personally use structNew(“soft”|“weak”) a lot inside cfml and java, because it is a very simple way to cache stuff and also a different way to the cache functions.
this way to “cache” is memory sensitive and not time sensitive like the cache functions are.
the garbage collector clean u.
In my opion this is a very strong feature in Lucee that needs more public awarness and should not be deprecated.
But is that what I want? Surely when created a weak reference, it should only apply to the very reference I… um… refer to. It should not second-guess what kind of references to make to other objects it internally references, should it?
If I want those other references to be weak, then I’d make them weak.
Also I wonder what the gain is in making the internal references weak? I’ve only done superficial reading - and have never used these things - but from my “understanding” as soon as the outer one is GCed, then the others would be as well anyhow, as they would have no further references to them anyhow. So it seems like work for the sake of it?
Memory management in Java is done for you automatically behind the scenes, courtesy of the Garbage Collector (GC). The GC reclaims previously used memory by removing “dead” objects.
Objects are considered “dead” if there are no references to them from the root of the JVM. The problem arises when you cache objects, so let’s say you create a cache with the results of a long process so that you don’t need to run the lengthy process each time:
var cachedObject = runLongProcess(key);
Application.data.cache[key] = value;
Now as long the Application.data.cache object is “alive”, the value stays in memory and will never be reclaimed, which is fine if you know for a fact that the cache store will never get crazy-large.
But if you keep adding objects to the cache store without any limitation – it is only a matter of time before you hit an OutOfMemoryException – because even objects that have been dead for days or weeks will still have a reference to them from the cache store.
Setting the reference type to “weak” or “soft” simply tells the GC to not consider that reference when determining whether an object is “alive” or not, so if there are other references to the object, it will stay in memory, but if all other references are long gone and the only reference is from the Hashtable (Struct) then it will be considered “dead” and safe to remove.
thread safe, in Lucee al struct and scopes are thread safe by default (changed in Railo 4.2), so this type is obsolete and only exists for backward compatibility