Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Programing Language: LISP Syntax Problem of Piping Functions

260 views
Skip to first unread message

Xah Lee

unread,
Sep 16, 2011, 6:09:19 PM9/16/11
to
〈Programing Language: LISP Syntax Problem of Piping Functions〉
http://xahlee.org/comp/lisp_syntax_function_pipe.html

plain text version follows
─────────────────────────────────────────

Programing Language: LISP Syntax Problem of Piping Functions

Xah Lee, 2011-09-16

One of the annoying problem of the lisp nested syntax is the problem
of sequencing functions.

Here's a example i frequently encounter in emacs lisp. I like to
change a string in several ways. Example:

(setq fname (file-name-sans-extension (file-name-nondirectory fname)))
(setq fname (replace-regexp-in-string "-" " " fname))
(setq fname (replace-regexp-in-string "_002d" "-" fname))
fname

Note the repeated reset of a variable. I don't want that. I want to
avoid mutable variables; it's bad in functional programing. So, one
should do like this:

(replace-regexp-in-string "_002d" "-"
(replace-regexp-in-string "-" " "
(file-name-sans-extension
(file-name-nondirectory fname))))

But that has several problems. It's hard to debug. Also, in
conventional lisp code formatting, “emacs-lisp-mode” would format it
like this (expand your window width to prevent line wrapping):

(replace-regexp-in-string "_002d" "-"
(replace-regexp-in-string "-" " "
(file-name-sans-
extension
(file-name-
nondirectory fname))))

Alternative is a one-liner formatting, but it's hard to read and edit:

(replace-regexp-in-string "_002d" "-" (replace-regexp-in-string "-" "
" (file-name-sans-extension (file-name-nondirectory fname))))

If lisp has adopted its early concept of M-expression as syntax
wrapper, then it could be written like this using a postfix syntax
like unix's pipe |. Here, i show it using Mathematica syntax:

file-name-nondirectory[fname] //
file-name-sans-extension //
Function[replace-regexp-in-string["-", " ", #]] //
Function[replace-regexp-in-string["_002d", "-", #]]

The // is similiar to unix's pipe | operator.

or in Mathematica's prefix notation, with @ as the prefix operator:

Function[replace-regexp-in-string["_002d", "-", #]] @
Function[replace-regexp-in-string["-", " ", #]] @
file-name-sans-extension @
file-name-nondirectory[fname]

Note that in functional languages (e.g. Haskell, OCaml), they have
both prefix and postfix operators. Usually the space character is used
as context-sensitive implicit prefix operator. e.g. f x means “f”
applied to “x”, and f a b c means (((f a) b) c). In Ruby, Perl,
usually they have postfix operator desguised as calling object's
methods. In perl, it's ->, in Ruby, it's just a dot ..

For detail, see:

The Concepts and Confusions of Prefix, Infix, Postfix and Fully
Nested Notations
Unix Pipe As Functional Language
Programing Language: A Ruby Illustration of Lisp Problems

Also note, that even Haskell and OCaml support postfix and prefix
syntax, but their syntax is a syntax soup. That is, it's one bunch of
ad hoc designs with no consistancy, systematic grammar, or
mathematical foundation. They are not much better than the syntax soup
of C-like langs. The symbols are used promiscuously (see: Problems of
Symbol Congestion in Computer Languages (ASCII Jam; Unicode;
Fortress)) and the forms are idiosyncratic, e.g. i++, ++i, for(;;){},
while(){}, 0x123, expr1 ? expr2 : expr3, sprint(…%s…,…), …. The only
language i know whose syntax approaches a systematic grammar is
Mathematica. See: The Concepts and Confusions of Prefix, Infix,
Postfix and Fully Nested Notations and Math Notations, Computer
Languages, and the “Form” in Formalism.

Xah

Piotr Chamera

unread,
Sep 17, 2011, 5:39:28 AM9/17/11
to
W dniu 2011-09-17 00:09, Xah Lee pisze:
> Programing Language: LISP Syntax Problem of Piping Functions
>
> Xah Lee, 2011-09-16
>
> One of the annoying problem of the lisp nested syntax is the problem
> of sequencing functions.
>
> Here's a example i frequently encounter in emacs lisp. I like to
> change a string in several ways. Example:
>
> (setq fname (file-name-sans-extension (file-name-nondirectory fname)))
> (setq fname (replace-regexp-in-string "-" " " fname))
> (setq fname (replace-regexp-in-string "_002d" "-" fname))
> fname
> (...)

You can always cook a macro to simplify this.

For example (in Common Lisp):

(defmacro sequential (marker &rest operations)
(labels ((make-step (ops)
(if (null (cdr ops))
(car ops)
(substitute-if
(make-step (cdr ops))
(lambda (x) (eq x marker))
(car ops)))))
(make-step (reverse operations))))

; usage
(sequential :x
(+ 1 2)
(* :x 5)
(/ 23 :x))

(macroexpand-1
'(sequential :x
(file-name-sans-extension (file-name-nondirectory fname))
(replace-regexp-in-string "-" " " :x)
(replace-regexp-in-string "_002d" "-" :x))
)

> (REPLACE-REGEXP-IN-STRING "_002d" "-"
(REPLACE-REGEXP-IN-STRING "-" " "
(FILE-NAME-SANS-EXTENSION (FILE-NAME-NONDIRECTORY FNAME))))


Probably this has many traps I am not aware of,
but seems to work in simple cases.


Pascal J. Bourguignon

unread,
Sep 17, 2011, 11:45:08 AM9/17/11
to
Piotr Chamera <piotr_...@poczta.onet.pl> writes:

> W dniu 2011-09-17 00:09, Xah Lee pisze:
>> Programing Language: LISP Syntax Problem of Piping Functions
> You can always cook a macro to simplify this.
> ; usage
> (sequential :x
> (+ 1 2)
> (* :x 5)
> (/ 23 :x))

If the OP ever gave more attention to what was written in cll than to
his own navel, he would have long know about such macros.

For example,
http://groups.google.com/group/comp.lang.lisp/msg/456d141214e1f575?hl=en
but there are much older posts on the same subject.

--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.

Marco Antoniotti

unread,
Sep 17, 2011, 2:10:57 PM9/17/11
to
The main problem with your post is that Xah does not like Common Lisp.

Cheers
--
MA

Xah Lee

unread,
Sep 18, 2011, 2:14:29 AM9/18/11
to

a decade ago, i didn't know lisp macro, but due to my admiration of
its Mathematica kinship and the grand-daddy of AI, i thought lisp
macros is a wonderful thing, powerful thing, a thing that allows one
to make arbitrary changes to the language's syntax on the fly.

today, i know, that lisp macros is the most motherfucking fuck in the
whole world of science in computer language.

which fuckhead invented lisp macros hack? I don't presume it's the
same guy who invented lisp. Anyone care to recite the history of lisp
macro?

without being knowledgeable of lisp macro history, my educated guess
is that its the forerunner that evolved into pattern matching proper a
la Mathematica.

Xah ∑ http://xahlee.org/

David Kastrup

unread,
Sep 18, 2011, 4:16:52 AM9/18/11
to
Xah Lee <xah...@gmail.com> writes:

> a decade ago, i didn't know lisp macro, but due to my admiration of
> its Mathematica kinship and the grand-daddy of AI, i thought lisp
> macros is a wonderful thing, powerful thing, a thing that allows one
> to make arbitrary changes to the language's syntax on the fly.

Nonsense. You can't change the reader syntax. Whether or not you are
using macros, the expressions you evaluate are read in completely
first. Macros don't change the syntax but rather the evaluation order.

> today, i know, that lisp macros is the most motherfucking fuck in the
> whole world of science in computer language.
>
> which fuckhead invented lisp macros hack? I don't presume it's the
> same guy who invented lisp. Anyone care to recite the history of lisp
> macro?

What problem do you have? It is a rather basic concept easily
implemented. The typical evaluator can be written (omitting the error
cases) as

(defun eval-list (list)
(if (atom list) list
(cons (eval (car list)) (eval-list (cdr list)))))

(defun eval (elem)
(if (atom elem) elem
(let ((head (eval (car elem))))
(if (macrop head) (eval (apply head (cdr elem)))
(apply head (eval-list (cdr elem)))))))

The last two lines are all that it takes to implement macros vs
functions.

That's much more straightforward than backquotes which are often
convenient (but not required) in connection with macros.

> without being knowledgeable of lisp macro history, my educated guess
> is that its the forerunner that evolved into pattern matching proper a
> la Mathematica.

What would make this an "educated guess"? I can see no connection with
pattern matching whatsoever.

--
David Kastrup

Pascal J. Bourguignon

unread,
Sep 18, 2011, 4:19:17 AM9/18/11
to
David Kastrup <d...@gnu.org> writes:

> Xah Lee <xah...@gmail.com> writes:
>> without being knowledgeable of lisp macro history, my educated guess
>> is that its the forerunner that evolved into pattern matching proper a
>> la Mathematica.
>
> What would make this an "educated guess"? I can see no connection with
> pattern matching whatsoever.

A better question would be "What education?"
Specifically, "What education Xah Lee ever received?"

Tim Bradshaw

unread,
Sep 18, 2011, 7:48:50 AM9/18/11
to
On 2011-09-18 07:14:29 +0100, Xah Lee said:

> without being knowledgeable of lisp macro history, my educated guess
> is that its the forerunner that evolved into pattern matching proper a
> la Mathematica.

No: macros have nothing to do with pattern matching. Obviously you
don't understand them at all.

jvt

unread,
Sep 18, 2011, 9:24:32 AM9/18/11
to
You don't even need to bring macros into this. You need several
functions which are short enough to
define here:

(define (comp2 f1 f2)
(lambda (&rest args)
(funcall f1 (apply f2 args)))

(define (compose &rest fs)
(reduce comp2 (reverse fs)))

(define (>partial f1 &rest args)
(lambda (&rest unapplied-args)
(apply f1 (append args unapplied-args))))

(define (partial< f1 &rest args)
(lambda (&rest unapplied-args)
(apply f1 (append unapplied-args args)

(funcall (compose (>partial #+ 2) (>partial #'* 3) (partial< #'/ 10))
10)

I'd argue, despite all this, that if you want to do this kind of point
free, pipe ish programming,
you should just refactor your code, because your packing too much
information into
too much space, and, just like pipe-heavy bash scripts, no one is
going to want to read
them later.

Or program in Factor.

Marco Antoniotti

unread,
Sep 18, 2011, 4:03:02 PM9/18/11
to

But macros are very useful if you want to build pattern matching. Another thing that was not understood. :)

Cheers
--
MA

Xah Lee

unread,
Sep 18, 2011, 6:19:41 PM9/18/11
to
On Sep 17, 11:14 pm, Xah Lee <xah...@gmail.com> wrote:
> which fuckhead invented lisp macros hack? I don't presume it's the
> same guy who invented lisp. Anyone care to recite the history of lisp
> macro?

answer:
https://plus.google.com/u/0/112757647855302148298/posts/ZAE5mMdvxc4

Xah

Xah Lee

unread,
Sep 18, 2011, 6:26:23 PM9/18/11
to
also of interest, if you want to know what i think of the various lang
creators.

https://plus.google.com/u/0/112757647855302148298/posts/dYs3vKyQwti

if you need a g+ invite, click on the link at bottom of:
http://xahlee.org/funny/whats_is_googleplus.html

i have 144 invite left.

Xah

David Kastrup

unread,
Sep 19, 2011, 3:50:06 AM9/19/11
to
Xah Lee <xah...@gmail.com> writes:

> On Sep 18, 3:19�pm, Xah Lee <xah...@gmail.com> wrote:
>> On Sep 17, 11:14�pm, Xah Lee <xah...@gmail.com> wrote:
>>
>> > which fuckhead invented lisp macros hack? I don't presume it's the
>> > same guy who invented lisp. Anyone care to recite the history of lisp
>> > macro?
>>
>> answer: https://plus.google.com/u/0/112757647855302148298/posts/ZAE5mMdvxc4
>>
>> �Xah
>
> also of interest, if you want to know what i think of the various lang
> creators.

I'd rather read Bukowski in the original.

--
David Kastrup

Tim Bradshaw

unread,
Sep 19, 2011, 5:52:58 AM9/19/11
to
On 2011-09-18 21:03:02 +0100, Marco Antoniotti said:

> But macros are very useful if you want to build pattern matching.
> Another thing that was not understood. :)

Yes, and you can also a macro system which uses pattern matching (I
don't really understand Scheme's macro system, but they seem to be at
least partly pattern-based). But the two concepts are orthoganal.

Tim Bradshaw

unread,
Sep 19, 2011, 5:56:24 AM9/19/11
to
On 2011-09-19 10:52:58 +0100, Tim Bradshaw said:

> Yes, and you can also a macro system which uses pattern matching (I
> don't really understand Scheme's macro system, but they seem to be at
> least partly pattern-based). But the two concepts are orthoganal.

PS I'm not disagreeing with the article I'm responding to, it just
looks that way!

Marco Antoniotti

unread,
Sep 19, 2011, 6:15:05 AM9/19/11
to
The way it looks, Bradshaw, is that it's a chicken-n-egg thingy that the some people don't get :) :)

Cheers
--
MA

Antti J Ylikoski

unread,
Sep 19, 2011, 11:33:33 AM9/19/11
to
18.9.2011 11:19, Pascal J. Bourguignon kirjoitti:
> David Kastrup<d...@gnu.org> writes:
>
>> Xah Lee<xah...@gmail.com> writes:
>>> without being knowledgeable of lisp macro history, my educated guess
>>> is that its the forerunner that evolved into pattern matching proper a
>>> la Mathematica.
>>
>> What would make this an "educated guess"? I can see no connection with
>> pattern matching whatsoever.
>
> A better question would be "What education?"
> Specifically, "What education Xah Lee ever received?"
>

Well -- perhaps the poster is referring to the fact that the parameter
list of a macro is sort of pattern matched with the actual argument
SEXP, which behaviour has been duplicated for the programmer in the
DESTRUCTURING-BIND.

Cheers, andy

WJ

unread,
Mar 24, 2012, 8:23:16 PM3/24/12
to
Clojure has the "threading" macros -> and ->>.

user=> (-> -3 (Math/abs) (Math/sqrt) (Math/exp))
5.6522336740340915

namekuseijin

unread,
Mar 25, 2012, 3:04:12 PM3/25/12
to
I've got math function composition (o f g etc) and argument lifting (^ + 1) in my personal Scheme lib. With them, instead of writing, say:

(string-prepend " Call me no more!!!"
(replace "this" "that"
(replace "You" "I do"
(replace "?" ", I do"
"this is right?! You think so?!"))))

I write

((o (^ string-prepend " Call me no more!!!")
(^ replace "this" "that")
(^ replace "You" "I do")
(^ replace "?" ", You"))
"this is right?! You think so?!")

or

(define replaces
(o (^ string-prepend " Call me no more!!!")
(^ replace "this" "that")
(^ replace "You" "I do")
(^ replace "?" ", You")))

(replaces phrase)

all evaluating to: "that is right, I do! I do think so, I do! Call me no more!!!"

Notice the chain of functions are put in the very same order they are normally called.

WJ

unread,
Dec 16, 2012, 5:52:18 PM12/16/12
to
WJ wrote:

>
> Clojure has the "threading" macros -> and ->>.
>
> user=> (-> -3 (Math/abs) (Math/sqrt) (Math/exp))
> 5.6522336740340915

user=> (-> -3 Math/abs Math/sqrt Math/exp)
5.6522336740340915
0 new messages