loops: having my cake and eating it too?
Apr. 27th, 2010 07:43 pmOne programming annoyance when writing loops is wanting to access each element of the list without passing the index, i.e. with code like:
I'm not aware of any solutions to this in current usage.
for (el in list) while simultaneously wanting to know the index without writing i=0 and i++.I'm not aware of any solutions to this in current usage.
(no subject)
Date: 2010-04-28 03:10 am (UTC)local fun mapi_aux i f [] = [] | mapi_aux i f (x::xs) = f (i, x) :: mapi_aux (i+1) f xs in (* mapi : (int * 'a -> 'b) -> 'a list -> 'b list *) fun mapi f list = mapi_aux 0 f list endNow instead of
for (el in list) { ... code(i, el) ... }you just saymapi (fn (i, el) => ... code(i, el) ...) list.The Standard ML Basis has things like
Array.iteriandVector.mapipredefined:(no subject)
Date: 2010-04-28 03:16 am (UTC)(no subject)
Date: 2010-04-28 03:32 am (UTC)http://ruby-doc.org/core/classes/Enumerable.src/M003137.html
hash = Hash.new %w(cat dog wombat).each_with_index {|item, index| hash[item] = index } hash #=> {"cat"=>0, "wombat"=>2, "dog"=>1}(no subject)
Date: 2010-04-28 04:24 am (UTC)(no subject)
Date: 2010-04-28 05:18 am (UTC)Part of one of the reasons I think there isn't a solution in common usage, is that the two access methods explicitly want you to consider the structure of the list:
for (el in list) - implies that the collection is unordered
for(int i=0;i<length(list);i++) - implies that the collection is strongly ordered.
(no subject)
Date: 2010-04-28 12:01 pm (UTC)(no subject)
Date: 2010-04-29 04:17 am (UTC)As opposed to whitespace.
(no subject)
Date: 2010-04-28 04:00 am (UTC)(loop :for el :in list :for i :from 0 :do ...)
(no subject)
Date: 2010-04-28 04:03 am (UTC)(no subject)
Date: 2010-04-28 04:06 am (UTC)If you want to nest, you can have a (loop ...) inside a (loop ...).
(no subject)
Date: 2010-04-28 04:08 am (UTC)See Olin Shivers' LOOP (for Scheme) for the best LOOP story ever.
(no subject)
Date: 2010-04-28 04:13 am (UTC)for i, v in enumerate(list):
print "%2d => %s" % (i, v)
(no subject)
Date: 2010-04-28 04:17 am (UTC)This really looks like the nicest solution!
Gotta love multiple assignment in one line! Sadly I only know of python and Matlab supporting this. Common Lisp does too, sort of, but not as nicely.
(no subject)
Date: 2010-04-28 04:23 am (UTC)(no subject)
Date: 2010-04-28 06:01 pm (UTC)mapi (fn (v,i) => [code]) list?(no subject)
Date: 2010-04-28 06:21 pm (UTC)is "fn" like "lambda" and "=>" like the "." following a lambda?
Your one line of code above doesn't enumerate.
(no subject)
Date: 2010-04-28 07:00 pm (UTC)it does enumerate. it applies the provided function (which takes the index as an argument) to every element of the list, and returns a list of the results. "appi" can be used if you just want to apply some effectful computation to every element, like printing it.
(no subject)
Date: 2010-04-29 04:25 am (UTC)You can abbreviate the writeup even further if you're single-national Canadian.
(no subject)
Date: 2010-04-29 04:39 am (UTC)but yeah i dunno, posting the actual implementation seems pedagogically more necessary in the ML example since a "map" call is totally bizarre-looking to someone used to seeing a loop structure.
(no subject)
Date: 2010-04-29 01:57 pm (UTC)mapi (fn (x, i) => printf I'" => "S $ i x) thelist, and you're worried they won't understand that line of code, why expect they'll get any illumination out of the implementation of mapi?This is a problem I've frequently had with CMU SML people. I'm used to a world that believes in abstraction. This method of giving the detailed implementation first is the very antithesis of abstraction.
(no subject)
Date: 2010-04-29 04:30 pm (UTC)(no subject)
Date: 2010-04-29 05:33 pm (UTC)(no subject)
Date: 2010-04-30 04:57 am (UTC)(no subject)
Date: 2010-04-29 04:41 am (UTC)(no subject)
Date: 2010-04-29 04:55 am (UTC)Here's a very short solution in another language you probably don't know:
Maybe Haskell is inherently more readable, though? :P This one makes creative use of laziness!
(no subject)
Date: 2010-04-29 05:10 am (UTC)(no subject)
Date: 2010-04-29 05:20 am (UTC)(no subject)
Date: 2010-04-29 05:19 am (UTC)mapi (fn (i, el) => ... code(i, el) ...) listis less elegant than
because
* the Python fewer tokens
* in the ML, what the heck is "..." anyway?
* in the ML, one explicitly writes the lambda. One of the reasons Paul Graham invented Arc is because "lambda(x)" appears too often in Lisp.
(no subject)
Date: 2010-04-29 01:32 pm (UTC)(no subject)
Date: 2010-04-29 01:40 pm (UTC)(no subject)
Date: 2010-04-29 01:44 pm (UTC)(no subject)
Date: 2010-04-28 05:22 am (UTC)Oh, a related C (but C99 only) solution for you.
It's not so much as avoiding the assignment,
as making it very explicit what you're doing:
int main(int argc, char** argv) { char* A[4] = {"foo","bar","hello","world"}; int length = 4; int i; char* s; for(i=0, s=A[i]; i<length; i++, s=A[i]) { printf("%d %s\n",i,s); } }(no subject)
Date: 2010-04-29 04:23 am (UTC)int length = sizeof(A) / sizeof(*A);
for(int i = 0; i < length; ++i) {
const char *s = A[i];
...
}
(no subject)
Date: 2010-04-28 06:22 am (UTC)foreach (list as $key => $value)
(do somethig)
(no subject)
Date: 2010-04-28 06:23 am (UTC)(no subject)
Date: 2010-04-28 07:59 am (UTC)(no subject)
Date: 2010-04-28 06:22 pm (UTC)(no subject)
Date: 2010-04-29 04:20 am (UTC)(no subject)
Date: 2010-04-29 01:58 pm (UTC)