;;;
;;; What's wrong with all these parentheses?
;;;

hello("world");

;; vs

(hello "world")


;;;
;;; Arithmetic expressions
;;;

(+ 3 (+ 1 2)) ;; evaluation is done with with C-x C-e

(+ 3 1 2)

(/ 4 (+ 1 2))


;;;
;;; Variables
;;;

(defvar me "nico")

(setq me "Nicolas")


;;;
;;; Functions
;;;

;; one argument
(insert "Hello")

;; 2 arguments
(insert "Hello" " world!")


;;;
;;; function definition
;;;

(defun hello (name)
  "Doc string"
  (insert "Hello from " name))

(hello me)


;;;
;;; Local variable bindings with `let'
;;;

(let ((name "HAL"))
  (hello name))


;;;
;;; formatting strings
;;;

(format "Hello, %s" "you")

(defun hello (name)
  (format "Hello from %s!\n" name))


;;;
;;; Lists
;;;

(defvar list-of-names '("nicolas" "benjamin" "henrik"))

;; Adding to a list

(cons "mikael" list-of-names)
(push "mikael" list-of-names)

;; Push is "similar" to
(setq var (cons new-value var))

;; car & cdr

(car list-of-names)
(cdr list-of-names)

;; nil & lists

(listp nil)
(null nil)

(if nil
    'truthy
  'falsy)

(if 'non-nil
    'truthy
  'falsy)

;; Mapping

(defun greetings-from (names)
  (mapcar #'hello names))

(greetings-from list-of-names)

;;;
;;; Symbols
;;;

'hello

(eq 'hello 'hello)
(eq "hello" "hello")

(symbol-name 'hello)
(intern "hello")

(eq (intern "hello") 'hello)

(make-symbol "hello")
(eq (make-symbol "hello") 'hello)

;;;
;;; Quoting
;;;

'(+ 1 2) ;; => (+ 1 2)
(+ 1 2)  ;; => 3
't       ;; => t
t        ;; => t
'1       ;; => 1
1        ;; => 1


;;;
;;; Quasi-quoting
;;;

`(foo ,emacs-version bar)


;;;
;;; code as data & macros
;;;

'(+ 1 2 3)
(eval '(+ 1 2 3))

(+ 1 2 3)

(3 2 1 +)

(defmacro postfixed (list)
  (reverse list))

(postfixed (1 2 3 +))

;; macroexpansion

(macroexpand '(postfixed (1 2 3 +)))

(defmacro inc (n)
  (list 'setq n (list '+ n 1)))

;; With quasi-quoting
(defmacro inc (n)
  `(setq ,n (+ ,n 1)))

(macroexpand '(inc foo))

(defvar val 3)
(inc val)
val


;; if-not macro

(defmacro if-not (condition then else)
  `(if (not ,condition)
       ,then
     ,else))

;; Hygienic macros

(defmacro dorepeat (n form) ;; dotimes already exists and is much better ;)
  `(let ((max 0))
    (while (< max ,n)
      ,form
      (inc max))))

(dorepeat 5 (inc val))

;; so far so good, but...

(defvar max 0)
(dorepeat 5 (inc max))
max

;; What went wrong?

(macroexpand '(dorepeat 5 (inc max)))


;; Let's fix it!

(defmacro dorepeat (n form)
  (let ((max (make-symbol "max")))
    `(let ((,max 0))
       (while (< ,max ,n)
         ,form
         (inc ,max)))))

(dorepeat 5 (inc max))