Perl | Emacs Lisp | |
---|---|---|
Forcing variable declarations. | use strict; |
No equivalent. A typo in a variable name, silently creates a new global with default value of nil. |
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)) ... ) |
Subroutine with explicit return |
=item times_2 An inane example that multiples by 2. =cut sub times_2 { my $input = shift; my $output = 2 * $input; return $output } |
(defun times_2 (input) "An inane expample that multiplies by 2." (let* ((output * 2 input)) output)) |
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?")) |
String length | $len = length( $stringy ); | (setq len (length stringy)) |
Length of an array/list |
$len = scalar( @items ); or $len = $#items + 1; | (setq len (length items)) ;; something elisp got right |
Error messages |
Undefined subroutine &main:: ... called Global symbol " ... " requires explicit package name bash: ... Permission denied (You forgot to make it "executable".) |
Symbol's definition as function is void: ... Symbol's value as variable is void: ... Wrong type argument: commandp, ... (You forgot the "(interactive)".) |
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. A more exact parallel, with the code in the form of a string: (setq code-string "(somefunc (car (cdr blah)))") (eval (read code-string) |
Trapping errors |
use Carp; eval { my $ratio = $a / $b; } if ($@) { carp "Problem with ratio of $a and $b: $@"; } |
(condition-case nil (setq ratio (/ a b)) (error (message "Problem with integer divide of %s by %s" (pp-to-string a) (pp-to-string b)))) |
Closures
| A perl closure example | None in elisp |
repeat/untill |
use Term::ReadKey; $message = "Please input the name: "; do {{ print $message, "\n"; $name = ReadLine(0); chomp($name); $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))) ;; note: that's an empty while loop, all the code is in the conditional |
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 5.10.0; use feature "switch"; my $test_this = "something else"; given ( $test_this ) { when ( /something/ ) { print "case 1" } when ( "case two string" ) { print "case 2" } default { print "default" } }; |
(cond ((string-match "something" test_this) (message "case 1")) ((string= 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 $fh or die; |
(and debug_flag (message "Problem!")
(or (...) (...)) |
For each item in a list, do something |
foreach $item ( @item_list ) { ... } |
(require 'cl) (dolist (item item-list) ...) Alternately: (mapc (lambda (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)) |
Do something to each item in a list (part II) |
my @new_list = map { "Prefix: $_" } ( "AAA", "BBB", "CCC" ); Result: ('Prefix: AAA', 'Prefix: BBB', 'Prefix: CCC'); |
(setq temp-list (mapcar (lambda (item) (concat "Prefix: " item)) '("AAA" "BBB" "CCC"))) Result: ("Prefix: AAA" "Prefix: BBB" "Prefix: CCC") |
Splitting a string |
@directory_levels = split m{ / }x, $filename; |
(setq directory-levels-list (split-string filename "[/]" ))
;; even more perlish (it has a limit parameter) (require 'dired-aux) (setq limit 4) (setq octets (dired-split "[\\.]" ip-address limit)) |
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 }xms; $first_capture = $1; |
(set-buffer some-stuff) (if (re-search-forward pattern nil t) ;; uses current buffer (setq first-capture (match-string 1))) ;; match-string defaults to match data from current buffer. |
Matching inside a given string |
if( $some_string =~ m{ $pattern }x ) { $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)) |
comparison operators |
( $num1 == $num2 ) ( $str1 eq $str2 ) ( $ref1 eq $ref2 ) # identical reference ( == would work too) use Data::Compare; # Note: CPAN module, not core if( Compare( $ref1, $ref2 ) ){ ... } |
(= num1 num2) (string= str1 str2) (eq emacs_object1 emacs_object2) ;; same object (if (equal structure1 structure2) ( ... ) |
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. I talk about this some more: over here. |
| |