Bug #276

take_while functions inconsistently

Added by Anonymous almost 4 years ago. Updated about 1 year ago.

[ruby-core:17768]
Status:Rejected Start date:07/15/2008
Priority:High Due date:
Assignee:- % Done:

0%

Category:-
Target version:-
ruby -v:

Description

take_while didn't work at all until 1.8.7 - I assume that is how it supposed to be. Perhaps that explains some of this behavior, too?

cards is an Array of Cards

pp cards:
[#<Card:0x179094 @suit="C", @value=4>,
 #<Card:0x1793b4 @suit="C", @value=3>,
 #<Card:0x177dd4 @suit="C", @value=10>,
 #<Card:0x177500 @suit="D", @value=13>,
 #<Card:0x1771e0 @suit="D", @value=14>,
 #<Card:0x1770c8 @suit="S", @value=14>,
 #<Card:0x177794 @suit="C", @value=12>]

suit = 'C'
cards = cards.take_while { |this_card| this_card.suit == suit }:
[#<Card:0x179094 @suit="C", @value=4>,
 #<Card:0x1793b4 @suit="C", @value=3>,
 #<Card:0x177dd4 @suit="C", @value=10>]

Note that #<Card:0x177794 @suit="C", @value=12> is not contained in the take_while although it is also 'C' for the suit.
For some reason, it also does not group the 4th 'C' together when sorted:

  def sortBySuit( cards = nil )
    if ! cards
      cards = @hand_check_cards
    end

    cards = cards.sort_by { |card| card.suit }    
  end

self.sortBySuit( cards )

So we try to grab another suit:

suit = 'S'
cards = cards.take_while { |this_card| this_card.suit == suit }:
[]

We end up with nothing.

Here is the Card class.

#!/usr/bin/env ruby

class Card

  attr_accessor :value, :suit

  @value
  @suit

  def initialize( value, suit )
    if value.is_a?(String)
      @value = value.to_i
    else
      @value = value
      pp value
      pp 'goda'
      exit
    end
    @suit = suit.to_s
  end

  def name

    case @value
      when 2 
        name = "2"
      when 3    
        name = "3"      
      when 4    
        name = "4"      
      when 5    
        name = "5"      
      when 6    
        name = "6"      
      when 7    
        name = "7"      
      when 8    
        name = "8"      
      when 9    
        name = "9"      
      when 10   
        name = "10"       
      when "T"    
        name = "10"
      when 11 # Jack
        name = "J"       
      when 12 # Queen
        name = "Q"       
      when 13 # King
        name = "K"       
      when 14 # Ace
        name = "A"      
    end
    return name + @suit
  end

  def next
    if @value == 14
      return 2
    else
      return @value + 1
    end
  end

  def prev
    if @value == 2
      return 14
    else
      return @value - 1
    end
  end

end

and here is where the Cards are initialized with their suits:
  def initCards()
    13.times do |this_time|
      index = this_time + 2
      @cards[index.to_s + 'D'] = Card.new( index.to_s, 'D' )
      @cards[index.to_s + 'C'] = Card.new( index.to_s, 'C' )
      @cards[index.to_s + 'S'] = Card.new( index.to_s, 'S' )
      @cards[index.to_s + 'H'] = Card.new( index.to_s, 'H' )
      @card_index.push( index.to_s + 'C' ) 
      @card_index.push( index.to_s + 'H' ) 
      @card_index.push( index.to_s + 'S' ) 
      @card_index.push( index.to_s + 'D' )
    end
  end

Am I doing something wrong? This seems like a bug. 

Asher (ahaig@penguinmilitia.net)

History

Updated by mboeh (Matthew Boeh) almost 4 years ago

Your sortBySuit method appears to be doing nothing, because it's just assigning the sorted result to a local variable which is subsequently discarded. You might want to try 

  cards.replace(cards.sort_by {|card| card.suit })

Enumerable#take_while is behaving properly in your first case: 

"Passes elements to the block until the block returns nil or false, then stops iterating and returns an array of all prior elements."

That is, since your fourth card has suit == "D", #take_while stops at that point and never gets to your last card. 

In any case, the behavior you appear to be expecting is provided by Enumerable#select, not Enumerable#take_while.

Updated by shyouhei (Shyouhei Urabe) almost 4 years ago

  • Status changed from Open to Rejected

Also available in: Atom PDF