Coercions to boolean

I am not sure where to post this, I have very recently discovered that some textual values can be coerced to boolean values. This may come in handy when you are reading defaults and such.

Try this:

set a to "NO" as boolean
log a
set b to "YES" as boolean
log b
set c to "no" as boolean
log c
set d to "yes" as boolean
log d
set e to "true" as boolean
log e
set f to "false" as boolean
log f

Don’t forget:


set g to 0 as boolean
log g
set h to 1 as boolean
log h
set i to no as boolean
log i
set j to yes as boolean
log j
set i to "nooo!!" as boolean
log i

set k to "Oh Yesss!" as expletive
log k

:smiley:

I have actually missed out on the fact that yes and no are boolean constants, thanks adayzdone

Well strictly speaking they’re not, although they can apparently be so coerced. They’re two thirds of the trio ‘yes’/‘no’/‘ask’: possible values for the ‘replacing’ parameter of certain commands.

I seem to recall that in the past, people would occasionally use booleans instead of ‘yes’ and ‘no’ and wonder why their scripts weren’t working. Nowadays, booleans can apparently be used instead of ‘yes’ and ‘no’, but not vice versa.

store script fred in file ((path to desktop as text) & "Fred.scpt") with replacing -- OK instead of 'replacing yes'.

if yes then beep -- Not OK.

Ahh I see, that is were the yes and no is coming from. But yes and no, is also the boolean values for true and false in Objective-C, I thought it was a connection there. Especially since they are uppercase, and the results of the defaults properties are too.

This works outside any dialogs and such, so I guess yes an no, are proper boolean values now.

set success to true
if success = yes then
    log "worked"
end if

A final obseveration, is that “0” is true when dealing with do shell script, that is, a command is exeuting properly, when it returns “0” as result. So one would have to invert the result from from a do shell script if one used a construct like

echo $?

To say how it went, or as a result from one of the test commands.

If this is successfull you would have to coerce it like

set doShellRes to not (theRes as number as boolean)

I also guess it breaks if the error is higher than one, so you would actually have to put it inside a try error block anyway! :slight_smile:

(The idea behind this was to code less, to leverage the automatic coercions, and avoid superfluos code.)

YES and NO are C-chars in Objective-C. yes/no/ask is in AppleScript since Mac OS transferred from Pascal to C.

Not on my machines.

Actually it does not work, because in AppleScript yes is an enumerated constant
which can be coerced to a boolean value

boolean is a special class in AppleScript with two values true and false
unlike in C/Objective-C where yes/true is anything ≠0/null

Hello!

:o

I am awfully sorry about that one! I should have used true in the test and not yes !

While I am at it, I’ll elaborate on the ; echo $? and just state that you can add it on the end of a do shell script command, then you effectively mask a non-zero return value, so there wouldn’t be any need to put the do shell script command within a try block. This obviously only works, when you require no output from the do shell script command.

Also keep in mind that it works for processes that can only return a 0 or an 1, there are many processes who returns other values on error. With the ; echo $? suffix you’re suppressing previous errors from command post the ‘;’. Better is that you’ll use bash expressions instead and echo an integer or boolean strings from bash.

I prefer a suffix like “&& echo true || echo false”. When you don’t redirect the stdout the last line of the output is the boolean value so you can choose this behavior to your likings. When I won’t need the stdout I redirect it to /dev/null

I prefer the same command. && echo true || echo false
construct. Another way to do it, for the sake of not getting any result, would be to put ; exit 0 as the last command.

One thing I am not sure if everybody is aware of, is that you can group commands in a subshell, to collate all its output into one stream, which may be handy when using the do shell script. like this:

set collOutput to  (do shell script "( echo \"Start of output\"; echo \"middle of output\" ; echo \"end of output\")")

(In order to make a one liner, without having to create intermediary files.)

Edit

The last construct isn’t good for collating standard output in a do shell script,not even in the Terminal,(It seems when a pipe is the receiver, but you’ll see the effect if you redirect to a file. Then the subshell constructs sees to that all the output is redirected into that file.

if you try this:

echo "line1" ; echo "line2" ; echo "line 3 " |cat -n

contra this:

(echo "line1" ; echo "line2" ; echo "line 3 " )|cat -n

You’ll see the difference.

This construct is unnecessary in a do shell script, as long as there isn’t any redirection involved, as it seems to keep all the standard output, appending to it as commands are executed.

Keep in mind that you’re also invoking a subshell. That means that variables set in a shell can’t be called by another shell.

do shell script "LANG=nl_NL.utf-8; echo $LANG " -->"nl_NL.utf-8"
do shell script "(LANG=nl_NL.utf-8); echo $LANG " -->""

Hello!

I didn’t think of that, but export would be a quick fix, not spelling this out for you. :slight_smile:

export LC_all=nl_NL.UTF-8 ; ( subshell commands.)

would make those variables visible within the subshell.

I still prefer to use the Environment.plist residing in the ~/.MacOsX folder. Knowing they are set differently in at least ML, if not Lion.

Have a nice evening, I better get back to learning Obj-C. Now, that is a learning curve! I have learned enough, to know that I am going to love it! :smiley:

Export doesn’t fix it, it behaves the same.

do shell script "(export LANG=nl_NL.UTF-8); echo $LANG" -->""

It can’t be working like that because a subshell forks a new instance of bash into a new child process. When using process forking (instead of threading) you will inherit the same variables and values as the parent process, same way as the Apache web server works. The advantage of this behavior is that it’s much quicker on single processor machines than threading but eats more memory. I think the main reason is, same for server/client models, is that forking is more reliable than threading. So when can it go wrong? Well the subshell inherits all the variables from it’s parent process but not the other way around. Or even when you change the value of a variable in the child process it won’t be changed in the parent and visa versa (like in my example codes).

You’re example works the other way around. The parentheses, are very much used by shell scripters, to define some temporary variables that doesn’t inflict with the main script. For instance while loops are often placed between parentheses.

Another example that shows the limitations of export as well:

do shell script "(export LANG=nl_NL.UTF-8;date);date"

I admit to not having tested all permutations of this, but I must say I find it funny that export doesn’t work for a subshell.

But the fix would then to be to export within the subshell. :wink:

And this is a good reason for having environment variables set from within the Environment.plist file or similar, because variables defined here will be set when you fork a new subshell.

Just for the record, I tested this on my machine:

export LC_all=nl_NL.UTF-8 ; ( subshell commands.)

and it works as it should.

I think it’s very straightforward rather than funny when knowing how process forking works. Even if the variables have the same value (due to forking) they aren’t connected in any way with each other; they are two variables with the same value in different environments and no connection.

There are of course some tactics to copy variables into the subshell as in your code, but changing them still isn’t possible.

I never said I was able to change them, just to export them, making them being read in the subshell.

You know, if the subshell had been exec’d (man bash ” / exec ) then all would have been futile as it would have overwritten the current shell, but the subshell is spawned/forked.

And you can transfer values, though somewhat awkwardly through a named pipe.

To pass values I always use command substitution, much simpler than named pipes.

You don’t need export for that; that was what I meant with the results of forking.

Hello!

That you don’t need to export a variable into the subshell construct, now that is puzzling! I’ll have to revisit the bash manual! :slight_smile: Thanks.

There is equally no problem in using command substiution with a subshell, what I mean is :

myvar=`( comm1 ; comm2 ; comm3 )`

The problem arises when you need more than one value out of the command. Or that you run several shells at once, with processes in the background.

I think the horse is beaten to death for now!

It was interesting :slight_smile: