Sequential Procedures in Lisp

When I try to program in a functional style with immutable objects, sequential operations end up writing inside out, for example:

(thing-operation3
  (thing-operation2
    (thing-operation1 thing extra-arg1)
    extra-arg2)
  extra-arg3)

I am starting to see that this pattern repeats throughout my code, and it is very difficult for me to read it. This could be slightly improved with higher order procedures such as curries and essays:

((compose1
  (curryr thing-operation3 extra-arg3)
  (curryr thing-operation2 extra-arg2)
  (curryr thing-operation1 extra-arg1))
 thing)

Better, perhaps, but it is still written in reverse order, and additional cognitive load is required to find out what is happening. And I'm not sure if this is an ideomatic Lisp code.

Object oriented style is much easier to read:

thing.operation1(extra-arg1).operation2(extra-arg2)
    .operation3(extra-arg3)

It reads in a natural way, and it can also be implemented with immutable objects.

Lisp, ?

+4
4

Common Lisp - LET*

(let* ((thing1 (thing-operation0 thing0 extra-arg0))
       (thing2 (thing-operation1 thing1 extra-arg1))
       (thing3 (thing-operation2 thing2 extra-arg2)))
  (thing-operation3 thing3 extra-arg3))

, , .

, :

(pipe
 (thing-operation1 thing extra-arg1)
 (thing-operation2 _2    extra-arg2)
 (thing-operation3 _3    extra-arg3)
 (thing-operation4 _4    extra-arg4))

, Lisp . :

(defmacro pipe (expression &rest expressions)
  (if (null expressions)
      expression
    (destructuring-bind ((fn arg &rest args) &rest more-expressions)
        expressions
      (declare (ignorable arg))
      `(pipe
        (,fn ,expression ,@args)
        ,@more-expressions))))

pipe :

(THING-OPERATION4
 (THING-OPERATION3
  (THING-OPERATION2
   (THING-OPERATION1 THING EXTRA-ARG1)
   EXTRA-ARG2)
  EXTRA-ARG3)
 EXTRA-ARG4)

:

(defmacro pipe (expression &rest expressions)
  (if (null expressions)
      expression
    (destructuring-bind ((fn arg &rest args) &rest more-expressions)
        expressions
      `(pipe
        (let ((,arg ,expression))
          (,fn ,arg ,@args))
        ,@more-expressions))))

:

(pipe (+ 1000 pi)
      (+ arg1 arg1)         ; use the previous result multiple times
      (+ arg2 (sqrt arg2))) ; use the previous result multiple times
+10

Clojure , ->, , :

(-> thing
    (thing-operation1 extra-arg1)
    (thing-operation2 extra-arg2)
    (thing-operation3 extra-arg3))

Lisp. Greg Hendershott rackjure ~>, Racket, .

-> ( ~> ) . , ->> (~>> ).

+3

PROGN Common Lisp.

Lisp, .

0

(reduce (lambda (a b) (funcall b a)) 
    (list thing 
          (partial-apply op1 arg1) 
          (partial-apply op2 arg2) 
          ... 
          (partial-apply opn argn) ))

( Lisp). Racket,

(foldl (lambda (a b) (a b))
   thing (list 
          (partial-apply op1 arg1) 
          (partial-apply op2 arg2) 
          ... 
          (partial-apply opn argn) ))

((curry fun) arg), (partial-apply fun arg).

0

Source: https://habr.com/ru/post/1599270/


All Articles