Re: can I do this better?
Re: can I do this better?
- Subject: Re: can I do this better?
- From: has <email@hidden>
- Date: Thu, 13 Jun 2002 16:24:59 +0100
Ric Phillips wrote:
>
Well, a great deal depends on what you consider to be 'better'. For some
>
that is purely a matter of speed, for others readability of the source - and
>
then there is memory usage, and / or just plain elegance!
Absolutely. Program design is just one big balancing act - a series of
tradeoffs according to your particular priorities.
>
Below is my (humble) offering. As to why.....
>
>
It's vanilla apple script (though you could do this a lot faster with
>
regular expressions, as a shell script in OS X, or with regex OSAX in pre OS
>
X)
e.g. Using the Satimage osax:
======================================================================
on trimBoth(theString)
change "(^[[:space:]]*|[[:space:]]*$)" into "" in theString
[NO-BREAK]regexpflag {"extended"} with regexp
end trimBothRE
======================================================================
"Faster" is relative, mind you. A vanilla routine will give you O(n)
behaviour [where n is number of characters to remove]. The above regex will
seem almost O(1) in comparison; however there is a penalty to be paid in
the time it takes for the shell/osax call to be made (much slower than a
local handler call), and an additional dent due by the time taken to
compile the expression. If your strings generally don't have large amounts
of white space to trim, you'll get better performance from the vanilla
routines.
--
>
if ({space, return, tab, ""} does not contain item i of (every
>
character of s)) then
>
set s to (characters i thru l of s) as string
These constructs should be avoided:
(every character of s)
(characters i thru l of s) as string
The first unnecessarily coerces a string into a list of characters - this
is inefficient. Use "character i of s" instead.
The second does much the same, coercing the string to a list and back to
string - inefficient *and* a source of errors if TIDs are set to something
other than "". Use "text i thru l of s" instead.
--
Anyway, here's mine:
The original poster's code might be a bit 'over-engineered', trying to do
too many things in the one place. Thus, another suggested approach: start
by using Occam's razor to split the two tasks [trim from start, trim from
end] into separate handlers.
======================================================================
script trimModule
property _whiteSpace : (ASCII character 9) & (ASCII character 10)
[NO-BREAK]& (ASCII character 11) & (ASCII character 12) & (ASCII
[NO-BREAK]character 13) & (ASCII character 32) & (ASCII character 202)
on trimStart(theString)
if theString's class is not string then error "Not a string."
try
repeat while {theString's first character} is in _whiteSpace
set theString to theString's text 2 thru -1
end repeat
return theString
on error number -1728
return ""
end try
end trimStart
on trimEnd(theString)
if theString's class is not string then error "Not a string."
try
repeat while {theString's last character} is in _whiteSpace
set theString to theString's text 1 thru -2
end repeat
return theString
on error number -1728
return ""
end try
end trimEnd
on trimBoth(theString)
trimStart(trimEnd(theString))
end trimBoth
end script
======================================================================
It's clean, with simple functions doing one task apiece (no single "kitchen
sink" function trying to do everything). Plus it's more
flexible/general-purpose, giving you get three functions for the price of
one.
I've also bundled these functions as a nice, neat module [reusable code is
a Good Thing].
These function should be pretty robust: the error trap catches only the
error it's supposed to [run out of string], and not unrelated errors such
as user cancels [-128]. There's also a check to make sure the value given
is the correct class, always a good precaution to take. Easy to overlook
these sorts of issues, but doing the right thing with invalid data is just
as important as doing the right thing with valid data.
--
Finally, if raw speed is really much more important than clean,
well-organised code - and with basic functions like this it may be - you
can squeeze a few percent better performance from:
======================================================================
on trimBoth(theString)
if theString's class is not string then error "Not a string."
try
repeat while {theString's first character} is in _whiteSpace
set theString to theString's text 2 thru -1
end repeat
repeat while {theString's last character} is in _whiteSpace
set theString to theString's text 1 thru -2
end repeat
return theString
on error number -1728
return ""
end try
end trimBoth
======================================================================
This is really just the same code as before, but inlined and with
duplication removed. Again, a tradeoff: fractionally better speed, but a
bit more duplicated code.
HTH
has
--
http://www.barple.connectfree.co.uk/ -- The Little Page of Beta AppleScripts
_______________________________________________
applescript-users mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/applescript-users
Do not post admin requests to the list. They will be ignored.