Bottom line: you are correct. First, consistency matters and Racket is inconsistent in this regard. Second, placement of 'major' arguments matter (I dislike your use of 'container' here but I figure I know where you come from).
re: consistency. Racket, like most languages, is a historically grown, organic artifact. As such various historical accidents have shaped the language. As the designers of artifacts, we should take the time to fix such inconsistencies on a regular basis, but we haven't -- partly because of legacy code and partly because these inconsistencies don't rank as high on our list as other problems we need to fix. re: major argument. In contrast to OOPLs, FPLs have wrestled with this issue for decades. Eli points out amusing little programming 'tricks' that shaped some interfaces -- and it is sad because it reveals that we lack(ed) a design philosophy. In my personal opinion, we should design interfaces like this: f1 : major-arg minor-arg1 ... -> result1 f2 : major-arg minor-arg2 ... -> result2 ... fn : major-arg minor-argn ... -> resultn where these things are types or contracts for many reasons. A side effect would be that readers would notice how close FP is to OOP and that programming well in either world takes reasonably similar design principles. (Plus, if you decide to switch to our classes, just eliminate major-arg and you have method definitions.) -- Matthias On May 15, 2011, at 3:47 PM, Deren Dohoda wrote: > Please forgive my ignorance on this matter. > > (cons value list) > --- Well, makes intuitive sense to put the container second here. > (map proc list) > --- Reads like English. > (foldl proc init list) > --- Hmm, I guess the association with "map" makes this understandable. > (take list 2) > (drop list 2) > --- OK, what? Why not (take 2 list)? > > I am not a programmer by trade, but this kind of plurality of > interface is slightly disturbing. When I am working on programs, I > inevitably look to put containers first. I'm not sure it is always > very pleasing, but it makes *-like procedures a bit friendly. E.g., > (define (push stack literal) > (cons literal stack)) > (define (push* stack . literals) > (foldl (lambda (lit st) (push st lit)) stack literals)) ;stupid lambda > Additionally, it can help with syntactic sugar if argument placement > has some consistency to it. > > And there is the germ of it. A small issue, really, but composing > container procedures becomes extremely ad hoc because the container > constructors and disassemblers themselves seem a bit ad hoc. The > example itself is a little trivial, I know, but what it means is that > if I later decide to change my stack representation with some other > container---hand-rolled or otherwise---the plumbing is not > particularly extensible unless, from the outset, I roll my own > container procedures and use them instead. (For larger programs, I > have.) > > In short, abstracting containers is not friendly, because built-ins > seem to be a mix of ideas. > > This is not a complaint, though, just a question. (If I complained > about every oddity I'd never have programmed in any language!) Where > might Racket be going in the future with this? Nowhere? Ideas still > percolating? Has anyone roughly solved the issue? I know clojure > attempted to (perhaps successfully) wrestle with this issue, but I > never looked very far into it. Different containers are often > different for a reason, and maybe this is not a problem that has a > "solution." > > Thanks for any insight, everyone, > Deren > _________________________________________________ > For list-related administrative tasks: > http://lists.racket-lang.org/listinfo/users _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users

