defaulting String values

0 views
Skip to first unread message

Bill Burcham

unread,
Nov 20, 2009, 10:17:41 AM11/20/09
to pdxruby
I find myself often writing code like this:

s.blank? ? 'some default' : s

and every time I do that it bugs me. Is there a little helper that
does that so I could write something like:

s.def( 'some default')

I can't really think of a good name for that method so I just called
it 'def' sorry.

Here's kind of what I mean:

class String
def def( val )
self.strip == '' ? val : self
end
end

class NilClass
def def( val )
val
end
end

s = 'hello'
puts "'#{s.def('0')}' should be 'hello'"
s = ''
puts "'#{s.def('1')}' should be '1' since string was empty"
s = nil
puts "'#{s.def('2')}' should be '2' since string was nil"
s = ' '
puts "'#{s.def('3')}' should be '3' since string was blank"

Jerry Hilts

unread,
Nov 20, 2009, 10:36:53 AM11/20/09
to pdx...@googlegroups.com
Interesting, though I personally wouldn't use 'def'. Given that that phrase is already a common keyword, it would force my brain to have to know the context each time I saw it: "Is that 'def' or '.def'?"

Granted, contextually, it would be obvious which one was being used, but it would be even more obvious to use a different method name altogether.
> --
>
> You received this message because you are subscribed to the Google Groups "pdxruby" group.
> To post to this group, send email to pdx...@googlegroups.com.
> To unsubscribe from this group, send email to pdxruby+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/pdxruby?hl=.
>
>

Sam Livingston-Gray

unread,
Nov 20, 2009, 11:40:45 AM11/20/09
to pdx...@googlegroups.com
s.if_blank('default')

Monkeypatch away!

-Sam

Bill Burcham

unread,
Nov 20, 2009, 1:48:30 PM11/20/09
to pdxruby
Yeah that's a decent name (if_blank). Short and kinda suggestive.

OTOH this whole thing bugs me a bit. I'm thinking a little about the
fact that this (generic) function as defined works only at the point
of use. It seems to me that the naming difficulty is indicative of a
semantic problem. I think the casual reader of s.if_blank('default')
might be surprised by its behavior (return a new string equal to the
receiver but if the receiver is blank, return 'default').

What if I could specify the default at String initialization time. Now
aside from the fact that implementing that would be a lot more work
(or at least more thought) I wonder if it would be useful or more
easily understood…

So imagine I could create a String that could never be empty. If you
empty it it gets the default value. If you assign some other value to
it then that new value "sticks" until you try to empty the String
again.

var s = new String('hello').if_blank('default');
// now s is 'hello'
s = '';
// now s is 'default'

That could be even cooler if the (re)initialization was "live":

var s = new String('hello').if_blank( function(){ something.getValue
(); } );
// now s is 'hello'
s = '';
// now s is 'live results: 1234'

Then again since Strings generally have "value semantics" maybe
if_blank() as it stands isn't so bad. Folks expect string methods to
return new Strings. Maybe my alternative could be called if_blank! and
we could have both behaviors make sense.

Bill Burcham

unread,
Nov 20, 2009, 1:50:03 PM11/20/09
to pdxruby
(woops, please excuse the JavaScript in the previous post. I'm doing
Ruby and JS at the same time and…)

David Turnbull

unread,
Nov 20, 2009, 2:21:40 PM11/20/09
to pdx...@googlegroups.com
What if I could specify the default at String initialization time. Now
aside from the fact that implementing that would be a lot more work
(or at least more thought) I wonder if it would be useful or more
easily understood…


You could make a new class, inherit String, and override the default initializer and to_s (and whatever else I'm not thinking of).

StringWithDefaultWhenBlank.new('my_def_value')

-david

Markus

unread,
Nov 20, 2009, 2:27:33 PM11/20/09
to pdx...@googlegroups.com

> class String
> def def( val )
> self.strip == '' ? val : self
> end
> end

*sigh* There goes one ruby hangman off my queue. (Prompted by Luke
saying that "you can't redefine 'def'").

As for the main point, I've been known to write:

class String
def |(other)
strip.empty? ? other : self
end
end

Which can be used like so:

puts Product.name | '(no name supplied)'


-- Markus

Markus

unread,
Nov 20, 2009, 2:38:57 PM11/20/09
to pdx...@googlegroups.com

> So imagine I could create a String that could never be empty. If you
> empty it it gets the default value. If you assign some other value to
> it then that new value "sticks" until you try to empty the String
> again.

Unless you "assign" to it using replace, this isn't going to do what you
appear to expect it to. Variables in ruby aren't objects; when you
change the value of a variable to a new object, the old value-object
never hears about it.

The closest you might come would be with attributes where you overrode
the getters, but that's still quite different from what you're
describing.

-- Markus



Sam Livingston-Gray

unread,
Nov 20, 2009, 3:35:13 PM11/20/09
to pdx...@googlegroups.com
On Nov 20, 2009, at 11:27 AM, Markus wrote:
> As for the main point, I've been known to write:
>
> class String
> def |(other)
> strip.empty? ? other : self
> end
> end
>
> Which can be used like so:
>
> puts Product.name | '(no name supplied)'

Interesting. On the one hand, I like that this reads like the inbuilt
|| operator, and is reasonably lightweight syntax. (So similar, in
fact, that a casual reader might not notice that there was anything
tricksy going on.) On the other hand, it would be very easy to type
this by mistake:

puts Product.name || '(no name supplied)'

...which, precisely *because* it reads so similarly, would be
difficult to detect (especially by another programmer who hadn't
spotted your '|' trick, and who would then think you were a complete
moron).

Oh, and now we're introducing another set of behavior for the |
operator, which also already means:
- non-short-circuiting "or" (on true, false, and nil),
- bitwise "or" (on Bignums),
- set union (on Array).

...which -- while arguably Not That Bad in this instance -- is
starting to mosey slightly Perl-ward. "If you're in scalar^H^H^H
string context, this operator does foo..."

On balance, though, I think I like it. (=
-Sam

Bryan

unread,
Nov 20, 2009, 3:59:56 PM11/20/09
to pdx...@googlegroups.com
You could just call it something like "or_default".  Borrowing from Markus's implementation it would be:

class String
  def or_default(other)

    strip.empty? ? other : self
  end
end

It's kind of like "redirect_back_or_default" in the Rails restful_authentication plugin.

puts Product.name.or_default('no name supplied)'

It's a little more typing but it's pretty clear what's going on. 

-Bryan

Bill Burcham

unread,
Nov 20, 2009, 4:34:57 PM11/20/09
to pdx...@googlegroups.com
Ooh yeah. or_default is a great name idea esp given the precedent.

To Markus' point about assign/replace: yeah. Dang it. This ain't yer C++.

Erik Hollensbe

unread,
Nov 21, 2009, 12:27:37 AM11/21/09
to pdx...@googlegroups.com
On 11/20/2009 1:48 PM, Bill Burcham wrote:
> What if I could specify the default at String initialization time. Now
> aside from the fact that implementing that would be a lot more work
> (or at least more thought) I wonder if it would be useful or more
> easily understood�
>

Perl has similar operators in 5.10 (and some 5.8 patches, which are
notably used in FreeBSD 5.8 perl from ports), called 'defined-or'.

e.g.:

$foo = 0;
unless ($foo) # works
unless (defined $foo) # doesn't

$foo = 1;

$foo ||= 2; # fails
$foo = 0;
$foo ||= 2; # succeeds
$foo = undef;
$foo //= 2; # succeeds
$foo = 0;
$foo //= 2; # fails

It should be noted here that an empty string in perl is a false value
already. Either way, it sounds like you need less of a method call and
more of an operator that works similarly, being able to differentiate
"blank" from what counts as a boolean. Bring it to the ruby redmine and
I imagine someone will get involved in at least a discussion.

-Erik
Reply all
Reply to author
Forward
0 new messages