Coercion to a class stored in a variable?

Is there any way in AppleScript to store a class in a variable, and then use that variable to perform a coercion? Instead of

set x to "1234"
set z to x as integer

something like

set x to "1234"
set y to integer
set z to x as y

This doesn't work, but I think you can see what I want to do. Actually, what I really want to do is perform a coercion within a subroutine, but with the specific coercion passed as a parameter:

on MySub(someValue, someClass)
. . . .
set z to (<...some expression involving someValue...>) as someClass
. . . .
return z
end MySub

Is this possible?

Dual 1.2 GHz, Mac OS X (10.5.6)

Posted on Jan 8, 2009 5:45 PM

Reply
6 replies

Jan 9, 2009 10:52 AM in response to Niel

Niel wrote:
Here:

set x to "1234"
set y to "integer"
set z to (run script (x & " as " & y))


Code generation is almost always the wrong solution to any given problem.

e.g. Unless x is guaranteed always to be a string of digits (in which case, why not just hardcode the coercion?), the above example will almost certainly produce errors or unexpected behaviours, e.g.:


set x to "hello"
set y to "string"
set z to (run script (x & " as " & y))
-- Error: The variable hello is not defined.


It also creates a potential security hole, allowing a maliciously crafted string to be executed as AppleScript code with all sorts of nasty consequences:


set x to "display dialog "I could trash your hard disk if I wanted to!" 1234"


Give the known shortcomings of AppleScript's 'as' operator, the correct solution is as follows:


-- Define objects for coercing a value to different classes
script CoerceToInteger
on coerceValue(val)
return val as integer
end coerceValue
end script
script CoerceToReal
on coerceValue(val)
return val as real
end coerceValue
end script
script CoerceToText
on coerceValue(val)
return val as text
end coerceValue
end script
script CoerceToList
on coerceValue(val)
return val as list
end coerceValue
end script
-- etc.
on doSomething(someValue, coercionObj)
-- do some stuff
set newValue to coercionObj's coerceValue(someValue)
-- do more stuff
end doSomething
-- Example usage:
doSomething("1234", CoerceToReal)
--> 1234.0
doSomething("1234", CoerceToList)
--> {"1234"}


HTH

Jan 9, 2009 1:06 PM in response to Jeff Johnson 1

Hello

Niel's solution using 'run script' may be refined as CODE1 below although I agree with hhas about dynamic code generation be mostly not good idea.

--CODE1
set x to 123
return asGivenClass(x, real)
--set x to "hello"
--return asGivenClass(x, string)

on asGivenClass(x, c)
(*
anything x : source value
class c : class to be coerced to
*)
run script "
script
on a(x)
return x as " & c & "
end a
end script"
tell result to return a(x)
end asGivenClass
--END OF CODE1

This way, the said potential security hole is blocked and "hello as string" problem won't arise.

---
Without using 'run script', you'd employ a simple handler as in CODE2 in addition to hhas' approach. In either way, though, you'd have to predefine the numerous coercion statements in advance. It's quite tedious and will raise a question: why not simply use 'x as integer' in lieu of 'asGivenClass(x, integer)' or the like?...
After all, it would depend upon how frequently you need to use this sort of dynamic coercions. I myself would go for simpler way. 😉

--CODE2
set x to 123
return asGivenClass(x, real)

on asGivenClass(x, c)
(*
anything x : source value
class c : class to be coerced to
*)
-- numbers
if c is integer then return x as integer
if c is real then return x as real
if c is number then return x as number
-- text
if c is text then return x as text
if c is string then return x as string
if c is Unicode text then return x as Unicode text
-- list
if c is list then return x as list
-- others
error "Unregistered class is given: " & c number 9000
end asGivenClass
--END OF CODE2

Good luck,
H

Message was edited by: Hiroto (fixed typo)

Jan 9, 2009 6:53 PM in response to Hiroto

Ahh. There remains serious security hole in my CODE1.

--HOLE
set x to 123
set c to "real & (display dialog \"security hole\")"
return asGivenClass(x, c)
--END OF HOLE

Here's a revised asGivenClass() handler which does check the class of given class.

--CODE1a
set x to 123
return asGivenClass(x, real)
--set x to "hello"
--return asGivenClass(x, string)

on asGivenClass(x, c)
(*
anything x : source value
class c : class to be coerced to
*)
if class of c is not class then error "Invalid class: " & c number 9000
run script "
script
on a(x)
return x as " & c & "
end a
end script"
tell result to return a(x)
end asGivenClass
--END OF CODE1a

All the best,
H

Jan 10, 2009 5:20 PM in response to Hiroto

Wow, leave a thread alone for a couple of days, and look at all the help I get. My thanks to both you and hhas for your suggestions. But on consideration, I think you are probably correct, that the number of situations in which this is a useful strategy is small, and that in most cases there are better, if more mundane, alternatives.

Thanks again to all.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Coercion to a class stored in a variable?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.