Emacs Lisp for Perl Programmers

Perl Emacs Lisp
Basic output print STDERR "A message for the user\n";
print STDOUT "Some of the real output\n";
(message "A message for the user")
(insert "Some of the real output")
Formatted strings $output = sprintf("%s occurs %d times", $string, $number); (setq output
(format "%s occurs %d times" string number))

Note: message does an implicit "format":
(message "%s occurs %d times" string number)
Assignment
$variable = "stuff";
(setq variable "stuff")
(set 'variable "stuff")
Assign to a variable indirectly
our $variable = "what";
our $indirect = "variable";
{ no strict "refs";
  ${ $indirect } = "hey";
  print "well, $variable \n";
 }
## prints "well, hey"
(let* (  (variable  "what")
           (indirect  'variable) )  ; Note *single* quote
   (set indirect "hey")
   (message "well, %s" variable))
;; prints "well, hey"

A difference from perl: we can't just use the
variable name quoted as a string, in elisp, indirect
assignment requires a variable's symbol
(hence the use of the single-quote).
Quoting a String
'quotation'
"quotation"
Interpolated quotes
"Eat my $madlibs, okay?"
No real equivalent in elisp (no sigils).
This works for environment variables:
  (setq script-location
     (substitute-in-file-name "$HOME/bin"))
String concatenation $newstring = "Eat my" . $madlibs . ", okay?"; (setq newstring
    (concat "Eat my" madlibs ", okay?"))
Global variables our $global="initial definition"; (defvar global "initial definition"
   "A global variable for doing stuff globally.")

(defcustom user_parameter "default setting"
   "Change this if you disagree with my default, fool")
Dynamic scoping
{local $variable1 = "hey";
  local $variable2 = "ho";
 }
(let ( (variable1 "hey")
        (variable2 "ho")
    ))

Or the less surprising:

(let* (  (variable1 "hey")
          (variable2 "ho")
          (variable3 variable2)
    ))
Lexical scoping
{my $lexical_dis = 1;
  my $lexical_luthor = 2;
  ...
 }
(require 'cl)
(lexical-let ((lexical-dis 1)
                  (lexical-luthor 2))
   ...
)
Error messages Undefined subroutine &main:: ... called

Global symbol " ... " requires explicit package name
Symbol's definition as function is void: ...

Symbol's value as variable is void: ...
Evaluating code stored in a variable:
$code = "somefunc( $blah[2] );"
eval $code;
(setq code '(somefunc (car (cdr blah))))
(eval code)

Note: Single quote delays evaluation.
Closures
A perl closure example None in elisp
repeat/untill
$message = "Please input the name: ";
do {
   ### read in the filename

   $message = "Not valid, try again: ";
   } until (not (-e $name))
  (setq message = "Please input the name: )
  (setq default-location
        (file-name-as-directory default-location))
  (while (progn
           (setq filename
                 (expand-file-name
                  (read-file-name message default-location)))
           (setq message
                 "Not valid, try again: " )
           (file-exists-p filename)))
Conditionals if ( is_first_time ) {
    print STDERR "This is the FIRST time.";
    print "we use this string the FIRST time.";
 } else {
    print STDERR "This is the SECOND time.";
    print "we use this string the SECOND time.";
 }
 (if (first-time-p)
        (progn ;; needed to glue together multi-line then clause
             (message "This is the FIRST time.")
             (insert "we use this string the FIRST time.")
             (insert "\n"))
      ;; the else clause has an "implicit progn"
      (message "This is the SECOND time")
      (insert "we use this string the SECOND time.")
      (insert "\n"))
elsif
No elisp equivalent, but see "cond" below...
case statement
use Switch 'Perl6';
given ($test_this) {
    when /something/
        { print "case 1" }
    when (eq "case two string")
        { print "case 2" }
    else
        { print "default" }
 }
(cond ((string-match "something" test_this)
       (message "case 1"))
      ((eq test_this "case two string")
       (message "case 2"))
      (t
       (message "default")))
logical operators for short-circuit/ lazy evaluation
(DEBUG) and print STDERR "Problem!\n";

close IT or die;
(and debug_flag (message "Problem!")

(or (...) (...))
For each item in a list, do something foreach $item (@item-list) {
 }
(dolist (item item-list)
  )
Do something to each item in a list @new-list =
   map { some-func($_) } @item-list;
(setq new-list
  (mapcar 'some-func item-list))
Splitting a string @directory_levels = split m{/}, $filename;
(setq directory-levels-list (split-string filename "[/]" ))
Joining strings join( "/", @directory-levels)
(mapconcat 'identity directory-levels "/")
  ;; Note: identity is the way to do nothing
Regexps:
(this|that)

$pattern = "<\s*(.*?)\s*>";

\(this\|that\)

(setq pattern "<[  \t]*\\(.*?\\)[  \t]*>")
  ;; Note \( gets a second slash, but \t does not
String matching: Perl defaults to $_ and emacs to the current buffer
undef $/;
$_ = <>;
m{ $pattern };
$first_capture = $1;
(set-buffer some-stuff)
(re-search-forward pattern) ;; uses current buffer
(setq first_capture (match-string 1))
   ;; defaults to match data from current buffer.
Matching inside a given string $some_string =~ m{ $pattern };
$first_capture = $1;
(string-match pattern some-string)
(setq first_capture (match-string 1 some-string))
   ;; need to use string name again with match-string
Making a global change $string =~ s/TAG/current value/g;
(setq string
    (replace-regexp-in-string "TAG" "current value" string)

Alternately, working in the current buffer:

(while (re-search-forward "TAG" nil t)
    (replace-match "current value" nil nil))
Natural data structures arrays and hashes
lists and alists (and hashes. and property lists. and...)
Note: alists are ordered hashes with slow look-up times.





Further discussion of Emacs Lisp: Devnotes
Joseph Brenner, 26 Feb 2004
Thanks to Shawn Betts for some corrections.