And I completely concur (great word choice)--I'm working in a text editor right now (TextMate, not Emacs), and it's perfectly suitable. Forcing use of an IDE, or biasing towards it, would turn me away from the language.
While Unix did win, that doesn't mean that Unix's names won. It's Unix's features that won. So it's reasonable to provide certain operations, but implementing them in terms of (system "unix-command-name ...") is not.
Of course, I use Mac OS X, so it's not like I'm adversely impacted. But the point still stands.
You can even be cleaner: $car is $.car (though this doesn't work for $.$.car). But I don't think this is really a specific case of partial application (though I see where you're coming from). While partial application would be ((map car) '((1 2) (3 4) (5 6))) and this would be ($car '((1 2) (3 4) (5 6))), the biggest win (for me) is not the partial application aspect, but the conciseness of having just one character, as opposed to (currently) ([map car _] '((1 2) (3 4) (5 6))) or ([apply map car __] '((1 2) (3 4) (5 6))), or even the partial application version. And even so, this strikes me as more similar to a request for explicit partial application, which is already implementable, than implicit partial application.
Yes, it was the conciseness I was after. The syntax was inspired by K, where you can do this by putting a ' before a function name.
Of course, K often looks like line noise, but then K takes this technique to its logical conclusion and uses special syntax for everything. There's no need to go that far.
Since most languages are SOV and SVO, Lisp already does not read like most human languages. Lisp is either VSO or VOS (depending on how it is written); the verb (function) comes first. However, the English or math-speak phrase here is "map f onto x". It is not "map x through f" or "map x by f;" neither of these is ever used. Set-builder notation writes { x/2 : x \in Z }; this is, in many ways, what map is based on, and it puts the function before the list. I find (map xs -) to be far less readable than (map - xs), not to mention (map xs ys +)vs.(map + xs ys). Furthermore, this way of writing it mimics function application: (car x) becomes (map car xs), and so on.
There is a slight gain in indentation-based readability with your version, but I'm not convinced it's substantial enough to warrant the less-readable, less-regular, less-common inversion to be the standard; at most, a provided variant, but probably something that one should define oneself.
And for what it's worth, if the function is particularly long, I usually write
i see your point about it mimicking function application, and that seems to me the reason if there was any for why that order was chosen
> I find (map xs -) to be far less readable than (map - xs), not to mention (map xs ys +) vs. (map + xs ys)
well, if the function is named, the order isn't as significant. i personally don't see a difference in either of those pairs, but compare (map + xs ys) to a version where + is a lambda, and likewise with (map xs ys +)
i wonder which usage is more common: map with a named function, or map with a lambda. i'm sure it is the lambda usage, but i haven't programmed much in lisp. it would be interesting to analyze some code and see some numbers
(map betas gammas
[foo (bar _)
(frob nitz)
(xyzzy (quux _ _)
alpha)])
(map betas gammas (fn (a b)
(foo (bar a)
(frob nitz)
(xyzzy (quux b a)
alpha))))
also, it could be made to accept any order. though i don't see a reason for that besides serving as a model for other functions w/ respect to the implied underscore notation
Clearly, readability is largely personal preference. As I said, I like the syntax of your version for lengthy anonymous functions. But I don't see it as a huge net win. It might, on the other hand, be nice to have a mapover macro which turned
(mapover as bs ... ys zs (a b ... y z)
(do-stuff a b ... y z))
into
(map (fn (a b ... y z) (do-stuff a b ... y z))
as bs ... ys zs)
which might be clearer in the really-lengthy-function case. Here it is (lightly tested):
(mac mapover (arg1 arg2 arg3 . arg4+)
" The last two arguments to mapover are treated as the parameter list and body
of a function `f', which is then applied to each element of the given
sequences (the other, previous arguments) in turn; a list consisting of the
results of this function is returned. In short, this is equivalent to
(map f arg1 arg2 ... argN), where `f' is the aforementioned constructed
function.
Note that there is *not* an implicit `do' around the body of the function;
if there were, it would be impossible to tell where the lists ended and the
function began.
See also [[map]] [[each]]. "
(withs (args (apply list arg1 arg2 arg3 arg4+)
body (last args)
parms (car:cut args -2 -1) ; 2nd to last
lists (cut args 0 -2))
`(map (fn ,parms ,body) ,@lists)))
Note that it's limited in that there is no implicit do around the body of the function; since it can take any number of lists, there would be no way to tell where they stopped and the function began. Also note that this may well rely on the Anarki, but I'm not 100% sure if it does.
(And I'm sure someone will tell me that CL's loop can do this in 3... 2... 1...)
Overall, I do think that (map f xs) is cleaner in the named-, short-, and moderately-long-function cases, but it's always possible to write an inversion if you think differently. But what do you think of mapover as another approach?
i wouldn't mind that, though it would probably be considered repetitive with map, and the first thing i would do would be (= map mapover) [edit]oops, macros aren't first class... yet
ya'll confuse me wit dem macros @_@. i made my own function called nap (the other option was pam, which rolls off the tongue with an undesirable cooking-spray sort of feel)
Note that mapover is less general than map. It's explicitly designed for the "long anonymous function" case, so you cannot do
(mapover '(1 2 3) '(4 5 6) +)
; instead, you must do
(mapover '(1 2 3) '(4 5 6) (x y)
(+ x y))
. This is why it is a macro: it needs to treat its last two arguments as part of a function body, so it cannot evaluate them. As a macro, it can package them up and put them in a function, which can be passed to map along with the lists.
nap is a clever function, but will oddly allow you to write (map '(1 2 3) < > '(4 5 6)), which is meaningless. Nevertheless, It's not a terrible idea.
Now, I'd rather have map stay as it is, as I've said. One should have fmap for "flipped map" which does this, and it may or may not belong in the core. After all, (map f xs) does read better than (map xs f). But even so, it is doable.
EDIT: The more I look at this, the more wrong it looks. I'm even more inclined against this; even if we have it, it shouldn't be called something so similar to map.
That's not necessarily true; as I pointed out further down (http://arclanguage.org/item?id=4704), you can get the effect you want. On the other hand, you do take a speed hit. I'm inclined towards supporting both, but swapping the args is very easy to write and may not belong in the core.
But when? That may be the single biggest change I want, actually--much of the rest is implementable within Arc, but this is not. Certainly, when that happens this is trivial, but it hasn't yet, and there's no inkling of when.
I really like this idea, but I don't know that $ is the best choice. On the other hand, I can't think of something better... ^car? &car? At any rate, fantastic idea.
Hmmm, I see what you mean. On the other hand, one might also often do something like (keep even mylist), which doesn't have that problem and does, I think, read better. One good option might be to provide both forms (map and fmap (f for flip or function), for instance)--map would be used where the list was longer, and fmap where the function was. You could even maintain the n-arity of map by doing