Re: [Jforum] Thinking in a Common Lisp implementation of J

33 views
Skip to first unread message

Raul Miller

unread,
Jul 16, 2025, 6:02:07 PM7/16/25
to fo...@jsoftware.com
What kind of model of J do you have in mind here?

For example:

* Are you trying to supportJ's rank conjunction?
* Are you trying to support J forks?
* Are you trying to support the ambivalence of J verbs?
* Are you trying to support J's under conjunction?
* Are you trying to support J's obverse conjunction?

Thanks,

--
Raul

On Wed, Jul 16, 2025 at 8:24 AM rodolfo sigmados mas <rsig...@gmail.com> wrote:
>
> Hello, I have been thinking about developing a version of J using common Lisp, I have several thousand lines of code (many with the help of LLMS (deepseek, grok, Le chat, ...), but they need to be prune of bugs. I am not in a hurry to develop this project because for now is just a hobby project. The main function is with-rank able to apply any operator selecting the rank.
> (with-rank (list left-rank right-rank) operator left-opeartor right-operator). Don't now if I will finish this project but for me is interesting, unfortunately it requires much effort because many LLMs have errors closing parenthesis (mainly let inside a defun), and other errors.
>
> Perhaps someone has tried a similar project?
>
> To unsubscribe from this group and stop receiving emails from it, send an email to forum+un...@jsoftware.com.

rodolfo sigmados mas

unread,
Jul 16, 2025, 7:02:57 PM7/16/25
to forum, Raul Miller

Hello, my initial plan is/was  to support all of J constructions, but since this is a hobby project and I don't have any hard deadline it could be never finished. Also I am finding a little boring the symple fact that LLM are not closing lisp parenthesis correctly, for example let inside defun usually produces lack of closing parenthesis, since I am not using agents and copy paste code, the procedure is not nice.  One litle  thing that could be useful was to use maxima (a cas based on common lisp) for symbolic computation and other libraries.  Anyway, you have to correct the LLM all the time, for example for random numbers   ? x is like CL  (random x) for x a positive integer but you need (random 1.0) to simulate ? 0 

  Anyway, if someone is curious about the kind of code,  here is a simple example of the code produced to parse J numbers using  LLMS deepseek correcting code of a new LLM called KIMI, but I haven't corrected the possible lack of closing parenthesis here 

(defpackage #:j-number
  (:use #:cl)
  (:export #:parse-j-number))
(in-package #:j-number)

;;; Helper Functions
(defun scan-digits (string start end &key (radix 10))
  (let ((pos start)
        (val 0))
    (loop while (< pos end)
          for ch = (char string pos)
          for digit = (digit-char-p (char-downcase ch) radix)
          when digit
            do (setf val (+ (* val radix) digit)
               (incf pos)
          else do (loop-finish)
          finally (return (and (> pos start) (cons val pos)))))

(defun scan-integer (string start end &key (radix 10))
  (when (< start end)
    (let ((sign 1)
          (pos start))
      (case (char string pos)
        (#\¯ (setf sign -1) (incf pos))
        (#\+ (incf pos)))
      (let ((result (scan-digits string pos end :radix radix)))
        (when result
          (cons (* sign (car result)) (cdr result)))))))

(defun scan-float (string start end &key (radix 10))
  (when (< start end)
    (let ((sign 1)
          (pos start))
      (case (char string pos)
        (#\¯ (setf sign -1) (incf pos))
        (#\+ (incf pos)))
      (let ((int-part (scan-digits string pos end :radix radix)))
        (when int-part
          (setf pos (cdr int-part))
          (let ((frac 0)
                (frac-digits 0))
            (when (and (< pos end) (char= (char string pos) #\.))
              (incf pos)
              (let ((frac-part (scan-digits string pos end :radix radix)))
                (when frac-part
                  (setf frac (car frac-part)
                        frac-digits (- (cdr frac-part) pos)
                        pos (cdr frac-part)))))
            (let ((exp 0)
                  (esign 1))
              (when (and (< pos end)
                         (member (char string pos) '(#\e #\E)))
                (incf pos)
                (case (char string pos)
                  (#\¯ (setf esign -1) (incf pos))
                  (#\+ (incf pos)))
                (let ((exp-part (scan-digits string pos end :radix 10)))
                  (when exp-part
                    (setf exp (* esign (car exp-part))
                          pos (cdr exp-part)))))
              (let ((num (+ (car int-part)
                            (/ frac (expt radix frac-digits)))))
                (when (/= exp 0)
                  (setf num (* num (expt (float radix) exp))))
                (cons (* sign num) pos)))))))))

;;; Main Parser
(defun parse-j-number (string)
  (let ((str (string-trim '(#\Space #\Tab #\Newline) string)))
    (or (parse-infinity str)
        (parse-complex str))))

(defun parse-infinity (str)
  (cond ((string= str "_")  most-positive-double-float)
        ((string= str "__") most-negative-double-float)
        (t nil)))

(defun parse-complex (str)
  (let ((len (length str)))
    (labels ((split-on-j (start)
               (loop for pos from start below len
                     when (char= (char str pos) #\j)
                       return pos)))
      (let ((j-pos (split-on-j 0)))
        (if j-pos
            (let* ((base-pos (or (position #\b str :end j-pos :test #'char-equal)))
                   (radix (if base-pos
                              (let ((r (parse-integer str :start 0 :end base-pos)))
                                (unless (<= 2 r 36)
                                  (error "Invalid radix ~D (must be 2-36)" r))
                                r)
                              10))
                   (real-start (if base-pos (1+ base-pos) 0))
                   (imag-start (1+ j-pos)))
              (complex (parse-real str real-start j-pos :radix radix)
                       (parse-real str imag-start len :radix radix)))
            (parse-real str 0 len))))))

(defun parse-real (str start end &key (radix 10))
  (let* ((base-pos (or (position #\b str :start start :end end :test #'char-equal)))
         (radix (if base-pos
                    (let ((r (parse-integer str :start start :end base-pos)))
                      (unless (<= 2 r 36)
                        (error "Invalid radix ~D (must be 2-36)" r))
                      r)
                    radix))
         (num-start (if base-pos (1+ base-pos) start)))
    (let ((float-p (loop for i from num-start below end
                         thereis (member (char str i) '(#\. #\e #\E)))))
      (handler-case
          (if float-p
              (car (scan-float str num-start end :radix radix))
              (car (scan-integer str num-start end :radix radix)))
        (error (e)
          (error "Failed to parse ~S as ~A number in base ~D: ~A"
                 (subseq str start end)
                 (if float-p "floating-point" "integer")
                 radix
                 e))))))

Raul Miller

unread,
Jul 17, 2025, 12:04:41 AM7/17/25
to rodolfo sigmados mas, forum
I guess I was more concerned about the plan than the code for
implementing that plan.

--
Raul
Reply all
Reply to author
Forward
0 new messages