Designing API strings vs symbols?

Hello all, I’m currently doing a port of Perl’s Data::FormValidator module
to Ruby because I think it would be an extremely useful library to have around,
and I can’t find anything like it on the RAA. Here’s an example usage:

@fv = FormValidator.new
profile = {
:optional => [“company”, “fax”],
:required => [“fullname”, “phone”, “age”]
}
form = {
“company” => “Some Company”,
“fullname” => “Travis Whitton”,
“phone” => “”
}
@fv.setup(form, profile)
@fv.required # => [“age”, “phone”]

or you’ll be able to use a runner and just say:
@fv = FormValidator.new
@fv.validate(form, profile)

which would run an entire suite of tests on the given input storing the result
in instance variables. Of course, it will have more functionality than this,
but on to my question:

Would most people prefer profile to exclusively use symbols, or should it
use the mix of symbols and strings as defined above? I.e.,

symbol version

profile = {
:optional => [:company, :fax],
}

string version

profile = {
:optional => %w{company fax}
}

I’m currently using strings because they’re analogous to keys given to
Ruby’s CGI objects; however, if symbols would be preferred, I’ll go that route.
Also note, the current version is returning arrays of strings in the list
of missing fields, which could also easily be changed. I want to design this
properly the first time, so I don’t have to go back and break the API. Also,
I’m having some weird behaviour with my unit tests where, I have to insert a
blank line at the end of my test, or it will break Test::Unit::TestCase with
the following error:

Loaded suite testvalid
/usr/lib/ruby/site_ruby/1.6/test/unit/util/procwrapper.rb:25:in initialize': unmatched ): /\300\017\022\010Proc:)/ (RegexpError) from /usr/lib/ruby/site_ruby/1.6/test/unit/util/observable.rb:39:innew’
from /usr/lib/ruby/site_ruby/1.6/test/unit/util/observable.rb:39:in
add_listener' from /usr/lib/ruby/site_ruby/1.6/test/unit/ui/console/testrunner.rb:62:inattach_to_mediator’
from /usr/lib/ruby/site_ruby/1.6/test/unit/ui/console/testrunner.rb:44:in
start' from /usr/lib/ruby/site_ruby/1.6/test/unit/ui/console/testrunner.rb:21:inrun’
from /usr/lib/ruby/site_ruby/1.6/test/unit.rb:192
from /usr/lib/ruby/site_ruby/1.6/test/unit.rb:164
from testvalid.rb:9

Anybody else had this problem?

Thanks,
Travis Whitton whitton@atlantic.net

i know exactly what you are talking about : symbols look nice, but strings are
more inline with cgi programming internals

why not support both?

def method s
s = s.intern if String === s # use symbols internally
end

or

def method s
s = s.to_s.gsub /^:/, ‘’ if Symbol === s # use strings internally
end

-a

···

On Mon, 3 Feb 2003, Travis Whitton wrote:

Hello all, I’m currently doing a port of Perl’s Data::FormValidator module
to Ruby because I think it would be an extremely useful library to have around,
and I can’t find anything like it on the RAA. Here’s an example usage:

@fv = FormValidator.new
profile = {
:optional => [“company”, “fax”],
:required => [“fullname”, “phone”, “age”]
}
form = {
“company” => “Some Company”,
“fullname” => “Travis Whitton”,
“phone” => “”
}
@fv.setup(form, profile)
@fv.required # => [“age”, “phone”]

or you’ll be able to use a runner and just say:
@fv = FormValidator.new
@fv.validate(form, profile)

which would run an entire suite of tests on the given input storing the result
in instance variables. Of course, it will have more functionality than this,
but on to my question:

Would most people prefer profile to exclusively use symbols, or should it
use the mix of symbols and strings as defined above? I.e.,

symbol version

profile = {
:optional => [:company, :fax],
}

string version

profile = {
:optional => %w{company fax}
}

I’m currently using strings because they’re analogous to keys given to
Ruby’s CGI objects; however, if symbols would be preferred, I’ll go that route.
Also note, the current version is returning arrays of strings in the list
of missing fields, which could also easily be changed. I want to design this
properly the first time, so I don’t have to go back and break the API. Also,
I’m having some weird behaviour with my unit tests where, I have to insert a
blank line at the end of my test, or it will break Test::Unit::TestCase with
the following error:

Loaded suite testvalid
/usr/lib/ruby/site_ruby/1.6/test/unit/util/procwrapper.rb:25:in initialize': unmatched ): /\300\017\022\010Proc:)/ (RegexpError) from /usr/lib/ruby/site_ruby/1.6/test/unit/util/observable.rb:39:in new’
from /usr/lib/ruby/site_ruby/1.6/test/unit/util/observable.rb:39:in
add_listener' from /usr/lib/ruby/site_ruby/1.6/test/unit/ui/console/testrunner.rb:62:in attach_to_mediator’
from /usr/lib/ruby/site_ruby/1.6/test/unit/ui/console/testrunner.rb:44:in
start' from /usr/lib/ruby/site_ruby/1.6/test/unit/ui/console/testrunner.rb:21:in run’
from /usr/lib/ruby/site_ruby/1.6/test/unit.rb:192
from /usr/lib/ruby/site_ruby/1.6/test/unit.rb:164
from testvalid.rb:9

Anybody else had this problem?

Thanks,
Travis Whitton whitton@atlantic.net

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

i have considered this myself and i think the best answer is to support what
the application demands. in other words. if spaces and such are illegal for
your apps use, then use Symbol, if not then use String. if you mix then you
have potential for errors.

CGI uses String because form element names can contain odd characters like
spaces.

of course if you internally support string, symbols are a subset of strings.
so you could do #to_s on everything that comes in and effectively take them
into account, but do not go the other way if there is any potential
uncertainty.

···

On Monday 03 February 2003 03:35 pm, Travis Whitton wrote:

Would most people prefer profile to exclusively use symbols, or should it
use the mix of symbols and strings as defined above? I.e.,


tom sawyer, aka transami
transami@transami.net

I can’t believe that gsub is necessary, and I’m right.

:frog.to_s == “frog”

Anyway, I prefer symbols to strings as “properties”: they display a
greater deal of intention: that the hash will work with these values
as keys and none, or little, other.

I expect it’s more efficient, too.

Gavin

···

On Tuesday, February 4, 2003, 9:35:39 AM, ahoward wrote:

On Mon, 3 Feb 2003, Travis Whitton wrote:

i know exactly what you are talking about : symbols look nice, but strings are
more inline with cgi programming internals

why not support both?

def method s
s = s.intern if String === s # use symbols internally
end

or

def method s
s = s.to_s.gsub /^:/, ‘’ if Symbol === s # use strings internally
end

Would most people prefer profile to exclusively use symbols, or should it
use the mix of symbols and strings as defined above? I.e.,

i have considered this myself and i think the best answer is to support what
the application demands. in other words. if spaces and such are illegal for
your apps use, then use Symbol, if not then use String. if you mix then you
have potential for errors.

‘foo bar baz’.intern # => :foo bar baz

of course if you internally support string, symbols are a subset of strings.
so you could do #to_s on everything that comes in and effectively take them
into account, but do not go the other way if there is any potential
uncertainty.

From a black-box perspective, a Symbol cannot contain \0, but everything
else seems cool.

irb(main):001:0> File.open(‘/kernel’) { |fp| puts fp.read.intern.class }
ArgumentError: string contains \0' from (irb):1:in intern’
from (irb):1
from (irb):1:in `open’
from (irb):1
irb(main):002:0> File.open(‘/kernel’) { |fp| puts fp.read.gsub(“\0”, ‘’).intern.class }
Symbol
=> nil

···

Tom Sawyer (transami@transami.net) wrote:

On Monday 03 February 2003 03:35 pm, Travis Whitton wrote:


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

what foolishness is this!

begots! this boggles my mind. is this good and right? what can i call thus?

class Foo
attr_accessor ‘test me’.intern
def initialize
self.send(‘test me=’.intern, 2)
end
end
t = Foo.new
puts t.send(‘test me’.intern)

that this works, i find irksome. IRK…

···

On Monday 03 February 2003 03:56 pm, Eric Hodel wrote:

‘foo bar baz’.intern # => :foo bar baz


tom sawyer, aka transami
transami@transami.net

Hi –

‘foo bar baz’.intern # => :foo bar baz

what foolishness is this!

A Symbol.

begots! this boggles my mind. is this good and right? what can i call thus?

class Foo
attr_accessor ‘test me’.intern
def initialize
self.send(‘test me=’.intern, 2)
end
end
t = Foo.new
puts t.send(‘test me’.intern)

that this works, i find irksome. IRK…

Easy solution: don’t do it :slight_smile: End of irkage.

send lets you get around some of the constraints of the parser, but by
the same token (so to speak :slight_smile: it can lead to some rather arcane
constructs.

David

···

On Tue, 4 Feb 2003, Tom Sawyer wrote:

On Monday 03 February 2003 03:56 pm, Eric Hodel wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav