The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

350596 (3) [Avatar] Offline
#1
If you run code Listing 8.14 (page 225) in groovyconsole, it works on the first run but fails if you run it again:

Assertion failed: 

assert "IBM".encode() == "HAL"
             |        |
             PIT      false


	at ConsoleScript6.run(ConsoleScript6:13)


Apparently (1) ibm.shift = 7 changes the shift value for all strings, not just the string in the variable ibm, and (2) rerunning the code does not reset shift to -1.

Q. Where is
shift
stored?

Q. Is

String.metaClass {
    shift = -1
    encode  {-> move delegate, shift  }
    decode  {-> move delegate, -shift }
    getCode {-> encode() }
    getOrig {-> decode() }
}

equivalent to
String.metaClass.shift = -1
String.metaClass.encode = {-> move delegate, shift  }
String.metaClass.decode = {-> move delegate, -shift }
String.metaClass.getCode = {-> encode() }
String.metaClass.getOrig = {-> decode() }

via some additional expando magic? The text doesn't explain.
Mittie (397) [Avatar] Offline
#2
Hi,

at the end of the first run, we set the shift value for the "IBM" String to 7.
That shift value has become part of the String and therefore remains in the second run of the script.
Technically, the storage place is the MetaClass of "IBM" (and for that string alone).
You can experiment with this by e.g. adding
println "ibm".encode()
println "IBM".encode()

before line 13 and you will see hal and PIT on the second run.

Thanks for posting
Dierk
350596 (3) [Avatar] Offline
#3
I see.

It took one more discovery to understand this: Re-running the script reads the string literal "IBM" into the existing string instance -- the one with shift set. Apparently the Groovy console+compiler interns all string literals (like Java does).

And on the question about
String.metaClass { ... }
indeed the ExpandoMetaClass doc says "ExpandoMetaClass also supports a DSL/builder like notation to combine multiple definitions together" (This may be worth mentioning.) But ExpandoMetaClass doesn't have a call(Closure c) method, so I'm puzzled how it does this.

Thanks, Dierk!