[plt-scheme] Mini code review request

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Thu Apr 8 17:30:19 EDT 2010

Greg, here is a slower version of Anthony's answer:

1. What's uniform about creating the parameter string? Making pairs of  
the shape key=value

2. What's not quite uniform? The & is a separator not a per-element  
thing.

Use map to do the uniform processing. Then you have an appropriate  
list of strings:

  (list "p1=1" "p2=2" "p3=3")

   (define =lst
      (map (lambda (x)
             (format "~a=~a"
                     (form-urlencoded-encode (first x))
                     (form-urlencoded-encode (second x))))
           lst))

Now use a foldl if this list isn't empty:

  (if (empty? lst)
       ""
       (foldl (lambda (f r) (string-append f "&" r))
              (first =lst)
              (rest =lst)))

You notice things are in reverse when you run the tests. Ah, run  
reverse on =lst and you're set.

3. Or, like Anthony, find string-join in the string library. -- Matthias




On Apr 8, 2010, at 4:32 PM, Anthony Cowley wrote:

> 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
>>
> _________________________________________________
>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme



Posted on the users mailing list.