Hash auto-true ({:a} == {:a => true})

Discussion in 'Ruby' started by Woody Peterson, Sep 8, 2008.

  1. I have a unix-inspired desire to pass arguments to a method where some
    are toggle flags and some are values, aka "bash$ method --flag
    --config=/etc/method". I can think of a few ways to do it that are
    close, but if I had a hash that initiated value-less keys to true, I
    would have it.

    Example:

    method:)flag, :another, :config => "/etc/whatever")

    For some of the functionality I colud use *args and check
    args.include?:)foo), but then I couldn't pass in key-value pairs easily.

    The closest way would be to use *args to pass in things of the form
    method:)flag, [:config, "/etc/whatever"]), then use args.include?:)flag)
    for flags and args.assoc:)config)[1] for value-based options.

    Example:

    method:)flag, [:config, "/etc/whatever"])

    ex. code:

    if args.include?:)flag) do; stuff; end
    if args.assoc:)config) do; @config = args.assoc:)config)[1]; end

    I'd have to make the args.assoc logic prettier with a helper method to
    set up default values, but that's the basics of it. Much easier/prettier
    if I could modify Hash to auto-assign empty keys to true. Note that
    there's a way to set the default value for empty keys from nil to
    another value (and even a proc), but this wouldn't be what I want. I
    want empty keys to be nil, and specified lone keys set to true.

    Thoughts? Anybody else think this would be really handy, or am I missing
    something?
    --
    Posted via http://www.ruby-forum.com/.
     
    Woody Peterson, Sep 8, 2008
    #1
    1. Advertising

  2. Woody Peterson

    James Coglan Guest

    [Note: parts of this message were removed to make it a legal post.]

    2008/9/8 Woody Peterson <>

    > I have a unix-inspired desire to pass arguments to a method where some
    > are toggle flags and some are values, aka "bash$ method --flag
    > --config=/etc/method". I can think of a few ways to do it that are
    > close, but if I had a hash that initiated value-less keys to true, I
    > would have it.




    If you make the restriction that flags always come first you could do
    something like this:


    def my_method(arg1, arg2, *args)
    options = (Hash === args.last) ? args.pop : {}
    puts args.inspect
    puts options.inspect
    end

    my_method('foo', 'bar', :flag, :value => 'something')
    [:flag]
    {:value=>"something"}

    my_method('foo', 'bar', :flag)
    [:flag]
    {}

    my_method('foo', 'bar', :value => 'something')
    []
    {:value=>"something"}


    Then you can check for flags using args.include?:)foo), or you could loop
    over them and set them to true in the hash:

    args.each { |key| options[key] = true }
     
    James Coglan, Sep 8, 2008
    #2
    1. Advertising

  3. Woody Peterson

    James Coglan Guest

    [Note: parts of this message were removed to make it a legal post.]

    >
    > Now I'm wondering what it would take to define a hash explode (sidenote:
    > is that what * on *args is called? explode?). How would one go about
    > defining something like {}args that explodes args into a
    > true-for-value-less hash (even using the code you posted)? I'm not sure
    > exactly how *args works internally, and it's pretty hard to find info
    > about it, actually. Any idea what kind of method it is, and how would
    > you define another one?




    Far as I know, the *args is part of Ruby's syntax, it's not a method that
    you can change. Even if you could change it, I've no idea which class the
    method would be in. The best you can do is use *args to mean "the remaining
    args" and pop the last one off if it's a hash.

    You could add a method in Hash to set one value to many keys:

    class Hash
    def set_many(value, *keys)
    keys.each { |key| self[key] = value }
    end
    end

    Then do the following:

    def my_method(arg1, arg2, *args)
    options = (Hash === args.last) ? args.pop : {}
    options.set_many(true, *args)
    # ...
    end
     
    James Coglan, Sep 8, 2008
    #3
  4. Woody Peterson

    James Coglan Guest

    [Note: parts of this message were removed to make it a legal post.]

    > You could add a method in Hash to set one value to many keys:
    >
    > class Hash
    > def set_many(value, *keys)
    > keys.each { |key| self[key] = value }
    > end
    > end
    >
    > Then do the following:
    >
    > def my_method(arg1, arg2, *args)
    > options = (Hash === args.last) ? args.pop : {}
    > options.set_many(true, *args)
    > # ...
    > end
    >



    Or this, to build the hash from the args array:

    module Enumerable
    def to_option_hash(value = true)
    ary = entries
    options = (Hash === ary.last) ? ary.pop : {}
    ary.each { |key| options[key] = value }
    options
    end
    end

    Then you can do:

    def my_method(arg1, arg2, *options)
    options = options.to_option_hash
    # ...
    end
     
    James Coglan, Sep 8, 2008
    #4
  5. > def my_method(arg1, arg2, *options)
    > options = options.to_option_hash
    > # ...
    > end


    That's pretty cool. I was thinking something similar, but got stuck on
    naming the method :p

    The advantage of this strategy over args.include?:)flag) is that it's
    backwards compatible with my_method:)flag => true, :config =>
    "whatever"). Also, although I'm sure it's negligible, after you hash it
    you have a seek time of O(1), whereas I assume you have a seek time of
    O(n) every time you call include?(). But mostly the backwards
    compatibility.
    --
    Posted via http://www.ruby-forum.com/.
     
    Woody Peterson, Sep 8, 2008
    #5
  6. > backwards compatible with my_method:)flag => true, :config =>
    > "whatever")


    err, following your examlpe, my_method("arg1", "arg2", :flag => true,
    :config => "whatever").
    --
    Posted via http://www.ruby-forum.com/.
     
    Woody Peterson, Sep 8, 2008
    #6
    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. =?Utf-8?B?V2FyYW4=?=

    Auto-Suggested Textbox like google auto suggest

    =?Utf-8?B?V2FyYW4=?=, Apr 20, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    8,531
    inrakeshworld
    Jul 27, 2007
  2. linkswanted
    Replies:
    1
    Views:
    927
  3. bdb112
    Replies:
    45
    Views:
    1,350
    jazbees
    Apr 29, 2009
  4. rp
    Replies:
    1
    Views:
    539
    red floyd
    Nov 10, 2011
  5. Srijayanth Sridhar
    Replies:
    19
    Views:
    627
    David A. Black
    Jul 2, 2008
Loading...

Share This Page