code equivalences

This table showcases how to do various common tasks in a few different programming languages. Similar to Rosetta Code, but may work better as a quick reference.

The currently covered languages are: Common Lisp, Guile, Emacs Lisp, Pharo, Factor, Raku, Python, Tcl, SuperCollider, Lua, Fennel, Bash, Fish, and JavaScript.

The following external pages may also be useful references for these languages:

Contents

  1. Fundamental Types
  2. Syntax
  3. Functions
  4. Basics
  5. Math
  6. Sequences
  7. Strings
  8. Hashtables
  9. Namespaces
  10. Metaprogramming
  11. Introspection
  12. Info

Table

Show columns:

taskCommon LispGuileEmacs LispPharoFactorRakuPythonTclSuperColliderLuaFennelBashFishJavaScript
Fundamental Types
Null
nil
When differentiation between false and null is needed, some libraries use the symbol naming the type of the nil value (null).
#nil
nil
nil
f
Nil
None
unsupported
nil
nil
nil
unsupportedunsupported
null
Booleans
t nil
#t #f
t nil
true false
t f
True False
True False
1 0
true false
true false
true false
0 1
0 1
true false
Special atoms
#<unspecified> #<eof>
undefined
Special variables
thisContext
(?)(?)
this
thisFunction
_G
_G
(?)(?)
arguments
Symbol
'heyo
'heyo
'heyo
#heyo
heyo
Symbols defined with SYMBOL: are subsequently referred to using barewords.
heyo
unsupportedunsupported
\heyo
unsupported
:heyo
Fennel supports symbols, however they evaluate to their name (i.e. strings).
unsupportedunsupported
Symbol("heyo")
String
"Foo"
"Foo"
"Foo"
'Foo'
"Foo"
"Foo"
"Foo"
"Foo"
Curly braces ({ and }) are used for literal strings (no interpolation).
"Foo"
"Foo"
"Foo"
"Foo"
"Foo"
"Foo"
Character
#\F
#\F
?F
Emacs represents characters with Unicode codepoints, so this code results in 70.
$F
CHAR: F
Factor represents characters with Unicode codepoints, so this code results in 70.
unsupportedunsupportedunsupported
$F
unsupportedunsupportedunsupportedunsupportedunsupported
Unicode character (by codepoint)
(code-char 10084)
(integer->char 10084)
10084
Emacs represents characters with Unicode codepoints. A list of codepoints can be converted to a string with concat.
Character codePoint: 10084
10084
Factor represents characters with their Unicode codepoints. An array of codepoints can be converted to a string with >string.
"\c[10084]"
Raku does not have a character type; this example uses interpolation to produce a single-character string.
chr(10084)
Python does not have a character type; chr returns a single-character string.
"u2764"
Tcl does not have a character type; this example uses the Unicode character escape sequence to create a single-character string from the codepoint at hex 0x2764 (dec 10084).
10048.asAscii
SuperCollider only supports ASCII, not Unicode.
unsupportedunsupportedunsupportedunsupported
"u{2764}"
JavaScript does not have a character type; this example uses the Unicode character escape sequence to create a single-character string from the codepoint at hex 0x2764 (dec 10084).
Unicode character (by name)
#\HEAVY_BLACK_HEART
(use-modules (ice-9 unicode))
(formal-name->char "HEAVY BLACK HEART")
?\N{HEAVY BLACK HEART}
Emacs represents characters as Unicode codepoints, so this code results in 10084.
(UnicodeCharacterData named: 'HEAVY BLACK HEART') character
This example requires the Unicode-Character-DataUnicode-Character-Data external library. Unicode characters can be looked up by their code point in stock Pharo using code like Character codePoint: 10084.
CHAR: heavy-black-heart
Factor represents characters as Unicode codepoints, so this code results in 10084.
"\c[heavy black heart]"
Raku does not have a character type; this example uses interpolation to produce a single-character string.
\N{HEAVY BLACK HEART}
Python does not have a character type; this example uses interpolation to produce a single-character string.
(?)unsupportedunsupportedunsupportedunsupportedunsupportedunsupported
Ratio
4/3
4/3
unsupported
4/3
4/3
4/3
import fractions
fractions.Fraction(4, 3)
unsupported
4/3
unsupportedunsupportedunsupportedunsupportedunsupported
Sequence (idiomatic)
'(1 2 3)
'(1 2 3)
'(1 2 3)
#(1 2 3)
{ 1 2 3 }
[1, 2, 3]
[1, 2, 3]
{1 2 3}
[1, 2, 3]
{1, 2, 3}
[1 2 3]
(1 2 3)
1 2 3
[1, 2, 3]
Linked list
'(1 2 3)
'(1 2 3)
'(1 2 3)
| linkedList |
linkedList := LinkedList new.
linkedList add: 1.
linkedList add: 2.
linkedList add: 3.
Pharo supports linked lists, but arrays are more idiomatic.
L{ 1 2 3 }
Factor supports linked lists, but arrays are more idiomatic.
(1, 2, 3)
from collections import deque
deque([1, 2, 3])
unsupported
List.newUsing([1, 2, 3])
unsupportedunsupportedunsupportedunsupportedunsupported
Array
#(1 2 3)
#(1 2 3)
[1 2 3]
#(1 2 3)
{ 1 2 3 }
[1, 2, 3]
[1, 2, 3]
Python refers to its arrays as lists, however they are not traditional linked lists a la Lisp.
{1 2 3}
[1, 2, 3]
{1, 2, 3}
Lua uses tables as both arrays and as hashtables.
[1 2 3]
Fennel uses tables as both arrays and hashtables, albeit with different syntax
(1 2 3)
1 2 3
[1, 2, 3]
Syntax
Comment
; Do something.
; Do something.
; Do something.
"Do something."
! Do something.
# Do something.
# Do something.
;# Do something.
// Do something.
-- Do something.
; Do something.
# Do something.
# Do something.
// Do something.
Multi-line comment
#| hello line 1
hello line 2 |#
#! hello line 1
hello line 2 !#
unsupported
"hello line 1
hello line 2"
USE: multiline
/* hello line 1
hello line 2 */
Factor supports a syntax that resembles multi-line comments, but single line comments (with !) are much more common.
#`( hello line 1
hello line 2 )
"""hello line 1
hello line 2"""
unsupported
/* hello line 1
hello line 2 */
--[[ hello line 1
hello line 2 ]]
unsupportedunsupportedunsupported
/* hello line 1
hello line 2 */
Basic math
(* (+ 1 3) 4)
(* (+ 1 3) 4)
(* (+ 1 3) 4)
1 + 3 * 4.
1 3 + 4 *
(1 + 3) * 4;
(1 + 3) * 4
expr {(1 + 3) * 4}
1 + 3 * 4
(1 + 3) * 4
(* (+ 1 3) 4)
$(((1 + 3) * 4))
math '(1 + 3) * 4'
(?)
Define variable
(defvar foo)
(define foo)
(defvar foo)
| foo |
SYMBOL: foo
our $foo;
global foo
set foo ""
~foo;
local foo
(var foo nil)
foo=
set foo
(?)
Define variable with initial value
(defparameter foo 3)
(define foo 3)
(defvar foo 3)
| foo |
foo := 3.
SYMBOL: foo 3 foo set
our $foo = 3;
global foo
foo = 3
set foo 3
~foo = 3;
local foo = 3
(var foo 3)
foo=3
set foo 3
(?)
Define variable with initial value, not overwriting existing value
(defvar foo 3)
(define foo 3)
(defvar foo 3)
unsupported
Pharo does not allow referencing undefined variables, and all defined variables default to nil.
INITIALIZED-SYMBOL: foo [ 3 ]
unsupported
Raku has the //= operator, which sets a variable's value only if it is not already set, but this doesn't seem to work when combined with variable declarations such as my or our.
(?)
if {![info exists foo]} { set foo 3 }
~foo = ~foo ? 3;
Variables default to nil, and the ? operator returns the first non-nil value.
(?)(?)(?)
if not set -q foo; set foo 3; end
(?)
Functions
Anonymous function (lambda)
(lambda (x y) (+ x y))
(lambda (x y) (+ x y))
(lambda (x y) (+ x y))
[ :x :y | x + y ]
[ + ]
sub ($x, $y) { $x + $y }
lambda x, y: x + y
(?)
{ | x y | x + y; }
function (x, y) x + y end
(fn [x y] (+ x y))
unsupportedunsupported(?)
Define function
(defun plus-3 (x) (+ x 3))
(define (plus-3 x) (+ x 3))
(defun plus-3 (x) (+ x 3))
| plus_3 |
plus_3 := [ :x | x + 3 ]
Typically, functions are defined as methods in a class rather than as blocks (anonymous functions) as shown here.
: plus-3 ( x -- y ) 3 + ;
sub plus-three($x) { return $x + 3; }
def plus_3(x): return x + 3
proc plus_3 {x} { return [expr {$x + 3}] }
~plus_3 = { | x | x + 3; };
function plus_3(x) x + 3 end
(fn plus-3 [x] (+ x 3))
plus_3() { echo $(($1 + 3)); }
function plus_3; math $x + 3; end
(?)
Define variadic function
(defun print-each (&rest x)
  (mapcar 'print x))
(define (print-each . x)
  (for-each write x))
(defun print-each (&rest x)
  (mapcar 'print x))
(?)unsupported
Stack languages like Factor do not support variadic functions in the traditional sense. Alternatives include passing a sequence, or writing a parsing word with SYNTAX:.
sub print-each(*@x) {
  @x.map: &say
}
def print_each(*x): print(*x, sep='n')
proc print-each args { foreach arg $args { puts $arg } }
~print_each = { | ... x |
  x.do(_.postln)
};
function print_each(...)
  for _, v in ipairs({...}) do
    print(v)
  end
end
(fn print-each [...]
  (each [_ v (ipairs [...])] (print v)))
print_each() {
  for arg in "$@"
    do echo "$arg"
  done
}
function print-each
  for arg in $argv
    echo $arg
  end
end
function print_each() {
  Array.from(arguments).forEach(console.log);
}
Call function with arguments
(my-func 1 2)
(my-func 1 2)
(my-func 1 2)
my_func value: 1 value: 2.
1 2 my-func
my-func(1, 2)
my_func(1, 2)
my_func 1 2
my_func.value(1, 2);
my_func(1, 2)
(my-func 1 2)
my_func 1 2
my_func 1 2
my_func(1, 2)
Call function specified in variable
(funcall my-func 1 2)
(my-func 1 2)
(funcall my-func 1 2)
(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)
Call function with arguments specified as sequence
(apply #'my-func '(1 2))
(apply my-func '(1 2))
(apply #'my-func '(1 2))
(?)(?)(?)(?)(?)(?)(?)
(my-func (table.unpack [1 2]))
(?)(?)(?)
Basics
Print (no newline)
(princ "Hello.")
(display "Hello.")
(message "Hello.")
Transcript show: 'Hello.'.
"Hello." write
"Hello.".print;
print("Hello.", end="")
puts -nonewline Hello.
"Hello.".post;
io.write("Hello.")
(io.write "Hello.")
echo -n "Hello."
echo -n "Hello."
(?)
Print (with newline)
(format t "~A~%" "Hello.")
(display "Hello.")
(newline)
(message "%s\n" "Hello.")
Transcript show: 'Hello.'; cr.
"Hello." print
"Hello.".say;
print("Hello.")
puts "Hello."
"Hello.".postln;
print("Hello.")
(print "Hello.")
echo "Hello."
echo "Hello."
(?)
If statement
(if some-test then-do-this else-this)
(if some-test then-do-this else-this)
(if some-test then-do-this else-this)
someTest ifTrue: [ thenDoThis ]; ifFalse: [ elseThis ].
some-test [ then-do-this ] [ else-this ] if
if some-test { then-do-this } else { else-this }
if some_test:
  then_do_this
else:
  else_this
if [some_test] { do_this } else { else_this }
if(some_test, { then_do_this }, { else_this })
if some_test then then_do_this else else_this end
(if some-test then-do-this else-this)
if some_test; then then_do_this; else else_this; fi
if some_test; then_do_this; else; else_this; end
(?)
Get type of datum
(type-of datum)
(use-modules (oop goops))
(class-of datum)
(type-of datum)
datum class.
datum class-of
datum.WHAT
type(datum)
::tcl::unsupported::representation $datum
can be used.
datum.class
type(datum)
(type datum)
unsupportedunsupported
typeof(datum)
Get object's string representation
(format "~S" obj)
(format #f "~S" obj)
(format "%s" obj)
obj storeString.
"%u" sprintf
$obj.raku
repr(obj)
(?)
obj.cs;
tostring(obj)
Lua does not have a built-in way to get a string representation of a table.
(fennel.view obj)
unsupportedunsupported
JSON.stringify(obj)
Print object's string representation
(print obj)
(write obj)
(message (format "%s" obj))
Transcript show: obj.
obj .
$obj.raku.say
print(obj)
(?)
obj.postcs;
print(obj)
Lua's print will not print the contents of tables or other compound objects; this functionality has to be implemented by the user. For tables, it can be done with for key, value in pairs(obj) do print(key, value) end
(print (fennel.view obj))
echo $obj
echo $obj
console.log(obj)
Read a line of text
(read-line)
(use-modules (ice-9 rdelim))
(read-line)
(read-string "Enter some text: ")
SpRequestTextDialog new openModal.
readln
prompt()
input()
gets stdin
EZText(action:{ | widget | f = widget.value; widget.window.close; });
SuperCollider's EZText is a graphical text field widget. Its callback action must be set to a function which binds the field's text to a variable (f in this case).
io.read()
(io.read)
read var
bash's read should be called with a variable name to specify where to write the text into. Without it, text is read, but discarded.
read
prompt()
Math
Infinity(?)(?)(?)(?)(?)(?)(?)
expr Inf
inf
(?)(?)(?)(?)(?)
Random integer from 0 below N
(random n)
(random n)
(random n)
n atRandom - 1
n random
n.rand.Int
from random import randint
randint(0, n - 1)
expr { int(rand() * n) }
n.rand
require("math")
math.random(0, n - 1)
(local math (require :math))
(math.random 0 (- n 1))
$(($RANDOM % $n))
random 0 (math $n - 1)
Math.floor(Math.random() * n)
Random float from 0 below N
(random n)
must be a float.
(random n)
must be a float.
(random* n)
must be a float.
(?)
n random
must be a float.
n.rand
from random import random
random() * n
expr { rand() * n }
n.rand
must be a float.
(?)(?)(?)(?)
Math.random() * n
Sequences
Sequence length
(length my-sequence)
(length my-sequence)
(length my-sequence)
my_array size
my-array length
@my-array.elems
len(my_list)
llength $my_list
my_array.size
#my_table
(length my-table)
${#my_list[@]}
count $my_list
my_array.length
First sequence element
(first my-list)
(car my-list)
(car my-list)
my_array first
my-array first
@my-array.first
my_list[0]
lindex $my_list 0
my_array.first
my_table[1]
(. my-table 1)
${my_list[0]}
$my_list[1]
my_array[0]
Second sequence element
(second my-list)
(list-ref my-list 1)
(cadr my-list)
my_array second
my-array second
@my-array[1]
my_list[1]
lindex $my_list 1
my_array[1]
my_table[2]
(. my-table 2)
${my_list[2]}
$my_list[2]
my_array[1]
Last sequence element
(car (last my-list))
(car (last-pair my-list))
(car (last my-list))
my_array last
my-array last
@my-array.tail
my_list[-1]
(?)
my_array.last
my_table[#my_table]
(. my-table (length my-table))
${my_list[-1]}
$my_list[-1]
my_array[my_array.length-1]
Sequence element at index N
(nth n my-list)
(list-ref my-list n)
(nth n my-list)
my_array at: n
n my-array nth
@my-array[n]
my_list[n]
lindex $my_list n
my_array[n]
my_table[n]
Note that Lua tables start from index 1.
(. my-table n)
Since Fennel compiles to Lua, its tables also start from index 1
${my_list[n]}
$my_list[n]
Note that Fish lists start from index 1.
my_array[n]
First N elements of sequence
(subseq my-list 0 n)
(list-head my-list n)
(subseq my-list 0 n)
myList first: n.
my-array n head
@my-array.head(n)
my_list[:n]
(?)
my_array.keep(n)
table.unpack(my_table, 1, n)
(table.unpack my-table 1 n)
"${my_array[@]:0:$n}"
$my_list[..$n]
(?)
Sequence without first N elements
(subseq my-list n)
(list-tail my-list n)
(subseq my-list n)
myList allButFirst: n
my-array n tail
@my-array[n..*]
my_list[n:]
(?)
my_array[n..]
table.unpack(my_table, n+1)
(table.unpack my-table (+ n 1))
(?)
$my_list[(math $n + 1)..]
(?)
Sequence of last N elements
(last my-list n)
(list-tail my-list (- (length my-list) n))
(last my-list n)
myList last: n
my-array n tail*
@my-array.tail(n)
my_list[-n:]
(?)
my_array.keep(-n)
table.unpack(my_table, #my_table-(n-1))
(table.unpack my-table (- (length my-table) (- n 1)))
(?)
$my_list[(math - $n)..]
(?)
Sequence without last N elements
(butlast my-list n)
(list-head my-list (- (length my-list) n))
(butlast my-list n)
myList allButLast: n
my-array n head*
(?)
my_list[:-n]
(?)
my_array.drop(-n)
table.unpack(my_table, 1, #my_table-n)
(table.unpack my-table 1 (- (length my-table) n))
(?)
$my_list[..(math "-1 * $n - 1")]
(?)
Sequence subsequence
(subseq my-seq start end)
(list-head (list-tail my-list start) (- end start))
This only works for lists, not other types of sequences.
(subseq my-seq start end)
mySeq copyFrom: start to: end
start end my-array subseq
@my-array[start..end-1]
my_list[start:end]
(?)
my_array[start..end-1]
table.unpack(my_table, start, end)
(table.unpack my-table start end)
(?)
$my_list[start..end]
(?)
Filter sequence to items true of predicate
(remove-if-not pred my-list)
(filter pred my-list)
(cl-remove-if-not pred my-list)
myList select: [ :x | x pred. ].
my-array pred filter
@my-array.grep(pred)
[i for i in my_list if pred(i)]
(?)
my_array.select(pred)
(?)(?)(?)(?)(?)
Filter sequence to items false of predicate
(remove-if pred my-list)
(filter (lambda (x) (not (pred x))) my-list)
(cl-remove-if pred my-list)
myList reject: [ :x | x pred. ].
my-array pred reject
(?)
[i for i in my_list if not pred(i)]
(?)
my_array.reject(pred)
(?)(?)(?)(?)(?)
Remove instances of item from sequence
(remove item my-list)
(use-modules (srfi srfi-1))
(remove (lambda (i) (eq? i item)) my-list)
(cl-remove item my-list)
(?)
item my-sequence remove
(?)
[i for i in my_list if i != item]
(?)
my_array.removeEvery([item])
(?)(?)(?)(?)(?)
Test for item in sequence
(find item my-list)
(member item my-list)
(member item my-list)
myList includes: item.
item my-array member?
@my-array.first(pred)
item in my_list
(?)
my_array.includes(item)
(?)(?)(?)
contains item $my_list
(?)
Get index of item in sequence
(position item my-list)
(list-index my-list item)
(cl-position item my-list)
myList indexOf: item.
item my-array index
(?)
my_list.index(item)
(?)
my_array.indexOf(item)
(?)(?)(?)
contains --index item $my_list
(?)
Get first item in sequence matching predicate
(find-if pred my-list)
(find pred my-list)
(cl-find-if pred my-list)
myList detect: [ :x | x pred. ].
my-array pred find
find returns both the matching item and its index; nip can be used to discard the index.
@my-array.first(pred)
(?)(?)
my_array.detect(pred)
(?)(?)(?)(?)(?)
Get index of first element matching predicate
(position-if pred my-list)
(list-index pred my-list)
(cl-find-if pred my-list)
(?)
my-array pred find
find returns both the matching item and its index; drop can be used to discard the item.
(?)(?)(?)
my_array.detectIndex(pred)
(?)(?)(?)(?)(?)
Test if all items in sequence match predicate
(every pred my-list)
(every pred my-list)
(cl-every pred my-list)
(?)
my-sequence pred all?
(?)(?)(?)
my_array.every(pred)
(?)(?)(?)(?)(?)
Count occurrences of item in sequence
(count item my-list)
(count (lambda (x) (equal? x item)) my-list)
(cl-count item my-list)
myList occurrencesOf: item
my-sequence [ item = ] count
(?)
my_list.count(item)
(?)
my_array.occurrencesOf(item)
(?)(?)(?)(?)(?)
Count items in sequence matching predicate
(count-if pred my-list)
(count pred my-list)
(cl-count-if pred my-list)
myList count: pred
my-sequence pred count
(?)
len(list(filter(pred, my_list)))
(?)
my_array.count(pred)
(?)(?)(?)(?)(?)
Apply function to each element, collecting results (map)
(mapcar func my-list)
(map func my-list)
(mapcar func my-list)
myList collect: [ :x | func ].
my-array func map
@my-array.map(func)
(?)(?)
my_array.collect(func)
(?)(?)(?)(?)(?)
Combine elements of a sequence with a function (fold/reduce)
(reduce func my-list)
(reduce func identity my-list)
(seq-reduce func my-list identity)
myList inject: identity into: func
my-sequence identity func reduce
reduce &func, @my-array
(?)(?)
my_array.reduce(func)
(?)(?)(?)(?)(?)
Elements common to two sequences (set intersection)
(intersection list-1 list-2)
(use-modules (srfi srfi-1))
(lset-intersection = list-1 list-2)
(intersection list-1 list-2)
(?)
array-1 array-2 intersect
(?)(?)(?)
array1.sect(array2)
(?)(?)(?)(?)(?)
Elements only in the first of two sequences (set difference)
(set-difference list-1 list-2)
(use-modules (srfi srfi-1))
(lset-difference = list-1 list-2)
(set-difference list-1 list-2)
list1 difference: list2
sequence-1 sequence-2 diff
(?)(?)(?)
array1.difference(array2)
(?)(?)(?)(?)(?)
Combine two sequences without duplicates (set union)
(union list-1 list-2)
(?)
(union list-1 list-2)
list1 union: list2
sequence-1 sequence-2 union
(?)(?)(?)
array1.union(array2)
(?)(?)(?)(?)(?)
Remove duplicates in sequence
(remove-duplicates my-list)
(?)
(cl-remove-duplicates my-list)
(?)
my-seq members
(?)(?)(?)
my_array.asSet.asArray
Converting to a set will not preserve the order of elements in the array.
(?)(?)(?)(?)(?)
Remove duplicates in sequence, comparing with predicate
(remove-duplicates my-list :test pred)
(?)
(cl-remove-duplicates my-list :test pred)
(?)
[let
    { } :> seen!
    my-seq [
        [ [ comparison-word ] curry seen swap find drop ]
        [ seen swap suffix seen! ] bi
    ] reject
]
There may be a better way of doing this than is implemented here. Typically, deduplication with the standard comparison check can be done more simply with members.
(?)(?)(?)(?)(?)(?)(?)(?)(?)
Reverse sequence
(reverse my-list)
Common Lisp also has an nreverse function which reverses in place.
(reverse my-list)
(reverse my-list)
myArray reverse
my-sequence reverse
@my-array.reverse
my_list.reverse()
my_list
Python's list.reverse method reverses in place.
(?)
my_array.reverse
(?)(?)(?)(?)
my_array.toReversed()
JavaScript also has a .reverse() method which reverses in place.
Sort sequence in natural order
(sort my-list #'<)
(?)
(sort my-list #'<)
myList sorted
my-sequence sort
(?)(?)(?)
my_array.sort
(?)(?)(?)(?)
my_array.toSorted(pred)
Sort sequence by predicate
(sort my-list pred)
(?)
(sort my-list pred)
myList sorted: pred
my-sequence pred sort-by
(?)(?)(?)
my_array.sort(pred)
(?)(?)(?)(?)
my_array.toSorted(pred)
Strings
Unicode supportimplementation-dependent
Most popular Common Lisp implementations fully support Unicode: SBCL, CCL, LispWorks, Allegro, ECL, and ABCL. Older and defunct implementations such as CLISP, CMUCL, and GCL do not.
supportedsupportedsupportedsupportedsupportedsupportedsupported
Supported as of v8.1.
unsupported
Unicode can be put in strings, however characters can only be 1 byte long.
unsupportedunsupportedsupportedsupportedsupported
Unicode string length
(length "🤦🏼‍♂️") ; 5
(string-length "🤦🏼‍♂️") ; 5
(length "🤦🏼‍♂️") ; 5
'🤦🏼‍♂️' size. "5"
"🤦🏼‍♂️" length ! 5
"🤦🏼‍♂️" >graphemes length ! 1
"🤦🏼‍♂️".elems # 1
len("🤦🏼‍♂️") # 5
string length "🤦🏼‍♂️" ;# 7
"🤦🏼‍♂️".size // 17
string.len("🤦🏼‍♂️") -- 17
(length "🤦🏼‍♂️") ; 17
foo='🤦🏼‍♂️'; echo ${#foo} # 5
string length "🤦🏼‍♂️" # 5
"🤦🏼‍♂️".length // 7
String concatenation
(concatenate 'string "foo" "bar")
(string-append "foo" "bar")
(concat "foo" "bar")
'foo', 'bar'
"foo" "bar" append
"foo" ~ "bar"
"foo" + "bar"
(?)
"foo" ++ "bar"
(?)
(.. "foo" "bar")
"foo""bar"
"foo""bar"
(?)
String subsequence
(subseq "foo bar" 0 3)
(substring "foo bar" 0 3)
(substring "foo bar" 0 3)
'foo bar' copyFrom: 1 to: 3.
0 3 "foo bar" subseq
substr("foo bar", 0, 3)
"foo bar"[0:3]
(?)
"foo bar"[0..2]
(?)
(string.sub "foo bar" 1 3)
(?)
string sub -s 1 -e 4 "foo bar"
(?)
Lowercase string
(string-downcase "FOO")
(?)
(downcase "FOO")
'FOO' asLowercase
"FOO" >lower
"FOO".lc
"FOO".lower()
(?)
"FOO".toLower
(?)
(string.lower "FOO")
(?)
string lower FOO
"FOO".toLowerCase()
Hashtables
Hash table
(make-hash-table)
(make-hash-table)
(make-hash-table)
Dictionary new
8 <hashtable>
&lt;hashtable&gt; requires an initial size.
Hash()
(?)
dict create
Dictionary()
(?)
{}
Like Lua, Fennel uses tables for arrays and "hash tables".
declare -A my_hash
bash requires a name for the variable when declaring it a hash.
unsupported(?)
Hash table literalunsupported(?)
#s(hash-table data (foo 1 bar 2))
unsupported
H{ { "foo" 1 } { "bar" 2 } }
{foo => 1, bar => 2}
(?)(?)
(foo: 1, bar: 2)
SuperCollider's events (used for this example) do not support looking up keys by strings, so symbols are used.
(?)
{:foo 1 :bar 2}
declare -A my_hash=( [foo]=1 [bar]=2 )
unsupported(?)
Get the value of key in hash table
(gethash "key" hash)
(?)
(gethash "key" hash)
myDict at: key
hash "key" at
%hash{"key"}
(?)
dict get $hash "key"
dict.at(key)
(?)
(. dict key)
${hash[key]}
unsupported(?)
Set the value of key in hash table
(setf (gethash "key" hash) 9)
(?)
(puthash "key" 9 hash)
myDict at: 'key' put: 9
9 "key" hash set-at
%hash{"key"} = 9;
(?)
dict set hash key
dict.put(key, 9)
(?)
(set (. dict key) 9)
hash[key]=9
unsupported(?)
Get list of keys in hash table
(loop for key being the hash-keys of hash collect key)
(?)
(hash-table-keys hash)
myDict keys
hash keys
%hash.keys;
(?)
dict keys $hash
dict.keys
(?)(?)
${!hash[@]}
unsupported(?)
Namespaces
Define a namespace
(defpackage #:my-package ...)
(define-module (my-module) ...)
unsupported
Emacs does not support namespaces. Instead, the convention is to prefix all of a package's symbols with the name of the package and a dash; for example cl-position is the position function from the cl-lib library.
(?)
"my-vocab" create-vocab
Typically new vocabularies (namespaces) are defined with IN:, which also sets the current active vocabulary, simply switching to it if it already exists.
(?)(?)(?)
Environment()
(?)(?)unsupportedunsupported(?)
Get the current namespace
*package*
(current-module)
unsupported(?)
current-vocab
(?)(?)(?)
currentEnvironment
(?)(?)unsupportedunsupported(?)
Set the current namespace
(in-package #:my-package)
(set-current-module (resolve-module '(my-module)))
unsupported(?)
IN: my-vocab
IN: will also create the vocabulary if it doesn't already exist.
(?)(?)(?)
env.push
(?)(?)unsupportedunsupported(?)
Use a namespace
(use-package #:other-package)
(use-modules (my-module) ...)
unsupported(?)
USE: other-vocab
use MyModule;
(?)(?)
env.use(func)
In this example, env is the environment (namespace) being used, and func is the function being evaluated in that environment.
(?)(?)unsupportedunsupported(?)
Metaprogramming
Define macro
(defmacro my-macro (arg-1 arg-2)
  `(do-thing ,arg-1 ,arg-2))
(define-syntax my-macro
  (syntax-rules ()
    ((_ arg-1 arg-2)
     (do-thing arg-1 arg-2))))
(defmacro my-macro (arg-1 arg-2)
  `(do-thing ,arg-1 ,arg-2))
(?)(?)
macro my-macro($arg-1, $arg-2) {
  quasi { do-thing({{{ $arg-1 }}, {{{ $arg-2 }}) }
}
unsupported(?)unsupportedunsupported
(macro my-macro [arg-1 arg-2]
  `(do-thing ,arg-1 ,arg-2))
unsupportedunsupportedunsupported
Introspection
Describe object
(describe obj)
(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)unsupportedunsupported(?)
Inspect object
(inspect obj)
Most Lisp environments also support various shortcuts for inspection in their own inspectors.
(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)unsupportedunsupported(?)
Get object's instance variables
(closer-mop:class-slots (class-of obj)) ; get slot definition objects
(closer-mop:slot-definition-name slot) ; get a slot's name
(?)(?)
obj class instanceVariables
obj class-of all-slots
obj.^methods
dir(obj)
(?)(?)(?)(?)unsupportedunsupported(?)
Get object's methods
(closer-mop:specializer-direct-methods (class-of obj))
This function only returns direct methods of the specified class; it does not return all functions applicable to the object.
(?)(?)
obj class methods
(?)
obj.^methods
dir(obj)
(?)
obj.class.methods
(?)(?)unsupportedunsupported(?)
Info
Software
  • Guix (OS/package manager)