It's funny how the little, basic things that you re-examine when you are trying to teach someone else a programming language can surprise you. I thought I knew how these different languages handled this topic but I was wrong. Here we go:
I want to show you some differences between Perl, Python and Ruby (the three of which I consider to be the main "scripting" languages at the moment) with respect to their handling of booleans and boolean expressions. I was taken by surprise with some of this behaviour, as I tend to mainly use booleans as the results of conditional expressions - and fairly explicitly when I do.
No boolean type.
$ perl -e 'if (100 > 1) { print "true\n" } else { print "false\n" }'
true
$ perl -e 'if (100) { print "true\n" } else { print "false\n" }'
true
$ perl -e 'if (1) { print "true\n" } else { print "false\n" }'
true
$ perl -e 'if (0) { print "true\n" } else { print "false\n" }'
false
$ perl -e 'if (-1) { print "true\n" } else { print "false\n" }'
true
$ perl -e 'if ("") { print "true\n" } else { print "false\n" }'
false
$ perl -e 'if ("hello") { print "true\n" } else { print "false\n" }'
true
Has a specific boolean type.
>>> x = False
$ python -c 'print ("true" if 100 > 1 else "false")'
true
$ python -c 'print ("true" if 100 else "false")'
true
$ python -c 'print ("true" if 1 else "false")'
true
$ python -c 'print ("true" if 0 else "false")'
false
$ python -c 'print ("true" if -1 else "false")'
true
$ python -c 'print ("true" if "" else "false")'
false
$ python -c 'print ("true" if "hello" else "false")'
true
... ok so it's the same as Perl at this point, but note these following boolean comparisons and compare to the upcoming Ruby code:
>>> 0 == False
True
>>> 1 == True
True
>>> 100 == True
False
>>> -1 == True
False
$ ruby -e 'if (100 > 1) then puts "true"; else puts "false"; end'
true
$ ruby -e 'if (100) then puts "true"; else puts "false"; end'
true
$ ruby -e 'if (1) then puts "true"; else puts "false"; end'
true
$ ruby -e 'if (0) then puts "true"; else puts "false"; end'
true
$ ruby -e 'if (-1) then puts "true"; else puts "false"; end'
true
$ ruby -e 'a = ""; if (a) then puts "true"; else puts "false"; end'
true
$ ruby -e 'a = "hello"; if (a) then puts "true"; else puts "false"; end'
true
... ok ... that's fairly different. That's because Ruby only counts something as false if it is specifically equal to 'false' or 'nil'. Interesting. What about boolean comparisons that aren't wrapped in conditional expressions?
(Python uses 'True' and 'False', Ruby uses 'true' and 'false')
irb(main):001:0> 0 == false
=> false
irb(main):002:0> 1 == true
=> false
irb(main):003:0> 100 == true
=> false
irb(main):004:0> -1 == true
=> false
That is considerably different to Python, right?
What do we know?
OK so this post wasn't exactly straightforward, but it shows how major languages can treat something as simple as booleans so differently.
It's nice to be able to type:
$ python
Python 2.5.2 (r252:60911, Mar 1 2008, 13:52:45)
[GCC 4.2.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 3 + 9
12
>>>
But what about Perl?
$ perl -de 0
Loading DB routines from perl5db.pl version 1.28
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(-e:1): 0
DB<1> print 6 + 18
24
DB<2>
This opens the debugger for the expression '0' and then lets you evaluate perl expressions line-by-line like the interactive python (or ruby (irb)) sessions. It works OK. Unfortunately for multi-liners you need to put a backslash at the end of each line, like so:
DB<4> if (1) {\
cont: print "OK\n";\
cont: }
OK
An alternative is to use this gentleman's psh script: http://uazu.net/freeware/psh/
The current Python (I do not know about Py3000) has some annoying features (annoying for me, not for you - you love them.)
How's this for counter-intuitive:
>>> a = ['f', 'a', 'i', 'l']
>>> a.join("")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'join'
>>> "".join(a)
'fail'
... the join method, to me, seems like it's in the wrong area. If I have an array (list), I want to join it together with a string. I don't want to get a string, then join it to an array.
More counter-intuitiveness:
>>> import re
>>> pat = re.compile('^\w\d+$')
>>> s = 'b45343'
>>> s.match(pat)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'match'
>>> pat.match(s)
<_sre.SRE_Match object at 0xb7c6e598>
... when programming and I have a string, I want to see if the string matches a pattern. I don't want to get a pattern and see if a string matches it. My suggestion could involve regex stuff being built into the string library - or not, depending on implementation. Either way is fine.
How about pypi, the place where Python packages live. Say I want a lib to do SSH, and don't know what the package is called. I ask pypi and I get a list including:
Contrast this to searching CPAN which is the place where Perl's libraries live. I get this:
CPAN is clearer.
Here's another thing: you can't do assignments in conditional tests. Observe:
>>> if (a = (1 + 1)): print "yay"
File "<stdin>", line 1
if (a = (1 + 1)): print "yay"
^
SyntaxError: invalid syntax
... compare to Perl:
$ perl -e 'if ($a = (1 + 1)) { print "yay\n" }'
yay
Django Python 960.gs Git Vim NetBSD Nginx
This is the blog of Brad Willis, a software engineer living in Brisbane.
Help
Latest entries
*BSD Agile Apache Apple apt Athletics Best-Practice Censorship Chrome Comedy Cool Crosswords Deployment Django English Exim Firefox FTP Git Hardcore Health irssi Javascript Jira Languages Linux Makefile Mathematics Mobile Broadband Mutt MySQL NetBSD nginx Nokia OpenVZ OSX Perl Postfix PostGreSQL Privacy Python Rant Requirements rsync Ruby Shell Slackware SQL SQLite SSH Standards Subversion Television Testing ThisBlog Vim VMWare (Fusion) VPN X zsh
PostGreSQL setup cheatsheet
Python property decorators
FTP
gvim - Always open new files as new tabs
crontab - escape % (percentage)
OSX Google Chrome - start in incognito mode
SQLite date arithmetic
Postfix - delete message in mailq
Checking for exceptions in doctests
Homer's Curling Speech
retry in Python
Vim Makefile tabs
Centos (or RH) IPTables
Converting ssh2 public keys to openssh
Vim comment hints
Context managers in Perl
Dish rotation
Git - fixing commit user
apt stuff
Using shell variables in AWK
Linux - Too many open files
Tell gvim to save and quit... remotely
Vim - automatically remove whitespace at EOL
Python - relative paths from within modules
TV Aspect Ratios
Git - Which commits are in your branch only?
Subversion setup cheat sheet
Force detach a screen session
Modify sudo's use of environment variables
Install all Perl modules
Mutt - delete old messages
OpenVZ VPS and swap space
fail2ban on NetBSD for ssh
NetBSD - Using sup
Python - testing for a sys.exit
Python Best Practice Link Dump
Python script names
Perl - Using an expensive module
Speed of git clone
Perl Modules with Custom Prefix