[plt-scheme] Mini code review request

From: Anthony Cowley (acowley at seas.upenn.edu)
Date: Thu Apr 8 16:32:31 EDT 2010

On Thu, Apr 8, 2010 at 3:24 PM, Greg Hendershott
<greghendershott at gmail.com> wrote:
> If anyone has time to do a mini code review, I'd appreciate the feedback.

I think it's helpful to start by thinking about per-element
operations, then figure out a specialized fold you want to perform on
the resultant data structure. For instance, I think I prefer this for
the function body:

(string-join (map (λ(p) (let ((k (form-urlencoded-encode (car p)))
                                (v (form-urlencoded-encode (cadr p))))
                            (string-append k "=" v)))
                    lst)
               "&"))

It involves a function that maps an input element to the corresponding
component of the output, then a fold over the result of that
transformation to produce the output.

The map function lets us operate within the structure of the input,
then we use a specialized fold (string-join) to change the structure
itself.

Anthony

>
> Welcome any comments, but mainly I'm curious about my experiment to
> stop being Mr. Imperative. Avoid iterating and mutating. Instead
> embrace map and fold. Don't just sip the kool aid, actually swallow
> it.
>
> I ended up with a (rest (reverse (flatten ...))) sequence which seems
> a bit of a pretzel.
>
> I'm looking at this code with the following questions:
> 1. Is this clean and simple ... or too "clever"?
> b. Is this reasonably idiomatic ... or am I still speaking Scheme as a
> second language?
> iii. How would you native speakers write it?
> 100. Should I spit up the kool aid and revert to my old iterative ways? :)
>
> Thanks in advance.
>
> Code:
>
> ---------
>
> #lang scheme
>
> (require net/uri-codec)
> (require test-engine/scheme-tests)
>
> (define/contract (pairs->params-string lst) ((listof (list/c string?
> string?)) . -> . string?)
>  ; Convert e.g.
>  ; '( ("Param1" "Value1")
>  ;    ("Param2" "Value2")
>  ;    ("Param3" "Value3") )
>  ; to
>  ; "Param1=Value1&Param2=Value2&Param3=Value3"
>  ;
>  ; The point of
>  ;   (rest (reverse (flatten (list "key" "=" "val" "&") ... )))
>  ; is to get the ampersands only BETWEEN, not start or end.
>  (if (empty? lst)
>      ""
>      (foldl string-append
>             ""
>             (rest (reverse (flatten (map (lambda (x)
>                                            (list
> (form-urlencoded-encode (first x)) ; key
>                                                  "="
>
> (form-urlencoded-encode (second x)) ; value
>                                                  "&"))
>                                          lst)))))))
>
> (check-expect (pairs->params-string '()) "")
> (check-expect (pairs->params-string '( ("foo" "bar" ) )) "foo=bar" )
> (check-expect (pairs->params-string  '( ("Param1" "Value1") ("Param2"
> "Value2") ("Param3" "Value3") ))
> "Param1=Value1&Param2=Value2&Param3=Value3" )
> (test)
> _________________________________________________
>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>


Posted on the users mailing list.