Quicklisp, 2

Euler problem 13

.

To run the following code, you have to install the Quicklisp library manager by following the steps in my blog post titled cmu-infix.

(ql:quickload "str")

(defun file-get-contents (filename)
  (with-open-file (stream filename)
    (let ((contents (make-string
                     (file-length stream))))
      (read-sequence contents stream)
      contents)))

(defun file-get-lines (filename)
  (with-open-file (stream filename)
    (loop :for line = (read-line stream nil)
          :while line
          :collect line)))

(file-get-lines #P"n.txt")

(defun string-to-list (the-string)
  (loop :for char :across the-string
        :collect char))

(defun char-to-integer-list (char-list)
  (mapcar #'digit-char-p char-list))

(let ((the-list (file-get-contents #P"n.txt")))
  (subseq
   (prin1-to-string
    (reduce
     #'+
     (mapcar
      #'parse-integer
      (butlast (str:split #\newline the-list)))))
   0 10))

— Me@2023-05-26 12:16:50 PM

.

.

2023.05.26 Friday (c) All rights reserved by ACHK

MacBook Pro A1502

Euler problem 12.1.2

.

(defun good-reverse (lst)
  (labels ((rev (lst acc)
             (if (null lst)
                 acc
                 (rev
                  (cdr lst)
                  (cons (car lst) acc)))))
    (rev lst nil)))

(defparameter *primes* '(2 3 5))

(defun primeFactors (n)
  (factor-iter n *primes* '()))

(defun range (max &key (min 0) (step 1))
  (loop :for n :from min :below max :by step
        collect n))

(defun primep (x)
  (NULL (cdr (primeFactors x))))

(defun factor-iter (n p-list acc-list)
  (let* ((p (car p-list))
         (ps (cdr p-list)))
    (cond ((> (* p p) n)
           (good-reverse (cons n
                               acc-list)))
          ((eql (mod n p) 0)
           (factor-iter (floor n p)
                        p-list
                        (cons p acc-list)))
          ((NULL ps)
           (let* ((op
                    *primes*)
                  (num-extend
                    (range (1+
                            (ceiling (sqrt n)))
                           :min (+ p 2)
                           :step 2))
                  (primes-extend
                    (remove-if-not
                     #'primep
                     num-extend)))
             (if (NULL primes-extend)
                 (cons n acc-list)                
                 (progn
                   (setf *primes*
                         (append op primes-extend))
                   (factor-iter n
                                primes-extend
                                acc-list)))))
          ('t
           (factor-iter n ps acc-list)))))

(defmacro prime-filter (n)
  `(remove-if-not #'primep
                  (cons 2
                        (range (1+ ,n)
                               :min 3
                               :step 2))))

(time (length (prime-filter 20000000)))

;; Evaluation took:
;; 13.056 seconds of real time
 
;; 1270607

— Me@2023-03-28 11:51:24 AM

.

.

2023.04.11 Tuesday (c) All rights reserved by ACHK

Euler problem 12.1.1

(defmacro sq (x)
  `(* ,x ,x))

(defmacro last-item (lst)
  `(car (last ,lst)))

(defun good-reverse (lst)
  (labels ((rev (lst acc)
             (if (null lst)
                 acc
                 (rev
                  (cdr lst)
                  (cons (car lst) acc)))))
    (rev lst nil)))

(defun prime-sieve-a-list (input-lst)
  (labels ((sieve-iter (go-lst acc-list)
             (if (not go-lst) 
                 acc-list        
                 (if (> (sq (car go-lst))
                        (last-item go-lst))

                     (append (good-reverse acc-list)
                             go-lst)
                     
                     (sieve-iter
                      (remove-if #'(lambda (x)
                                     (=
                                      (mod x
                                           (car go-lst))
                                      0))
                                 (cdr go-lst))
                      (cons (car go-lst)
                            acc-list))))))

    (sieve-iter input-lst '())))

(defun range (max &key (min 0) (step 1))
  (loop :for n :from min :below max :by step
        collect n))

(defmacro prime-sieve (n)
  `(prime-sieve-a-list (cons 2
                             (range (1+ ,n)
                                    :min 3
                                    :step 2))))


(time (length (prime-sieve 20000000)))

;; Evaluation took:
;; 19.907 seconds of real time

What is the value of the first triangle number to have over five hundred divisors?

(defun factor-iter (n p-list acc-list)
  (if (NULL p-list)
      acc-list         
      (let* ((p (car p-list))                                   
             (ps (cdr p-list)))  
        (cond ((> (* p p) n)           
               (good-reverse (cons n
                                   acc-list)))
              ((eql (mod n p) 0)
               (factor-iter (floor n p)
                            p-list
                            (cons p acc-list)))   
              ('t
               (factor-iter n ps acc-list))))))

(defparameter *pm* 2000000)

(defparameter *psi* (prime-sieve *pm*))

(defun factor (n)
  (if (> n (expt *pm* 2))
      
      (let ((m (floor (sqrt n))))
        (factor-iter n (prime-sieve m) '()))
      
      (factor-iter n *psi* '())))

(defun group-factors (lst)
  (labels ((gf (acc lst)
             (if (NULL lst)
                 (good-reverse acc)
                 (let* ((p (car lst))
                        (ps (cdr lst))
                        (lp1 (list p 1)))
                   (if (NULL acc)                      
                       (gf (list lp1) ps)                      
                       (if (eql p (caar acc))
                           (gf (cons
                                (list p
                                      (+ 1
                                         (cadar acc)))
                                (cdr acc))
                               ps)                  
                           (gf (cons lp1 acc) ps)))))))    
    (gf '() lst)))

(defmacro sum (lst)
  `(reduce #'+ ,lst))

(defmacro product (lst)
  `(reduce #'* ,lst))

(defun nDiv (n)
  (product (mapcar #'(lambda (x) (1+ (cadr x)))
                   (group-factors (factor n)))))

(defun fm (m n)
  (labels ((tri-div (n)
             (if (evenp n)
                 (* (nDiv (/ n 2)) (nDiv (1+ n)))
                 (* (nDiv n) (nDiv (/ (1+ n) 2))))))    

    (if (> (tri-div n) m)
        (/  (* n (1+ n)) 2) 
        (fm m (+ 1 n)))))

;

(time (fm 500 1))

;; Evaluation took:
;; 0.007 seconds of real time

;; 76576500

— Me@2023-03-25 07:51:18 PM

.

.

2023.03.27 Monday (c) All rights reserved by ACHK

Euler problem 10.1

Find the sum of all the primes below two million.

(defmacro sq (x)
  `(* ,x ,x))

(defmacro last-item (lst)
  `(car (last ,lst)))

(defun good-reverse (lst)
  (labels ((rev (lst acc)
         (if (null lst)
         acc
         (rev
          (cdr lst)
          (cons (car lst) acc)))))
    (rev lst nil)))

(defun prime-sieve-a-list (input-lst)
  (labels ((sieve-iter (go-lst acc-list)
         (if (not go-lst) 
         acc-list        
         (if (> (sq (car go-lst))
            (last-item go-lst))

             (append (good-reverse acc-list)
                 go-lst)
             
             (sieve-iter
              (remove-if #'(lambda (x)
                     (=
                      (mod x (car go-lst))
                      0))
                 (cdr go-lst))
              (cons (car go-lst)
                acc-list))))))

    (sieve-iter input-lst '())))

(defun range (max &key (min 0) (step 1))
  (loop :for n :from min :below max :by step
    collect n))

(defmacro prime-sieve (n)
  `(prime-sieve-a-list (cons 2 (range (1+ ,n)
                      :min 3
                      :step 2))))

(defun sum (lst)
  (reduce #'+ lst))

(sum (prime-sieve 2000000))

(time (sum (prime-sieve 2000000)))

— Me@2023-02-16 11:34:49 PM

.

.

2023.02.21 Tuesday (c) All rights reserved by ACHK

cmu-infix

is

a library for writing infix mathematical notation in Common Lisp.

To install it:

1. In the Bash terminal, get Quicklisp by the following command:

sudo apt-get install cl-quicklisp

The file quicklisp.lisp will be created at

/usr/share/common-lisp/source/quicklisp/quicklisp.lisp

.

2. Run the command

sbcl --load /usr/share/common-lisp/source/quicklisp/quicklisp.lisp

3. Follow the install instructions:

(quicklisp-quickstart:install)

(ql:add-to-init-file)

.

4. To enable the library, in the Common Lisp REPL, run the code:

(ql:quickload :cmu-infix)

5. And then run:

(named-readtables:in-readtable cmu-infix:syntax)

.

6. To test the library, run:

(defmacro add (x y)
  `(let ((a ,x)
         (b ,y))
     #I(a+b)))

(add 2 3)

(macroexpand-1 '(add 2 3))

(macroexpand-1 '#I(1+2-3*5^^6))

(eval (macroexpand-1 '#I(1+2-3*5^^6)))

— Me@2022-12-25 10:13:04 AM

.

.

2022.12.25 Sunday (c) All rights reserved by ACHK

Pier, 2.2

Euler problem 9.1

.

There exists exactly one Pythagorean triplet for which a + b + c = 1000. Find the product abc.

(defun e9c ()
  (loop :for a :from 1 :to 1000 :do
    (loop :for b :from 1 :to a :do
      (let ((c (- 1000 (+ a b))))
        (if (= (+ (* a a) (* b b)) (* c c))
            (return-from e9c
                (list a b c (* a b c))))))))

— colorized by palette fm

— Me@2022-12-05 05:59:49 PM

.

.

2022.12.05 Monday (c) All rights reserved by ACHK

ParEdit

.

(autoload 'enable-paredit-mode
  "paredit" "Turn on pseudo-structural editing." t)

(add-hook 'emacs-lisp-mode-hook
      #'enable-paredit-mode)

(add-hook 'eval-expression-minibuffer-setup-hook   
      #'enable-paredit-mode)

(add-hook 'ielm-mode-hook
      #'enable-paredit-mode)

(add-hook 'lisp-mode-hook
      #'enable-paredit-mode)

(add-hook 'lisp-interaction-mode-hook
      #'enable-paredit-mode)

(add-hook 'scheme-mode-hook
      #'enable-paredit-mode)


(add-hook 'slime-repl-mode-hook
      (lambda () (paredit-mode +1)))

(defun override-slime-repl-bindings-with-paredit ()
   (define-key slime-repl-mode-map
     (read-kbd-macro paredit-backward-delete-key) nil))

(add-hook 'slime-repl-mode-hook
      'override-slime-repl-bindings-with-paredit)

.

— Me@2022-11-29 10:03:49 PM

.

.

2022.11.29 Tuesday (c) All rights reserved by ACHK

Pier, 1.2

Euler problem 8.1

.

.

73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450

Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?

(defun file-get-contents (filename)
  (with-open-file (stream filename)
    (let ((contents (make-string
                     (file-length stream))))
      (read-sequence contents stream)
      contents)))

(defun file-get-lines (filename)
  (with-open-file (stream filename)
    (loop :for line = (read-line stream nil)
          :while line
          :collect line)))

(file-get-lines #P"n.txt")

(defun string-to-list (the-string)
  (loop :for char :across the-string
        :collect char))

(defun char-to-integer-list (char-list)
  (mapcar #'digit-char-p char-list))

(let ((the-digits (char-to-integer-list
           (string-to-list
            (remove #\newline
                    (file-get-contents #P"n.txt"))))))

  (loop :for i :from 0 :to (- (length the-digits) 13)
        :maximize (apply #'*
                    (subseq
                      the-digits i (+ i 13)))))

.

— colorized by palette fm

— Me@2022-11-12 04:50:19 PM

.

.

2022.11.12 Saturday (c) All rights reserved by ACHK

Euler problem 6.1

— by this meme’s creator

.

(defun range (max &key (min 0) (step 1))
  (loop :for n :from min :below max :by step
    collect n))

(defun sum-1-n (n)
  (/ (* n (+ n 1)) 2))

(defun sum (lst)
  (reduce #'+ lst))

(defun square (x)
  (* x x))

(- (square (sum-1-n 100))
   (sum (mapcar #'square (range 101 :min 1))))

; 25164150

.

— Me@2022-10-29 06:39:07 AM

.

.

2022.10.29 Saturday (c) All rights reserved by ACHK

Euler problem 5.1

1930s, 3

.

— meme creator

.

(defun range (max &key (min 0) (step 1))
  (loop :for n :from min :below max :by step
    collect n))

(defmacro lcm-lst (lst)
  `(apply #'lcm ,lst))

(lcm-lst (range 21 :min 2))

.

— palette fm

— Me@2022-10-17 05:21:23 PM

.

.

2022.10.17 Monday (c) All rights reserved by ACHK

Euler problem 4.1

(describe #'elt)

(defun palindromep (seq)
  (let ((end (1- (length seq))))
    (or (< end 1)
        (and (eql (elt seq 0) (elt seq end))
             (palindromep (subseq seq 1 end))))))

(defun euler-4 ()
  (loop for a from 1 to 999
      maximize
      (loop for b from 1 to 999
            when (palindromep
                    (prin1-to-string (* a b)))
              maximize (* a b) into best
            finally (return (or best 0)))))

— skeeto/euler-cl

.

— Me@2022.10.03 03:03:30 PM

.

.

2022.10.03 Monday (c) All rights reserved by ACHK

Way

There is always a WAY.

.

(defun sum-of-squares(x y &key (a 1) (b 1))
  (+ (* a x x) (* b y y)))

(deftype candidate()
  '(simple-array boolean (*)))

(defmacro get-sieve-function(a b mod-results)
  `(lambda(x y)
     (let* ((n (sum-of-squares x y :a ,a :b ,b))
        (r (mod n 12)))
       (when (and (<= n limit)
          (not (null
            (member r ,mod-results))))
     (setf (aref candidates n)
           (not (aref candidates n)))))))

(defun get-atkin-prime-candidates-map(limit)
  (let* ((lmt (isqrt limit))
         (candidates (make-array
              (1+ limit)
              :initial-element nil))
         (stage1 (get-sieve-function 4 1 '(1 5)))
         (stage2 (get-sieve-function 3 1 '(7)))
         (stage3 (get-sieve-function 3 -1 '(11))))
    (declare (type candidate candidates))
    (declare (optimize (speed 3)))
    (loop for x from 1 to lmt do
      (loop for y from 1 to lmt do
    (progn
      (funcall stage1 x y)
      (funcall stage2 x y)
      (when (> x y)
        (funcall stage3 x y)))))
    candidates))

(defun atkin-sieve-map(candidates)
  (let ((len (length candidates)))
    (loop for i from 1 to (1- len)
      when (aref candidates i)
        do (loop for j from 1
             for n = (* j i i)
             while (< n len)
             do (setf (aref candidates n) nil))))
  (setf (aref candidates 2) T)
  (setf (aref candidates 3) T)
  candidates)

(defun eratosthene-sieve-map(limit)
  (let ((candidates
      (make-array
       (1+ limit) :initial-element T)))
    (declare (type candidate candidates))
    (declare (optimize (speed 3)))
    (progn
      (setf (aref candidates 0) nil)
      (setf (aref candidates 1) nil))
    (loop for i from 2 to limit
      when (aref candidates i)
        do (loop for j from (+ i i) to limit by i
             when (aref candidates j)
               do (setf (aref candidates j) nil)))
    candidates))

;; This is free software released
;; into the public domain.
;;
;; ykm

(defun get-primes(limit
          &key
            (generator :eratosthene))
  (let ((candidates
      (case generator
        (:atkin (atkin-sieve-map
             (get-atkin-prime-candidates-map
              limit)))
        (:eratosthene (eratosthene-sieve-map
               limit))
        (otherwise
         (error "not valid type
(:atkin :eratosthene)")))))
    (declare (type candidate candidates))
    (loop for i from 0 to (1- (length candidates))
      when (aref candidates i)
        collect i)))

(format t "soe: ~d
" (time (length (get-primes 12345678))))

(format t "soa: ~d
" (time (length (get-primes 12345678
                :generator :atkin))))

(defmacro log10 (x)
  `(/ (log ,x) (log 10)))

.

— Me@2022.09.06 03:24:36 PM

.

.

2022.09.06 Tuesday (c) All rights reserved by ACHK

It doesn’t matter

Euler problem 3.1

.

The bad news is: You cannot make people like, love, understand, validate, accept, or be nice to you.

The good news is: It doesn’t matter.

(defmacro sq (x)
  `(* ,x ,x))

(defmacro list-head (lst)
  `(car ,lst))

(defmacro list-tail (lst)
  `(cdr ,lst))

(defmacro last-item (lst)
  `(car (last ,lst)))

(defun good-reverse (lst)
  (labels ((rev (lst acc)
         (if (null lst)
         acc
         (rev
          (cdr lst)
          (cons (car lst) acc)))))
    (rev lst nil)))

(defun prime-sieve-a-list (input-lst)
  (labels ((sieve-iter (go-lst acc-list)
         (if (not go-lst) 
         acc-list        
         (if (> (sq (list-head go-lst))
            (last-item go-lst))

             (append (good-reverse acc-list)
                 go-lst)
             
             (sieve-iter
              (remove-if #'(lambda (x)
                     (=
                      (mod x (list-head go-lst))
                      0))
                 (list-tail go-lst))
              (cons (list-head go-lst)
                acc-list))))))

    (sieve-iter input-lst '())))

(defun range (max &key (min 0) (step 1))
  (loop :for n :from min :below max :by step
    collect n))

(defmacro prime-sieve (n)
  `(prime-sieve-a-list (cons 2 (range (1+ ,n)
                      :min 3
                      :step 2))))

(time (length (prime-sieve 1234567)))

;; 0.764 seconds of real time
;; 95360

(time (length (prime-sieve 12345678)))

;; 20.128 seconds of real time
;; 809227

— Me@2022-08-27 07:59:30 PM

.

.

2022.08.28 Sunday (c) All rights reserved by ACHK

High level machine language

susam 16 days ago

The first article in this issue of BYTE has a very interesting characterization of Lisp that I have not come across before. I mean, famous quotes like “Lisp is a programmable programming language” by John Foderaro and “The greatest single programming language ever designed” by Alan Kay are often mentioned in articles about Lisp. But in this issue of BYTE, the article “An Overview of LISP” by John Allen at page 10 has something very interesting to say. Excerpt from the article:

“The best description of the LISP programming language is that it is a high level machine language. That is, it shares many of the facets of contemporary machine language –the necessity for attention to detail and the freedom to manipulate the machine’s data and programs without restriction– yet LISP is high level in that the language contains the expressive power and convenience of traditional high level languages. The contradiction is resolvable: a LISP machine is just a higher level machine whose data items are organized differently from the binary bit patterns of most machines, and the LISP programming language is the assembly language for this machine.”

Consider the Emacs Lisp (Elisp) interpreter for example. Elisp interpreter is the Lisp machine. It understands Elisp symbolic expressions, the language of this machine. With enough code written in this machine’s language, we get this fine editing and productivity software known as Emacs!

aap_ 16 days ago

This exactly matches my thoughts. It seems that machine language and LISP are the only two languages (that I know anyway) where code and data are fundamentally the same kind of thing.

— Byte Magazine: LISP (1979)

— Hacker News

.

.

2022.08.22 Monday ACHK

開心 vs 關心

Euler problem 2

.

The older I get, the less I care about what people think about me. Therefore the older I get, the happier I am.

.

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

(defun fib (n)
  (cond ((= n 0) 0)
        ((= n 1) 1)
        ((> n 1) (+ (fib (- n 2)) (fib (- n 1))))))

(time (fib 40))

;; Evaluation took:
;;   2.648 seconds of real time
;;   2.640080 seconds of total run time
;;   99.70% CPU
;;   9,002,590,370 processor cycles
;;   0 bytes consed
;; 

;; tail resursion

(defun fib-t (n)
  (labels ((fib-iter (m a b)
            (if (= m 0)
            a
            (fib-iter (- m 1) b (+ a b)))))
        (fib-iter n 0 1)))

(time (fib-t 40))

;; Evaluation took:
;;   0.000 seconds of real time
;;   0.000002 seconds of total run time
;;   100.00% CPU
;;   2,184 processor cycles
;;   0 bytes consed
;;
  
;; infinite list

(defmacro append-last (lst obj)
  `(append ,lst (list ,obj)))

(defun fib-i (n)
  (labels ((fib-iter (m fib-list a b)
            (if (> m (- n 2))
            fib-list
            (fib-iter (1+ m)
                (append-last fib-list (+ a b))
                b
                (+ a b)))))
    (fib-iter 0 '(0 1) 0 1)))

(time (fib-i 40))

;; Evaluation took:
;;   0.000 seconds of real time
;;   0.000008 seconds of total run time 
;;   100.00% CPU
;;   21,960 processor cycles
;;   32,768 bytes consed


(defun filter (fn lst)
  (let ((acc nil))
    (dolist (x lst)
      (let ((val (funcall fn x)))
    (if val (push val acc))))
    (nreverse acc)))

(defmacro filter-list (fn lst)
  `(filter #'(lambda (x)
                (if (funcall ,fn x) x))
            ,lst))

(defmacro filter-2 (fn1 fn2 lst)
  `(filter-list #'(lambda (x)
                    (if (and
                    (funcall ,fn1 x)
                    (funcall ,fn2 x))
                    x))
                ,lst))

(reduce #'+ (filter-2 #'evenp
              #'(lambda (x) (< x 4000000))
              (fib-i 100)))

; 4613732

— Me@2022-08-07 12:34:19 PM

.

.

2022.08.09 Tuesday (c) All rights reserved by ACHK

Mega Man Zero 3

Euler problem 1

.

(proclaim '(optimize speed))

(reduce #'+ '(1 2 3 4))

; 10

(loop :for n :below 10 :collect n)

; (0 1 2 3 4 5 6 7 8 9)

(describe :below)

(defun range (max &key (min 0) (step 1))
   (loop :for n :from min :below max :by step
      collect n))
      
(- (+ (* 3 (reduce #'+ (range 334 :min 1 :step 1)))
      (* 5 (reduce #'+ (range 200 :min 1 :step 1))))
   (* 15 (reduce #'+ (range 67 :min 1 :step 1))))
   
; 233168

(defun sum-1-n (n)
  (/ (* n (+ n 1)) 2))
  
(- (+ (* 3 (sum-1-n 333))
      (* 5 (sum-1-n 199)))
   (* 15 (sum-1-n 66)))
   
; 233168

— Me@2022-08-01 03:29:01 PM

.

.

2022.08.01 Monday (c) All rights reserved by ACHK

Common Lisp Reloaded

; sudo apt-get install sbcl

; sudo apt-get install slime

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(setq inferior-lisp-program "sbcl")

(defun load-slime-with-correct-buffer-position ()

  (save-excursion (slime))
     
 
  (delete-other-windows) 
) 

(defun prelude-start-slime ()
  (unless (slime-connected-p)
    (load-slime-with-correct-buffer-position)))

(add-hook 'slime-mode-hook 'prelude-start-slime)

(set-register ?f '(file . "/path_to/lisp_file.lisp"))

— Me@2022-07-23 05:20:32 PM

.

.

2022.07.23 Saturday (c) All rights reserved by ACHK

Common Lisp vs Racket

flavio81 11 months ago [-]

The author, a famous and well-liked lisper, is not considering portability features. CL is an ANSI standard and code often runs with no changes in many distinct CL implementations/compilers/interpreters.

Also, related to that point: There are many different CL implementations out there that satisfy different use cases, like for example JVM deployment (ABCL), embedded systems (ECL), speed(SBCL), fast compile times (Clozure), pro-level support (LispWorks, ACL), etc. So the same code has a huge amount of options for deployment. It really makes Common Lisp be “write once, run anywhere”.

Then speed is also never mentioned. Lisp can be seriously fast; under SBCL it is generally 0.3x to 1x C speed; LispWorks might be faster, and there’s a PDF out there called “How to make Lisp go faster than C”, so that should give an idea of Lisp speed potential.

CL wasn’t created by philosophing about what a programming language should be for many years; CL was basically created by merging Lisps that were already proven in the industry (Maclisp, Zetalisp, etc), already proven to be good for AI, heavy computation, symbolic computation, launching rockets, writing full operating systems, etc.

CL is a “you want it, you got it” programming language. You want to circumvent the garbage collector? Need to use GOTOs for a particular function? Want to produce better assembly out? Need side effects? Multiple inheritance? Want to write an OS? CL will deliver the goods.

In short, I would guess that from a computer scientist or reseacher point of view, Racket is certainly more attactive, but for the engineer or start-up owner that wants to have killer production systems done in short time, or to create really complex, innovative systems that can be deployed to the real world, Common Lisp ought to be the weapon of choice!

— Why I haven’t jumped ship from Common Lisp to Racket just yet

— Hacker News

.

.

2022.07.13 Wednesday ACHK

Lisp macros 3

Power

Macros are one of the things that make Lisp so extensible, because they let you transform arbitrary code into other arbitrary code. This is true for macros in languages like C too, but Common Lisp macros are different because they’re part of the language.

In C you have a layer of macros on top, written in a preprocessor macro language. The macro layer and the language layer are separate from each other, with the macro layer providing one one extra level of abstractive power (which, don’t get me wrong, is certainly useful).

In Common Lisp, you write macros in Common Lisp itself. You can then use those macros to write functions, and use those functions to write more macros. Instead of two stratified layers it’s a feedback loop of abstractive power.

— A Road to Common Lisp

— Steve Losh

.

.

2022.05.22 Sunday ACHK

The Lisp debugger

oo101 7 days ago [-]

There are a few ways in which the shared objects method you suggest does not match the full power of Lisp debugging.

First of all, when a C program crashes, it just crashes. There is no REPL. There is only a core dump. So any live-debugging you plan to do is after the fact. After you have seen a crash, you would now begin to prepare for the next crash by launching your process via GDB or restarting your process and attaching a GDB to it. Whether a similar crash would occur again or not or when it would occur again depends on the nature of the bug. Now contrast this with Lisp debugging when your program crashes, it stops there and offers you an REPL to interact with the program right then. There is no need to wait for the next crash.

Secondly, when you debug with GDB, you would be dealing with syntaxes: The syntax of C that we are so familiar with. The GDB syntax to investigate the problem that we may be less familiar with. When the Lisp debugger offers the REPL to you, you are working with Lisp again. Your compiler, debugger, program, etc. all are part of the same unified environment where you just execute Lisp code to debug your issue.

Finally, putting your code in shared objects and reloading them requires you to go through the complete write-build-test-debug cycle. And then what do you do if your shared object itself crashes? With Lisp you skip the write-build-test part when all you want to do is debug an error. You jump straight to the debug part of the cycle and begin investigating the runtime state. And it works the same in a uniform manner whether your main program crashes or a dependency crashes.

— A Road to Common Lisp

— Hacker News

.

.

2022.05.05 Thursday ACHK