Advice on programming style...

For the Compleat Fan
Locked
cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Advice on programming style...

Post by cormullion »

If you want to process some data using a series of functions, then one way to do it is like this:

Code: Select all

(set 's "string")
(func1)
(func2)
(func3)
where func1 and func1 just do things to s - s being global...

But you could also do it like this:

Code: Select all

(set 's "string")
(set 's (func1 s)
(set 's (func2 s)
(set 's (func3 s)
where func1 and co return a modified version of s. This is presumably less efficient (since s is being shuffled around and copied...)? It doesn't look so good - repetition, too many set's.

There's also

Code: Select all

(set 's (func3 (func2 (func1 s)))
where func1 are as the previous example. I don't like this because it's backwards.

What I want to write is:

Code: Select all

(*?* func1 func2 func3 s)
or more likely:

Code: Select all

(*?* '(func1 func2 func3) s)
I can't see how to do it... It's probably got a name...?

Jeff
Posts: 604
Joined: Sat Apr 07, 2007 2:23 pm
Location: Ohio
Contact:

Post by Jeff »

Using globals for state is generally bad practice, especially with dynamic functions, because you can never completely accurately predict the value of the global when the function is called.

The lispy solution is (func3 (func2 (func1 s))). Realistically, the best alternative is to hide that in a func4 in order to make the code setting the value of s more expressive.

The lispy alternative is to create a function that serially applies functions to the same value, like:

Code: Select all

(define (s-apply fn-list val)
  (dolist (f fn-list)
    (setq val (f val))
  val)
Jeff
=====
Old programmers don't die. They just parse on...

Artful code

jrh
Posts: 36
Joined: Mon Nov 14, 2005 9:54 pm
Location: Portland, Oregon

Post by jrh »

That dolist looks like Fortran (as do all dolists).

(func3 (func2 (func1 s))) is LISP !!!
-

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Hi Jeff. Yes, that works well.

Code: Select all

(define (s-apply fn-list val)
  (dolist (f fn-list)
    (set 'val (f val)))
   val)

(println (s-apply (list reverse upper-case explode) "hi jeff"))

;-> ("F" "F" "E" "J" " " "I" "H")
I suppose it's kind of opposite to map - mapping lots of functions onto a single argument, rather than one function onto lots of arguments.

Thanks.

jrh
Posts: 36
Joined: Mon Nov 14, 2005 9:54 pm
Location: Portland, Oregon

Post by jrh »

Subroutines instead of functions, whatever floats your boat, but I'll pass.

rickyboy
Posts: 607
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia

Post by rickyboy »

Remember that for expressions like

Code: Select all

(f (g (h x)))
you can always use a function composer, e.g. some are found in http://newlisp-on-noodles.org/wiki/inde ... _functions and write instead

Code: Select all

((compose f g h) x)
I think it's more natural to write the function constituents right-to-left (like the mathematical convention of functional composition), but you could write another composer that took the functions in reverse order. I'd call it rcompose, so as not to confuse it with the conventional composer (sorry cormullion, you may be in the minority):

Code: Select all

((rcompose h g f) x)
Also, I agree with jrh. I'd rather write a composer (in general, these are called combinators) which generates a new function than write a function that just applies its constituents right away. (Also, I think dolist is ugly too, but it is a faster iterator, which I believe was Jeff's chief concern.) Utilizing a combinator leaves the door open for building computations and keeping them in symbol references for continued reuse. For instance, you can't use s-apply (defined above) in a fold operation, so the composer is more flexible:

Code: Select all

(let ((my-operator (compose more-func your-operator)))
  (fold my-operator '(1 2 3 45 49 20 98 892)))
That is, now you can chose not only when but also how to apply the new function.
(λx. x x) (λx. x x)

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Excellent! Thanks.

Once I know what things are called, it's easier to find out about them...

Jeff
Posts: 604
Joined: Sat Apr 07, 2007 2:23 pm
Location: Ohio
Contact:

Post by Jeff »

Ricky,

That sounds an awful lot like continuations. Is that what combinators are?

Jeff
Jeff
=====
Old programmers don't die. They just parse on...

Artful code

Locked