What's with |notes|()?

Some object has an instance method named “notes”.
So I invoke the method, using my chosen notation for now, by spelling it “|notes|()”.
Other method names I spell the same way, the compiler leaves 'em alone.
But this one, I hit Command-S, and the compiler changes it to “notes()”. (No pipes.)
It works, but why?

–Gil

Are you talking about methods, not properties? Why do you want to put pipes around notes? When I try it, any method name I put in pipes that isn’t an applescript word has the pipes removed when I type command s.

Ric

Ah! You got it!

I got properties and methods mixed up.

The CalEvent Class Reference in XCode → Help → Developer Documentation lists a bunch of properties, but not “notes”. It also has no method called “notes”. However, “notes” works*, so I assumed it was a property inherited from some superclass. Apparently it’s a method inherited from some superclass, and all the other cases I was looking at were indeed properties.

I know classes can inherit methods. Can’t classes inherit properties, too?

I think I need to read a chapter on “properties”.

  • – “notes” (even without pipes nor parentheses) seems to be the only way to get at the description field of an iCal event.

Well, I had heard that pipes didn’t hurt anything. So, in a rather naive effort to avoid complexity while I’m learning this stuff, I decided to put pipes on every Cocoa thing that I thought even might be an AppleScript reserved word. I guess the compiler is trying to tell me when they are not needed.

Thanks, Ric.

–Gil

Actually, “notes” is a property of CalEvent’s superclass, CalCalendarItem. Subclasses have access to their superclass’s properties through getter and setter methods – the getter method, which you are using, has the same name as the property, but in ASOC you need to use the parentheses after the name to distinguish the property from the getter method. You should get an error if you try to use notes instead of notes(). So, by using notes(), you are actually using a getter method that accesses the superclass property.

Ric

Thanks for explaining that, Ric.

I tried dropping the parenthses after notes, and you were right! “The variable notes is not defined.”

So then I tried dropping the parentheses after startDate, and gpt the same error: “The variable |startDate| is not defined.”

But startDate is a property of the CalEvent class, not its superclass. Evidently, I need the parentheses to invoke the getter method for any property, superclass or not. Does that seem right?

If so, then all one-token (i.e., parameterless) invocations, whether to property or method, need the parentheses. Can this be so?

So, what’s the point of listing properties separate from methods in the documentation? We invoke them the same way, don’t we?

I’m not sure how your program is set up. It works in mine to use |title| or startDate without the parentheses. This is the code I have to load a table with all the events from this years calendar:

on applicationWillFinishLaunching_(aNotification)
		set theData to current application's NSMutableArray's alloc()'s init()
		set cal to CalCalendarStore's defaultCalendarStore()
		set homeCal to cal's calendars()
		set thisYear to NSCalendarDate's |date|()'s yearOfCommonEra()
		set theStart to NSCalendarDate's dateWithYear_month_day_hour_minute_second_timeZone_(thisYear, 1, 1, 0, 0, 0, missing value)
		set theEnd to NSCalendarDate's dateWithYear_month_day_hour_minute_second_timeZone_(thisYear, 12, 31, 23, 59, 59, missing value)
		set eventPredicate to CalCalendarStore's eventPredicateWithStartDate_endDate_calendars_(theStart, theEnd, homeCal)
		set theEvents to cal's eventsWithPredicate_(eventPredicate)
		repeat with anEvent in theEvents
			set dict to {eventTitle:anEvent's |title|, theStart:anEvent's startDate}
			theData's addObject_(dict)
		end repeat
		setTheData_(theData)
	end applicationWillFinishLaunching_

Ric

Ric, although Apple uses NSCalenderDate in its own code samples, the class is deprecated.
You can compose the dates the same way with NSDateComponents, this is the ObjC version


	NSCalendar *calendar = [NSCalendar currentCalendar]; // assuming the current calendar is gregorian
	NSDateComponents *offsetComponents = [calendar components:NSYearCalendarUnit fromDate:[NSDate date]];
	NSDate *firstSecondThisYear = [calendar dateFromComponents:offsetComponents];
	[offsetComponents setYear:[offsetComponents year] + 1];
	NSDate *lastSecondThisYear = [[calendar dateFromComponents:offsetComponents] dateByAddingTimeInterval:-1.0];

Thanks for your observation, Stefan. Actually, I am using NSDate in my working application. Seems to produce the same thing.

However, to focus our discussion, I can replicate Ric’s code to illustrate my question.

Well, mostly. Ric, you must have some property statements up above that simplify your code. I added some tell statements so that it would compile and I could follow what’s happening:


	on applicationWillFinishLaunching_(aNotification)
		set theData to current application's NSMutableArray's alloc()'s init()
		--set cal to CalCalendarStore's defaultCalendarStore()
		tell current application to ¬
			set cal to class "CalCalendarStore"'s defaultCalendarStore()
		set homeCal to cal's calendars()
		--		set thisYear to NSCalendarDate's |date|()'s yearOfCommonEra()
		--		set theStart to NSCalendarDate's dateWithYear_month_day_hour_minute_second_timeZone_(thisYear, 1, 1, 0, 0, 0, missing value)
		--		set theEnd to NSCalendarDate's dateWithYear_month_day_hour_minute_second_timeZone_(thisYear, 12, 31, 23, 59, 59, missing value)
		tell current application
			tell class "NSCalendarDate"
				set thisYear to |date|()'s yearOfCommonEra()
				set theStart to dateWithYear_month_day_hour_minute_second_timeZone_(thisYear, 1, 1, 0, 0, 0, missing value)
				set theEnd to dateWithYear_month_day_hour_minute_second_timeZone_(thisYear, 12, 31, 23, 59, 59, missing value)
			end tell
			--		set eventPredicate to CalCalendarStore's eventPredicateWithStartDate_endDate_calendars_(theStart, theEnd, homeCal)
			tell class "CalCalendarStore" to ¬
				set eventPredicate to eventPredicateWithStartDate_endDate_calendars_(theStart, theEnd, homeCal)
		end tell
		set theEvents to cal's eventsWithPredicate_(eventPredicate)
		repeat with anEvent in theEvents
			set dict to {eventTitle:anEvent's |title|, theStart:anEvent's startDate}
			theData's addObject_(dict)
		end repeat
		--?		setTheData_(theData)
		
		--Here are my observations:
		
		set anEvent to item 1 of theEvents --just to pick one
		tell anEvent
			log "class of anEvent=" & ¬
				|description|() of (|class|() of anEvent)
			-->class of anEvent=CalEvent
			
			--startDate and endDate are properties of CalEvent:
			log "start date=" & |description|() of |startDate|() & "<"
			log "end date =" & |description|() of |endDate|() & "<"
			
			--while notes and title are properties of 
			--CalEvent's superclass, CalCalendarItem
			log "notes=" & notes() & "<"
			log "title=" & |title|() & "<"
			
			--when I typed it, the notes line looked like this:
			--log "notes=" & |notes|() & "<"
			--but the compiler removed the pipes
			--I guess because notes isn't a reserved word?
			
			--These worked:
			log "start date=" & |description|() of startDate() & "<"
			log "start date=" & description of startDate() & "<"
			--"description" is pink in the second line
			
			--These did not:
			--log "start date=" & |description|() of startDate & "<"
			-->The variable startDate is not defined.
			
			--log "title=" & title & "<"
			--The variable title is not defined.
			
			--For the following two, the strangest thing happened.
			--the compiler did not change the text color, 
			--which usually indicates a compiliation error,
			--but "Build and Run" succeeded, and 
			--both log statements did work! 
			--(Notice that the text is still offset.)
			log "Two that did not compile:"
				log "start date=" & description() of startDate() & "<"
				log "title=" & title() & "<"
		end tell
	end applicationWillFinishLaunching_

Here’s the log from the code above:

I’m going to have to think about this for a while. Perhaps there are rules to cover these situations, but I don’t see them yet. Do you?

–Gil

FWIW, instead of saying something like:

       tell current application
           tell class "NSCalendarDate"

You can simply say:

       tell current application's NSCalendarDate

The class names are automatically properties of the current application.

I suspect you’re getting confused because Ric is defining the properties himself. This means he can leave out the "current application’s ", but it doesn’t copy and paste well.