Hey developers! We’re excited to announce that we’re live with the first episode of our new podcast series, “BoxLang Town Meetings.” Now, dive deep into BoxLang, CFML, and Java development!
Link to Live: https://www.youtube.com/live/GhPgsjE4IR0?si=jB98LNBxi8aqIXmp
Take advantage of this chance to engage with the community, ask questions, and gain valuable insights. Click the link above to join us live. See you there!
BoxLang #Podcast #LiveEvent #WebDevelopment #CFML #Java #Programming #TechTalks #Coldfusion
Informative, thanks for doing that.
I’ve been reviewing the CFML BIF Google sheet that Brad linked in the chat and noticed that the only function I used that is not planned to be supported is objectEquals
.
I’m curious if there’s another supported way in CFML itself to compare two value objects w/o looping over metadata?
2 Likes
We can do this in the compat module. I think one of the biggest reasons we marked it “won’t do” was because we’ve never used it and I’m not even sure what it does!
At first, I thought it would be the equiv of the equals()
method on java.lang.Object
but the cfdocs description is
Identifies any conflict between CFC instances on the client and the server.
which doesn’t make a great deal of sense. It appears to be a comparison check, yet it’s listed on “conflict management” and the docs keep mentioning “client” and “server” which makes no sense.
The docs also make it clear it’s only for CFCs, yet passing simple values in doesn’t error! Glancing at Lucee’s source code, there’s a whole bunch of checks that differ based on whether the inputs are
- component
- collection
- UDF
- simple value
that falls back to obj.equals( obj2 )
. I have no idea if ACF does all this as well or not.
Can you share how you’re using it?
1 Like
Thanks Brad. The code I had in front of me when checking this was a cart cfc
with composed address
value objects (e.g. “Bill To”, “Ship To”, etc.)
The Coldbox preHandler would do a populate( model="address" )
from a checkout form and then do something like this:
if( ! objectEquals( shipAddress, cart.getDefaultShip() ) ){
// do some stuff...
}
The way Lucee handled ===
made objectEquals
the only quick/simple way for me to do this. Otherwise, I’m doing stuff with getMetaData( shipAddress ).properties
which isn’t as nice.
Right, that makes sense. I can’t believe I’ve never used this BIF, lol. I think we can do this for sure-- it’s just a matter of whether it belongs in compat or is useful enough for core. We haven’t overriden the equals() method on CFC instances, but it wouldn’t hurt. Of course, accessing underlying Java methods isn’t possible on CFC instances.
shipAddress.equals( cart.getDefaultShip() )
expects there to be an actual CF UDF named “equals”, which is where the BIF comes in handy. We’d have to do a recursive check on all properties-- or perhaps the entire variables scope? What about the this scope? Hard to say. We’d also need to prevent the endless recursion bugs that happen easily with this sort of thing causing stack overflows. I saw Lucee has code to handle that.
@lmajano Thoughts on re-considering this.
1 Like
This is also new to me, but coincicendatally I was writing docs about it and checked and we do not have it. So here are my thoughts.
- Equals() on the IClassRunnable
This should be done for sure. In order to do equality I think we need to evaluate the this
and `variables1st scope. We should do this via hashcodes for each scope. This way, it makes it easy on us to not check every single property or variable. I do this with ColdBox a bit to compare collections. I thought we did scope equality at one point, can’t remember.
Rules for equality
-
Not null
-
Same Class Instance Type
-
Compare class hashcodes (see point 3)
-
I think the BIF has merit to be core, however, I would love a member method as well for it. Now you can attach member methods to classes @bdw429s . I added that last week. If the user creates it’s own equals
then it should use that, if not the member method can kick in.
-
Since we will do equals
I say we do also hashcode()
for the class, which should calculate it via the hashcodes of the variables and this scope.
1 Like
@lmajano How do you feel about only calculating declared properties of a class? I realize not everyone uses properties, but if a user class has a firstname
, lastname
, and age
, I could see a case for just comparing variables.firstName
, variables.lastName
, and variables.age
. A caveat to exclude properties used for injection like
property name="wirebox" inject;
could be nice too.