• re: Lisp and J

    From B. Pym@Nobody447095@here-nor-there.org to comp.lang.lisp,comp.lang.scheme on Mon Jul 14 15:30:54 2025
    From Newsgroup: comp.lang.scheme

    [ Earlier in the thread, this was written:

    Recently a question was posed in TV about the number of "5"
    characters occuring within all integral decimal numerals
    between 0 and 100.

    ]

    Frank Buss wrote:

    Don't know J, but my experience with APL (from the 1970s,
    a few years before I started programming in Lisp)
    is that it is perfectly readable in the long run.

    you are right. You have to learn the meaning of all the single or two
    char commands first, but the language itself is much easier than Perl.

    Looks like J has a powerful set of commands. Perhaps it could be
    translated to Lisp? Of course, this should be done the Lisp-way, which
    means using verbose names:

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

    (defun seq-eql (element list)
    (map 'list #'(lambda (x) (if (eql element x) 1 0)) list))

    (defun make-seq (last)
    (loop for i from 0 below last collect i))

    The translation of this J expression: +/'5'=":i.100 :


    I've noticed in the past that moronic users of J
    don't have sense enough to separate the tokens
    with spaces. Even with spaces the code is ultra
    concise. Why try to make it less comprehensible
    by removing the spaces?


    +/ '5' = ": i. 100

    Or is it:

    + / '5' = ": i. 100



    (sum (list-eql #\5 (princ-to-string (make-seq 100))))

    But it could be done nearly as short as in J:

    (defun +/ (list)
    (reduce #'+ list))

    (defun j= (element list)
    (map 'list #'(lambda (x) (if (eql element x) 1 0)) list))

    (defun i. (last)
    (loop for i from 0 below last collect i))

    (defun \"\: (object)
    (princ-to-string object))

    (sum (list-eql #\5 (princ-to-string (make-seq 100))))

    (+/ (j= #\5 (\"\: (i. 100))))

    But using \"\: is not very readable. What about writing some macros (and perhaps reader-macros) for embedding J into Lisp? I don't have enough
    time now to do it, but looks promising.

    Interesting.

    Testing:

    * (i. 9)

    (0 1 2 3 4 5 6 7 8)

    * (\"\: (i. 9))

    "(0 1 2 3 4 5 6 7 8)"

    * (j= #\5 (\"\: (i. 9)))

    (0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0)

    [ There's a 0 or 1 for each character in the string. ]

    * (+/ (j= #\5 (\"\: (i. 9))))

    1

    * (+/ (j= #\5 (\"\: (i. 100))))

    20



    Gauche Scheme

    (use gauche.sequence) ; So we can map over a string.

    (define i. iota)
    (define q: x->string)
    (define (== obj seq) (map (lambda(x) (if (equal? obj x) 1 0)) seq))
    (define (// func seq) (reduce func #f seq))

    (// + (== #\5 (q: (i. 100))))
    ===>
    20


    (define (J . args)
    (let ((args (reverse args)))
    (let go ((xs (cdr args)) (result (car args)))
    (if (null? xs)
    result
    (let ((func (car xs)))
    (if (equal? 2 (arity func))
    (go (cddr xs) (func (cadr xs) result))
    (go (cdr xs) (func result))))))))

    (J + // #\5 == q: i. 100)
    ===>
    20
    --
    [T]he problem is that lispniks are as cultish as any other
    devout group and basically fall down frothing at the mouth if
    they see [heterodoxy]. --- Kenny Tilton (05 Dec 2004)
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From B. Pym@Nobody447095@here-nor-there.org to comp.lang.lisp,comp.lang.scheme on Tue Jul 15 11:58:44 2025
    From Newsgroup: comp.lang.scheme

    B. Pym wrote:

    [ Earlier in the thread, this was written:

    Recently a question was posed in TV about the number of "5"
    characters occuring within all integral decimal numerals
    between 0 and 100.

    ]

    Frank Buss wrote:

    Don't know J, but my experience with APL (from the 1970s,
    a few years before I started programming in Lisp)
    is that it is perfectly readable in the long run.

    you are right. You have to learn the meaning of all the single or two
    char commands first, but the language itself is much easier than Perl.

    Looks like J has a powerful set of commands. Perhaps it could be
    translated to Lisp? Of course, this should be done the Lisp-way, which means using verbose names:

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

    (defun seq-eql (element list)
    (map 'list #'(lambda (x) (if (eql element x) 1 0)) list))

    (defun make-seq (last)
    (loop for i from 0 below last collect i))

    The translation of this J expression: +/'5'=":i.100 :


    I've noticed in the past that moronic users of J
    don't have sense enough to separate the tokens
    with spaces. Even with spaces the code is ultra
    concise. Why try to make it less comprehensible
    by removing the spaces?


    +/ '5' = ": i. 100

    Or is it:

    + / '5' = ": i. 100



    (sum (list-eql #\5 (princ-to-string (make-seq 100))))

    But it could be done nearly as short as in J:

    (defun +/ (list)
    (reduce #'+ list))

    (defun j= (element list)
    (map 'list #'(lambda (x) (if (eql element x) 1 0)) list))

    (defun i. (last)
    (loop for i from 0 below last collect i))

    (defun \"\: (object)
    (princ-to-string object))

    (sum (list-eql #\5 (princ-to-string (make-seq 100))))

    (+/ (j= #\5 (\"\: (i. 100))))

    But using \"\: is not very readable. What about writing some macros (and perhaps reader-macros) for embedding J into Lisp? I don't have enough
    time now to do it, but looks promising.

    Interesting.

    Testing:

    * (i. 9)

    (0 1 2 3 4 5 6 7 8)

    * (\"\: (i. 9))

    "(0 1 2 3 4 5 6 7 8)"

    * (j= #\5 (\"\: (i. 9)))

    (0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0)

    [ There's a 0 or 1 for each character in the string. ]

    * (+/ (j= #\5 (\"\: (i. 9))))

    1

    * (+/ (j= #\5 (\"\: (i. 100))))

    20



    Gauche Scheme

    (use gauche.sequence) ; So we can map over a string.

    (define i. iota)
    (define q: x->string)
    (define (== obj seq) (map (lambda(x) (if (equal? obj x) 1 0)) seq))
    (define (// func seq) (reduce func #f seq))

    (// + (== #\5 (q: (i. 100))))
    ===>
    20


    (define (J . args)
    (let ((args (reverse args)))
    (let go ((xs (cdr args)) (result (car args)))
    (if (null? xs)
    result
    (let ((func (car xs)))
    (if (equal? 2 (arity func))
    (go (cddr xs) (func (cadr xs) result))
    (go (cdr xs) (func result))))))))

    (J + // #\5 == q: i. 100)
    ===>
    20

    (use gauche.sequence) ; So we can map over a string.

    (define (sequence? x) (or (vector? x) (string? x) (pair? x)))

    (define (==: a b) (if (eqv? a b) 1 0))

    (define (== a b)
    (if (sequence? a)
    (map ==: a b)
    (map (lambda(x) (==: a x)) b)))

    (define (// func seq . args)
    (if (null? args)
    (reduce func #f seq)
    (fold func (car args) seq)))

    ;; Pipelining or chaining borrowed from Clojure.
    (define-syntax ->
    (syntax-rules ()
    [(_ x) x]
    [(_ x (y more ...) z ...)
    (-> (y x more ...) z ...)]
    [(_ x y z ...)
    (-> (y x) z ...)]))
    (define-syntax ->>
    (syntax-rules ()
    [(_ x) x]
    [(_ x (y ...) z ...)
    (->> (y ... x) z ...)]
    [(_ x y z ...)
    (->> (y x) z ...)]))

    100 iota x->string (== #\5) (// +))

    ===>
    20
    --
    [T]he problem is that lispniks are as cultish as any other
    devout group and basically fall down frothing at the mouth if
    they see [heterodoxy]. --- Kenny Tilton (05 Dec 2004)
    --- Synchronet 3.21a-Linux NewsLink 1.2