[plt-scheme] Mini code review request
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