Hopscotching Arrays with Flip-Flops #
Hehe. You’re going to love this! (Warning: some of you are going to hate this.) Watch me skip every other element in an array with a flip-flop.
>> s = true >> (1..10).reject { true if (s = !s) .. (s) } => [1, 3, 5, 7, 9]
Well, actually, that’s not so neat, since such a thing can simply be done with a single assignment in the block.
>> s = true >> (1..10).reject { s = !s } => [1, 3, 5, 7, 9]
BUT! BUT! Tell me, can you hop to every third element in an array using only booleans and assignment? My flip-flops can jump that much higher.
>> s = true >> a = (1..10).reject { true if (s = !s) .. (s = !s) } => [1, 4, 7, 10]
Now, let’s see you beat this reassembling of our array into threes. My flip-flops bunch triplets together!
>> s = true >> a = (1..10).inject([]) do |ary, v| >> ary << [] unless (s = !s) .. (s = !s); ary.last << v; ary >> end => [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
Well, maybe this one you can beat with a modulo, but mine will be more detestable for sure.
iiome
the last one is hardcore: i hate this :)
John Wilger
I don’t understand how this works. If I try to construct a range as:
Ruby complains:
Sam Goldman
if bool..bool has a special meaning, though I can’t remember what it is exactly. It’s so cryptic I decided not to use it a long time ago.
murphy
I love it! What a mess of obfuscated glory…a cute little game we have in these range conditions.
Now here’s the solution to split in bits of eight entries:
Please, don’t show this to Nubys. The may jump from a bridge…or even turn to Java…
why
John Wilder: the double-dot is a flip-flop operator when used in a conditional. The flip-flop is turned on by the first expression’s truth and turned off by the second expression’s truth. The tricky thing about the flip-flop is that it keeps the on/off state inside, so once it’s turned on by the opening expression, it says on until the closing expression is proven true.
‘Taint harmful. ‘Tis part of Ruby’s histree!!
Mark
You’ve (red) handed all those obfuscated Ruby programmers another intoxicated rabbit they can pull out of their fedoras.
I tips me hat to you!
Mark
You’ve (red) handed all those obfuscated Ruby programmers another intoxicated rabbit they can pull out of their fedoras.
I tips me hat to you!
(Sorry if this a dupe – I posted it before but it didn’t appear in the comments)
phil
‘Taint harmful. ‘Tis part of Ruby’s histree!!
Correct, why, but there are elements within the Ruby community pushing for the elimination of the flip-flop operator in future versions of Ruby. They seek to eliminate it because to them it is some sort of strange Perlish thing. Yes, it is Perlish (Perl invented it from what I can tell), and it might seem a bit strange if you’re not used to it, but the flip-flop is mighty powerful!
Save the flip/flop op!
Yxhuvud
MenTaLguY
Hmm, wow. So, how do flip-flops interact with e.g. threads and continuations?
To wit: in the case of threads, is the state thread-local or global? Can they be reified as objects?
I suspect the answers would be global, and no (I’ll have to play around a bit to verify later).
If true, the flip-flop is quite like the regexp in Perl before they were finally made first-class objects. Phantom figments of the parse tree, stateful, but unincarnate.
We did it for Range—let’s have a FlipFlop class!
MenTaLguY
Aha, Ruby does flip-flops correctly. Better than thread-local, even.
Flip-flop state for each method invocation is separate, but can be captured by blocks (as why’s examples demonstrate).
MenTaLguY
Incidentally, here’s another way to skip by threes:
(note extra dot)
MenTaLguY
A key to understanding Ruby flip-flops is that the “off” test never has an immediate effect on the result.
The difference between .. and … is that .. will try the “off” test within the same iteration if the “on” test succeeds, whereas … will wait for the next iteration to try.
And here’s the promised FlipFlop class:
So, why’s last example could be rewritten:
Of course this is ugly. Still far too much sand between the toes.
Anyone have any ideas for making it nicer syntactically?
Gene
I love it. Gentle reminder: built-in to lump / slice n-tuples:
require ‘enumerator’ list.each_slice(n) ## gives you top-level list of lists
timb
two, three, four…
Mark
There was a lot of discussion about the flip-flop-op on the list quite a while back… I seem to remember Matz saying that he didn’t like it and it would be removed. I wonder what ever became of that?
Comments are closed for this entry.