Why doesn't this code work? (to change a record)

I’m having trouble understanding how to change values, particularly the values of records. All of my reading has come up with tons of examples on how to set variables and access them, but I can’t seem to find something to tell me about changing their values.

My main problem right now has to do with records (properties of objects).

why doesn’t this work?

set myProperties to {text:"19 - 25", class:text, color:{0, 0, 0}}
set text of myProperties to "blah"

I can’t seem to get around this problem. I tried an alternative solution which “seemed” to work but didn’t accomplish what I wanted it to. This seemed like it should work but didn’t actually change the text property of the object in my app.

set myProperties to properties of myObject -- which are: {class:text, text:"19 - 25", color:{0, 0, 0}} (for example)
set myProperties to {text:"blah"} & myProperties 
set oi to {myProperties, properties of myObject}
get oi
-- result = {{text:"blah", class:text, color:{0, 0, 0},{class:text, text:"19 - 25", color:{0, 0, 0} }

So, I thought, I should just set the value of the properties of object. But I can’t:

set properties of myObject to myProperties --nope. not gona work

Obviously I just don’t understand something properly, a leg up here would be really handy! Thanks!

That returns this error message:

AppleScript is interpreting “text” as a keyword instead of a record label. The “class” label in your record can also cause trouble (see Nigel’s thead: ‘Class of record’ catch).

I think the easiest way to avoid this is to change your labels.

set myProperties to {theText:"19 - 25"}
set theText of myProperties to "blah"
return myProperties

.or escape your record labels.

set myProperties to {|text|:"19 - 25"}
set |text| of myProperties to "blah"
return myProperties

Hi Chris.

You can concatenate two records to produce a record that begins with the properties of the record to the left of the operator, followed by the properties of the record to the right of the operator. If both records contain properties with the same name, the value of the property from the record to the left of the operator appears in the result. For example:

set myProperties to {text:"19 - 25", class:text, color:{0, 0, 0}}

set myProperties to {text:"blah"} & myProperties

--> {text:"blah", class:text, color:{0, 0, 0}}

(I also posted a suggestion to your concurrent thread here.)

Actually, it’s perfectly legal for property names to be keywords, as long as they’re the right sort of keywords. The problem here is that AS is interpreting ‘text’ as an element name, not a property name, and since AS records don’t have elements the reference fails.

The ‘text’ keyword can be particularly problematic as it’s heavily overloaded: sometimes it’s a property name, sometimes it’s an element name, sometimes it’s a semi-synonym for the ‘string’ keyword. Synonyms and homonyms can be a real menace in AS: this sort of ambiguity requires AS to guess which meaning is actually meant, and - as the OP’s discovered - it’s not an especially good guesser.

As you suggest, it’s generally sensible practice to use AS identifiers rather than keywords for property names in records that are defined and consumed by AS only, as those can’t be confused for anything else.

Thanks Bruce and kai!

In response to Bruce:
That looks like it answers my question “why doesn’t this code work”. In the script I’m working with though, I don’t have the choice to change the record label, since it comes from the class provided by the application I’m working with. (OmniGraffle) That helps me better understand the problem of course so thanks for the insights!

In response to kai:
I actually tried to concatenate, but it didn’t work the way I was expecting either. (see my original post above) Basically I tried this:

set myProperties to {text:"blah"} & the properties of myObject's text
set the properties of myObject's text to myProperties

Maybe this better explains the problem I’m trying to grapple with. I’m must not be understanding something about how to use the set command. I feel like I should just be able to do something like “myObject.text.properties := {text:“blah”}&myObject.text.properties” (of course that is so non-AppleScript).

In my particular case I am working with this:
The object I’m working with is a Solid which has a property text which in turn has its own properties (including of course, text. Essentially I just want to modify text of text of Solid to “my text”.

If I do this:

get properties of mySolid's text

I end up with

{size:24.0, underlined:false, font:"Copperplate", baseline offset:missing value, superscript:missing value, alignment:left, text:"19 - 25", class:text, color:{0, 0, 0}}

(I feel like I’m || this close to accomplishing what I want at this point…)

The item with the label “text:” of properties of mySolid’s text is what I want to change, but I can’t manage to do it! (not without wiping out the rest of the properties by just doing something like:

 set text of mySolid to "blah"

I know it’s legal, but I couldn’t describe the rest properly. :confused: Thanks for clearing it up.

I knew that was coming. :rolleyes:

If I can find my old copy of OmniGraffle, I’ll try it out.

Did you try:

 set text of text of mySolid to "blah"

Affirmative.

tell application "OmniGraffle"
	set myPage to page 1 of document "myDocument.graffle" of application "OmniGraffle"
	set myObject to solid id 164 of myPage
	set text of text of myObject to "blah"

yields:

That’s not quite what I suggested in your other thread, Chris. You really need a record that looks more like {text:{text:“blah”…, rather than just {text:“blah”….

For example, I tried this in TextEdit:

tell application "TextEdit"

    set myProperties to {text:{text:"blah"} & properties of document 1}

end tell

--> {text:{text:"blah", modified:true, path:missing value, class:document, name:missing value}}

(Not that I can do much with that - but it looks more like what you’re after.) :wink:

So rather than:

set myProperties to {text:"blah"} & the properties of myObject's text

…you might want to try something more like:

set myProperties to  {text:{text:"blah"} & properties of myObject}

I’m not saying that’ll work any better - but it should be closer to what’s needed…

Unfortunately, that doesn’t work (tried it). Ultimately, I’m concerned about the properties of text within myObject rather than the properties of myObject.
I actually don’t have a problem getting the variable myProperties to be what I want. The problem is getting the values into the object I’m concerned about.

Of course since reading your post I found a “solution” to my problem: just do it manually
.
Basically what I was working on was one-week calendar layout that I did in OmniGraffle. With that explanation, it might be easier to understand the resulting script.

tell application "OmniGraffle"
    activate
    set myDay to ¬
        text returned of (display dialog "Enter start day" default answer "1") as integer
    set myPage to page 1 of document "Planner.graffle" of application "OmniGraffle"
    set properties of solid id 164 of myPage to {text:{text:(myDay as text) & " - " & myDay + 6, alignment:left, font:"Copperplate", size:24}}
    set myX to 0
    repeat with i from 171 to 177
        if (myDay + myX) > 31 then -- of course this doesn't deal with varying month lengths
            set myDay to 1
            set myX to 0
        end if
        set properties of solid id i of myPage to {text:{text:((myDay + myX) as text), alignment:right, font:"Copperplate", size:24}}
        set myX to myX + 1
    end repeat
end tell

What you’ll notice though is that I still wasn’t able to change only the text property. I just set the ones that I cared about manually. I still would like a way of doing it so that I could do the layout and font work in OmniGraffle and then replace the text without needing to know set the properties manually. It’s not an urgent need though. I just want to learn. :slight_smile:

Works here (OG 2.0.8), but may be different in other versions. Make sure it’s not a problem in some other part of your code, of course - that error message doesn’t tell you which part of the reference it failed on. If your version of OG is broken, you should file a bug report on it.