getting char from string as fixnum in 1.8 and 1.9

Discussion in 'Ruby' started by Joel VanderWerf, Jul 20, 2009.

  1. What's the best way to write this program so that it will run correctly
    on both 1.8 and 1.9? This works, but I'm just curious if there's
    anything better, preferably without the RUBY_VERSION test, without
    adding methods to String, and without losing much efficiency compared
    with 1.8's String#[].

    if RUBY_VERSION =~ /\A1\.9/
    def third_char_as_fixnum(s)
    s[2].ord
    end
    else
    def third_char_as_fixnum(s)
    s[2]
    end
    end

    s = "abc"
    p third_char_as_fixnum(s) # ==> 99

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Jul 20, 2009
    #1
    1. Advertising

  2. Hi --

    On Tue, 21 Jul 2009, Joel VanderWerf wrote:

    >
    > What's the best way to write this program so that it will run correctly on
    > both 1.8 and 1.9? This works, but I'm just curious if there's anything
    > better, preferably without the RUBY_VERSION test, without adding methods to
    > String, and without losing much efficiency compared with 1.8's String#[].
    >
    > if RUBY_VERSION =~ /\A1\.9/
    > def third_char_as_fixnum(s)
    > s[2].ord
    > end
    > else
    > def third_char_as_fixnum(s)
    > s[2]
    > end
    > end
    >
    > s = "abc"
    > p third_char_as_fixnum(s) # ==> 99


    I'm sure someone will have something more elegant but I'll get the
    ball rolling with:

    def third_char_as_fixnum(s)
    s[2,1].unpack("C*")[0]
    end

    It may not pass the not losing much efficiency test, though.


    David

    --
    David A. Black / Ruby Power and Light, LLC
    Ruby/Rails consulting & training: http://www.rubypal.com
    Now available: The Well-Grounded Rubyist (http://manning.com/black2)
    Training! Intro to Ruby, with Black & Kastner, September 14-17
    (More info: http://rubyurl.com/vmzN)
    David A. Black, Jul 20, 2009
    #2
    1. Advertising

  3. David A. Black wrote:
    > def third_char_as_fixnum(s)
    > s[2,1].unpack("C*")[0]
    > end


    Hm, worth a try, and also:

    s[2,1].unpack("C").first

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Jul 20, 2009
    #3
  4. Joel VanderWerf wrote:
    > David A. Black wrote:
    >> def third_char_as_fixnum(s)
    >> s[2,1].unpack("C*")[0]
    >> end


    About a factor of three slower, as I measure it:

    require 'benchmark'

    if RUBY_VERSION =~ /\A1\.9/
    def third_char_as_fixnum_1(s)
    s[2].ord
    end
    else
    def third_char_as_fixnum_1(s)
    s[2]
    end
    end

    def third_char_as_fixnum_2(s)
    s[2,1].unpack("C").first
    end

    s = "abc"
    N = 1_000_000

    Benchmark.bmbm(12) do |bm|
    bm.report("1") {N.times {third_char_as_fixnum_1(s)}}
    bm.report("2") {N.times {third_char_as_fixnum_2(s)}}
    end

    __END__

    Rehearsal -----------------------------------------------
    1 1.060000 0.000000 1.060000 ( 1.079800)
    2 1.620000 0.000000 1.620000 ( 1.634525)
    -------------------------------------- total: 2.680000sec

    user system total real
    1 0.580000 0.000000 0.580000 ( 0.598929)
    2 1.640000 0.000000 1.640000 ( 1.664318)

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Jul 20, 2009
    #4
  5. Joel VanderWerf

    Guest

    On Mon, Jul 20, 2009 at 7:40 PM, Glenn Jackman<> wrote:
    > At 2009-07-20 02:20PM, "Joel VanderWerf" wrote:
    >>
    >> =A0What's the best way to write this program so that it will run correct=

    ly
    >> =A0on both 1.8 and 1.9? This works, but I'm just curious if there's
    >> =A0anything better, preferably without the RUBY_VERSION test, without
    >> =A0adding methods to String, and without losing much efficiency compared
    >> =A0with 1.8's String#[].
    >>
    >> =A0if RUBY_VERSION =3D~ /\A1\.9/
    >> =A0 =A0 def third_char_as_fixnum(s)
    >> =A0 =A0 =A0 s[2].ord
    >> =A0 =A0 end
    >> =A0else
    >> =A0 =A0 def third_char_as_fixnum(s)
    >> =A0 =A0 =A0 s[2]
    >> =A0 =A0 end
    >> =A0end
    >>
    >> =A0s =3D "abc"
    >> =A0p third_char_as_fixnum(s) # =3D=3D> 99

    >
    > This works in both 1.9.1 and 1.8.7
    >
    > =A0 =A0 def third_char_as_fixnum(s)
    > =A0 =A0 =A0 s[2].ord
    > =A0 =A0 end
    >
    > Because Integer#ord returns the integer receiver.


    > ruby -v -e 'p "foo"[2].ord'

    ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-linux]
    -e:1: undefined method `ord' for 111:Fixnum (NoMethodError)

    > cat foo.rb

    unless 0.respond_to?:)ord)
    class Integer
    def ord; self; end
    end
    end

    > ruby -v -rfoo -e 'p "foo"[2].ord'

    ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-linux]
    111

    Still meets the constraint: "without adding methods to String"
    :)
    , Jul 20, 2009
    #5
  6. wrote:
    >> ruby -v -e 'p "foo"[2].ord'

    > ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-linux]
    > -e:1: undefined method `ord' for 111:Fixnum (NoMethodError)
    >
    >> cat foo.rb

    > unless 0.respond_to?:)ord)
    > class Integer
    > def ord; self; end
    > end
    > end
    >
    >> ruby -v -rfoo -e 'p "foo"[2].ord'

    > ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-linux]
    > 111
    >
    > Still meets the constraint: "without adding methods to String"
    > :)


    That seems like a pretty good approach, actually, and it happens to be
    what the snmp gem does (lib/ber.rb):

    #
    # Add ord method to Fixnum for forward compatibility with Ruby 1.9
    #
    if "a"[0].kind_of? Fixnum
    unless Fixnum.methods.include? :eek:rd
    class Fixnum
    def ord; self; end
    end
    end
    end


    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Jul 20, 2009
    #6
  7. Joel VanderWerf wrote:
    > wrote:

    ...
    >>> cat foo.rb

    >> unless 0.respond_to?:)ord)
    >> class Integer
    >> def ord; self; end
    >> end
    >> end

    ...
    >> Still meets the constraint: "without adding methods to String"
    >> :)

    >
    > That seems like a pretty good approach, actually, and it happens to be
    > what the snmp gem does (lib/ber.rb):


    The reason I wanted to avoid adding anything to String was that I
    couldn't think of a method name that would be pretty safe from conflict
    without being too verbose or obscure (String#get_nth_char_as_int ?).

    It's hard to imagine Integer#ord ever meaning anything other than this
    (it does in 1.8.7 and 1.9.1, as Glenn pointed out), so it seems safe to
    import it from future, as they say.

    Thanks everyone! (This will help bit-struct run in 1.9.)

    --
    vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
    Joel VanderWerf, Jul 20, 2009
    #7
  8. Hi --

    On Tue, 21 Jul 2009, Joel VanderWerf wrote:

    > wrote:
    >>> ruby -v -e 'p "foo"[2].ord'

    >> ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-linux]
    >> -e:1: undefined method `ord' for 111:Fixnum (NoMethodError)
    >>
    >>> cat foo.rb

    >> unless 0.respond_to?:)ord)
    >> class Integer
    >> def ord; self; end
    >> end
    >> end
    >>
    >>> ruby -v -rfoo -e 'p "foo"[2].ord'

    >> ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-linux]
    >> 111
    >>
    >> Still meets the constraint: "without adding methods to String"
    >> :)

    >
    > That seems like a pretty good approach, actually, and it happens to be what
    > the snmp gem does (lib/ber.rb):
    >
    > #
    > # Add ord method to Fixnum for forward compatibility with Ruby 1.9
    > #
    > if "a"[0].kind_of? Fixnum
    > unless Fixnum.methods.include? :eek:rd
    > class Fixnum
    > def ord; self; end
    > end
    > end
    > end


    There's always a bit of fragility, since someone else might have added
    an ord that does something else... unlikely, of course, but still.

    Also, I didn't suggest adding String#ord because you had said you
    didn't want to add methods to String (though your next post clarifies
    what you meant by that). If you want to be more future-esque you could
    add it to String instead of Fixnum (though that might involve one of
    those unpack-based implementations and therefore not be as fast).


    David

    --
    David A. Black / Ruby Power and Light, LLC
    Ruby/Rails consulting & training: http://www.rubypal.com
    Now available: The Well-Grounded Rubyist (http://manning.com/black2)
    Training! Intro to Ruby, with Black & Kastner, September 14-17
    (More info: http://rubyurl.com/vmzN)
    David A. Black, Jul 20, 2009
    #8
  9. > preferably without the RUBY_VERSION test, without adding methods to
    > String, and without losing much efficiency compared with 1.8's String#[].
    >
    >


    This may not be pretty, but you do not need to add anything.
    It works on 1.8.6, 1.8.7, and 1.9.0 if byte is good enough.

    s[2..2].each_byte{|f| p f}


    Harry

    --
    A Look into Japanese Ruby List in English
    http://www.kakueki.com/ruby/list.html
    Harry Kakueki, Jul 21, 2009
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. wwj
    Replies:
    7
    Views:
    525
  2. lovecreatesbeauty
    Replies:
    1
    Views:
    991
    Ian Collins
    May 9, 2006
  3. Jun Young Kim
    Replies:
    4
    Views:
    75
    Jun Young Kim
    Feb 24, 2009
  4. Heesob Park

    Why Fixnum===Fixnum is false?

    Heesob Park, May 13, 2009, in forum: Ruby
    Replies:
    5
    Views:
    106
    Joel VanderWerf
    May 14, 2009
  5. MaggotChild
    Replies:
    6
    Views:
    124
    MaggotChild
    Dec 2, 2009
Loading...

Share This Page