Names for small functions: just say no... Re: Data.List.join

Jon Fairbairn jon.fairbairn at cl.cam.ac.uk
Mon Oct 30 10:59:48 EST 2006


On 2006-10-30 at 14:03+0100 "Josef Svenningsson" wrote:
> On 10/29/06, Jon Fairbairn <jon.fairbairn at cl.cam.ac.uk> wrote:
> > On 2006-10-27 at 17:56+0200 "Josef Svenningsson" wrote:
> > > My argument for intercalate builds on the fact that intersperse seems
> > > to be the wrong abstraction. Recall that I supplied some evidence that
> > > intersperse is only used together with concat:
> > > http://www.google.com/codesearch?q=file%3A%5C.hs+intersperse&btnG=Search+Code
> >
> > Mostly, not only.
> >
> OK, it's mostly.

I probably shouldn't have made that point, it was a
knee-jerk reaction to seeing a false statement.

> If you had quoted a bit more of what I wrote I did
> actually nuance my statement a bit, acknowledge pretty printing code
> as an exception.

There's also this:

hugs98-Feb2001/lib/hugs/GenericPrint.hs  - 12 identical

   313: intersperse :: a -> [a] -> [a]
        intersperse x (y:ys@(_:_)) = y : x : intersperse x ys
        intersperse x ys = ys
        
        for__ :: Monad m => [a] -> (a -> m ()) -> m () -> m ()
        for__ xs f inc = sequence $ intersperse inc $ map f xs

which while it's in some printing code isn't an instance of
the kind of exception that you are making.

> 
> > > For me this suggests that intersperse is the wrong
> > > abstraction. The right one is intercalate.
> >
> > I don't agree with the methodology... Firstly, while extant
> > code tells you how things have been used, it doesn't tell
> > you how they /should/ be used. Second, I suspect that the
> > majority of current Haskell code was written by novices -- I
> > don't mean anyone any disrespect, it's just that it takes
> > quite a long time to become an expert, the number of new
> > novices has been increasing rapidly and the people who have
> > known Haskell long enough to be experts probably nolonger
> > write so much code: they get their students to do it
> > :-). [How many of the cases you found should have been foldr
> > (.) id etc?]
> >
> Of course there is a risk of being influenced by bad
> coding principle when using this methodology. But do you
> think that this is what happened in this particular case?

No, I'm not talking about bad code in this case -- I don't
see anything at all wrong with writing “concat . intersperse
"blah"”, I'm complaining about the methodology in
general. In this case I could even argue that your data
supports my position! How many of those occurrences of
“concat . intersperse x” are in the body of a definition of
intercalate (by whatever name)? Out of 100 results, there's
the join in ByteString, joinList in Pugs-6.0.1 (but then
there are instances of the idiom rather than joinList in
later versions of Pugs), a join_with in FreeArc, and that's
it. So most of those programmers (and my guess would be that
it's not really enough to mean much) were sufficiently happy
with intersperse not to bother abstracting away from it.

There /are/ several definitions of the form “spacify =
concat . instersperse " "”, which also seems reasonable.

> I challenge you to go through all the search results and
> report any bad code that you find so that we can avoid
> being influenced by that.

Given that that's not my complaing, I don't think I need to,
but since I had to go through to see how many were defining
intercalate I did find this comment "this is hideously
broken, actually" in one, which might just suggest bad code
;-)

> Then there is all the good code that *hasn't* been written
> but perhaps should have been and therefore was excluded
> from the search. If you feel that that's what happened
> here I ask you to put forward concrete examples which we
> can learn from.

That just seems like an unfair challenge. How am I supposed
to come up with a programme that one might want to write for
which intersperse is exactly the right abstraction? I've no
idea what programme that might be!

> As for you second objection. To me it seems that because you don't
> like the outcome of the code search you declare the programmers who
> wrote the code to be immature.

Now that's a gross mischaracterisation of my second point!
Let me recast it in a way that insults noone but me: Every
line of code that I have ever written was written by someone
less experienced that I am now. So I don't want to use that
code in deciding how I /should/ write code in future.  This
is essentially the is/ought problem in philosophy. If your
argument had been that all these uses could have been
written more concisely using intercalate, I couldn't have
disputed it, but I would still have made the argument I did
about not giving names to small functions. Instead, you are
trying to argue that they ought to have been written using
intercalate because it's the right abstraction, and whether
or not that conclusion is true, the data neither supports
nor undermines it.

> > I don't know about natural. Looking back at the 25 year old
> > Ponder list_ops library, I find that I defined
> >
> >   join_with filler l1 [] = l1
> >   join_with filler l1 l2 = l1 ++ filler ++ l2
> >
> > and then
> >
> >   flatten_with filler = foldr (join_with filler) []
> >
> > which is another way of writing intercalate.
> >
> Nice!

But I should add that it's a subtly different function, in
case anyone didn't notice.

> > > As for being more primitive, that's not true. Both
> > > functions are interdefinable.
> >
> > Right. So your motive is more complicated than it appeared
> > to me. I missed that first time round, sorry.
> >
> > The problem we have is that
> >
> >    intersperse x == intercalate [x] . map (:[])
> >
> > and
> >
> >    intercalate x = concat . intersperse x
> >
> > [...] I /suspect/
> > (unprovably) that were intercalate the preferred form,
> > people would write intersperse in several different ways, in
> > contrast to the present state of affairs where "concat
> > . intersperse splod" seems already to have become idiomatic.
> >
> I agree that the second looks simpler.
> 
> So you're suspecting that people would define their own intersperse in
> many different ways. I don't see how that fits in our current
> discussion. No one is proposing to remove intersperse.

Oh, I thought what you were proposing was that intersperse
would fall out of use, so there would then be no point in
having it in a library. Having both of them is definitely an
instance of more vocabulary for little gain.

> If people do find a need for intersperse then they should
> go ahead and use it. My argument is that people *don't*
> use intersperse, at least not without concat, and that
> that idiom will hopefully be replaced with intersperse.

But why? You hope for this, yet I thought you agreed with my
general point that adding library names for short idiomatic
constructions was counterproductive. 

> >  What would convince me of your case would be someone saying
> > that intercalate is the <oojit> of the <weeble> category
> > while intersperse enjoys no such property...
> >
> Yes. That would indeed be a nice thing. I know that the
> reasoning I use to argue for intercalate is one which we
> are not used to in the Haskell community. We want our
> stuff to be firmly based in mathematics and not some
> accidental choice of idiom by some unknown body of
> programmers.

Just so. But there are lots of languages where the stuff is
based on accidental choices of idioms by unknown bodies, and
I "[h]ates the lot of [th]em", so I don't want Haskell to go
that way.  I'm really uneasy at the idea that we should be
in favour of rapid changes to libraries; I'd much rather
they were developed after a good deal of argument about the
mathematical properties.

> But I personally find intercalate very useful and common
> enough to warrant a name. And apparently so does many
> others.

[...]

> I'd like to come to some sort of conclusion. Judging from
> the response I got from my suggestion to include
> intercalate in the library it seems there is a clear
> majority in favour. And then there is you and a few others
> who disagree. With the new submission guidelines we should
> strive for a consensus about patches. How do you suggest
> we proceed?

For the case of intercalate, if everyone who is in favour of
its inclusion has read my arguments and remains unswayed,
then it should surely go in. I'd like to think that the
points I'm making would have some effect, but if they don't,
at least I get my choice of name!

  Jón

-- 
Jón Fairbairn                              Jon.Fairbairn at cl.cam.ac.uk




More information about the Libraries mailing list