

When in doubt, turn to _why - judofyr
http://judofyr.net/posts/when-in-doubt.html

======
markessien
Code should not look like that. Such code is too difficult to understand -
even in C I've rarely seen such a mess.

The style of programming that in any way values a lot of weird unreadable
characters is a relic of the past, and it is not in any way related to skill
level or intelligence, as a lot of people seem to think.

Code should always be made as clear as possible first, and should only be made
more obscure when performance is critical, and there is no clear way of
writing the same block.

~~~
jon_dahl
You're entirely right, of course. But I don't think Camping designed to be
used for normal applications. Camping is Camping partly because its unusual
and hacky. It's a little more like an experiment than a business solution.

~~~
bjclark
What?!? The "4k pocket full-of-gags web microframework" isn't the right choice
for this financial transaction app I'm writing? I FEEL USED.

------
jcl
If you need a blog post explaining line-by-line how it works, it probably
won't be very easy to maintain.

 _This was the first time I’ve ever heard of the merge block. It’s not even
properly documented! But it’s a very simple and very powerful feature..._

...doesn't inspire confidence. :)

~~~
bjclark
Totally agreed. Code must always be Enterprise Ready™. How could anyone
possibly post about some different/interesting/witty way to do something?

~~~
palish
That's not what he was saying. He's saying what he said, and nothing more.

------
GHFigs
"Some do not understand Camping and lash out with spears reaching 4 to 6 feet
in length."

Some context might help:
<http://redhanded.hobix.com/bits/campingAMicroframework.html>
<http://github.com/why/camping/tree/master>

------
smanek
I don't know Ruby, but the author's comments suggest that why_'s way is more
brittle, longer, and slower.

How is it better then?

~~~
judofyr
It's not better, it's _awesomer_. I'm so tired of all this scalable, readable,
fully tested code (which of course is good), that I find these small, wicked
snippets so entertaining for the hacker part of my brain; and after all, this
is the true reason I code: for fun.

~~~
jacobscott
this kind of thing is good to write a blog post on, but when else is it
useful? I think it is irresponsible to choose "_awesomer_" over "scalable,
readable, fully tested" for anything that is supposed to be production quality
(don't know the status of the particular project in question).

You may end up with non-scalable, unreadable, and/or untested code in a
production system for a number of reasons. Some I can think of off the top of
my head include performance and schedule pressure. Introducing it for fun
sounds like bad news bears to me.

~~~
bjclark
Most of the time you get non-scalable, unreadable, and/or untested code in a
production system because you're not very good and you don't step back and
look at interesting/different ways to do things. "Awesomer" isn't a good
reason to do things, but it's probably the original source of some of the
things we like about Python and Ruby and Lua and IO and Potion . . .

------
felixmar
When in doubt, use a real parser instead of regexes (but perhaps i am spoiled
by Haskell).

~~~
bk
I'm actually curious what a haskell version of this would look like.

~~~
shrughes
I'd be happy to write you an example if you specified more clearly than the
linked website what the problem is.

~~~
bk
Essentially, you get a hash consisting of key/value pairs, where the keys may
have a format such that

    
    
        "key[subkey][subsubkey]" => "some_value"
    

is parsed into

    
    
        {"key" => {"subkey" => {"subsubkey" => "some_value"}}}
    

for any depth of nesting.

Valid keys would be:

    
    
        "key"
        "key[subkey]"
        "key[subkey][subsubkey]"
        etc.
    

I hope I got the spec right. Pretty tired right now, been coding all day. :)

~~~
shrughes
<http://paste.lisp.org/display/74007>

    
    
        let Right x = paramTree [("a[x]","b"),("a[b]","c"),
        ("a[b][c]","d"),("bc[de]","f")] in putStrLn (drawTree x)
    
        { "a" => { "b" => <conflict>, "x" => "b" }, "bc" => {
        "de" => "f" } }

~~~
eru
Interesting. Could you have implemented drawTree with Language.Haskell.Pretty?
Also I get the following error with ghc:

yc.hs:35:34: No instance for (Monad (Either String)) arising from a use of
`mapM' at yc.hs:35:34-52 Possible fix: add an instance declaration for (Monad
(Either String)) In a 'do' expression: keys <\- mapM parseKey names In the
expression: do keys <\- mapM parseKey names return (toTree (zip keys values))
In the definition of `paramTree': paramTree nameValues = do keys <\- mapM
parseKey names return (toTree (zip keys values)) where (names, values) = unzip
nameValues

(Edit: I'm sorry that the error message's whitespace gets messed up here.)

Also your groupings function is only used in conjunction with
Data.Map.fromList. Did you consider using something like Data.Map.fromListWith
(++) instead? Of course you'd have to wrap your would-be Map values in
singleton lists first.

~~~
shrughes
What version of GHC (or of the libraries) do you have? (Either String) should
be a monad as specified through Control.Monad.Error:

    
    
        instance Error e => Monad (Either e) where
            ...
    

I didn't consider Data.Map.fromListWith; I didn't know about it. (Thanks.)

------
bprater
The problem with this article is that it doesn't immediate demonstrate, in
code, what the problem is.

Here's an example of a nested hash: "XXX". Here's what normally happens in
Rack: "XX". Here's what we want to happen: "XX". Here's a couple solutions.

Ding, now everyone is clearly on the same page, instead of reading the article
twice trying to figure out what's going on.

