From: Matthew Smillie Date: 2006-07-02T01:38:11+09:00 Subject: Re: Help please On Jul 1, 2006, at 15:39, Dark Ambient wrote: > So, all if / else must have a following end ? I realize it must be > somewhere, but do they always necessarily follow the if / else or > perhaps could they be further down depending on the code logic ? I'm not 100% sure exactly what you mean here. You can have as much code as you like between the 'if' or 'else' and the corresponding 'end'. What you can't do is overlap the start of one statement with the end of another, which seems to be what you're saying here: > pic_names.each do |name| #start of array loop > while (continue) > [...] > end # for array loop > end # for while loop Judging from your code, you're still mixed up about which 'end' matches which statement - you've labelled the end of the while loop and the end of the array loop backwards from what they actually are. You need to remember that the statements are nested one inside the other. Suppose you have something like the following: a.each do |x| # a <-------- # | b.each do |y| # b <----- | # | | c.each do |z| # c <-- | | [...] # | | | end # c --- | | # | | end # b ------ | # | end # a --------- Three starts to the statements, and three ends. The indentation gives you a clue as to which 'end' belongs to which loop. In other words, if you *start* a set of statements a, b, c, then you have to finish them in *reverse* order: c, b, a. if/elsif/else is only very slightly different. The 'elsif' and/or 'else' aren't separate statements, they're part of the main 'if' statement. For example, you can't have 'elsif foo' in your code outside of an 'if' statement. So all together, they only need one 'end'. Modifying the above diagram: a.each do |x| # a <-------- # | b.each do |y| # b <----- | # | | if c # c <-- | | [1] # | | | else # | | | [2] # | | | end # c --- | | # | | end # b ------ | # | end # a --------- The code in [1] gets execute when something == true, otherwise the code in [2] gets executed. You can think of the 'else' as implicitly ending the 'if', I suppose, but you still only need one 'end'. [1] or [2] could contain other if statements, and they'd nest just like anything else would: if a # ------ if b # ---- | [a true, b true] # | | else # | | [a true, b false] # | | end # ---- | else # | if b # ---- | [a false, b true] # | | else # | | [a false, b false] # | | end # ---- | end # ------ So, if you look at your code, you'll see a few things: 1.a) 'continue' is never set to false, so the while-loop never ends, which implies: 1.b) the end of the each-loop is never reached, and so 'name' is never set to the next element of the array. 2) the 'end' of the first if block does 'end' the first if block, certainly, but I don't think that's where you want it to be. Think about what would happen if the file didn't exist - decision wouldn't have a correct value, and the second if statement would do something unpredictable (probably raise an exception in this specific case). matthew smillie.