documentation as source

M

Mauricio Fernández

Eivind said:
From a practical use of Florian's code (his sample from Regexp::English):

# Creates a Regexp which matches a literal string. In this
# string any special regular expression meta-characters will
# be escaped automatically.
#
# # This creates a Regexp which will match 3 "foo"s.
# re = Regexp::English.literal("foo" * 3)
# re.match("foofoofoo")[0] # => "foofoofoo"
def literal(text); Node::Literal.new(text); end

Translated to Nathaniel's syntax:

# Creates a Regexp which matches a literal string. In this
# string any special regular expression meta-characters will
# be escaped automatically.
example do
# This creates a Regexp which will match 3 "foo"s.
re = Regexp::English.literal("foo" * 3)
assert_equal("foofoofoo", re.match("foofoofoo")[0])
end
def literal(text); Node::Literal.new(text); end

Note that this will also presently break rdoc, though there is an
intention of later adding rdoc support. To avoid breaking with rdoc
presently, you'd need to move the example BEFORE the comment.
If this were a voting thing I would go for Nathaniel's syntax as
Florian's looks like it is commented out and should not be run.
Besides how would you comment out something in Florian's syntax.

Look carefully at the example:

# # This creates a Regexp which will match 3 "foo"s.
# re = Regexp::English.literal("foo" * 3)
# re.match("foofoofoo")[0] # => "foofoofoo"
 
E

Eivind Eklund

If this were a voting thing I would go for Nathaniel's syntax as
Florian's looks like it is commented out and should not be run. Besides
how would you comment out something in Florian's syntax. I think
Nathaniel's is much more obvious.

I think Nathaniel's is much more obvious *if you're viewing this
primarily as tests*.

I'm not - these are labelled as "examples", and should IMO primarily
be viewed as examples. Examples that happen to be tested, and that
happen to include some of the test coverage for the program, but
*primarily* examples, and a part of documentation.

But it looks like I'll have to resign to either presenting bad
documentation to the users or to having to fix up and maintain the
fixups for thousand of examples for RPA :-(

Eivind.
 
T

trans. (T. Onoma)

On Tuesday 19 October 2004 09:59 am, Eivind Eklund wrote:
| Sure. From a practical use of Florian's code (his sample from
| Regexp::English):
|
| # Creates a Regexp which matches a literal string. In this
| # string any special regular expression meta-characters will
| # be escaped automatically.
| #
| # # This creates a Regexp which will match 3 "foo"s.
| # re = Regexp::English.literal("foo" * 3)
| # re.match("foofoofoo")[0] # => "foofoofoo"
| def literal(text); Node::Literal.new(text); end
|
| Translated to Nathaniel's syntax:
|
| # Creates a Regexp which matches a literal string. In this
| # string any special regular expression meta-characters will
| # be escaped automatically.
| example do
| # This creates a Regexp which will match 3 "foo"s.
| re = Regexp::English.literal("foo" * 3)
| assert_equal("foofoofoo", re.match("foofoofoo")[0])
| end
| def literal(text); Node::Literal.new(text); end

This points out the distinction nicely --and the slight dislike I have with
both approaches --Florian's is comment and Nathaniel's is not an example but
a test. I would like things to be what they are.

# Creates a Regexp which matches a literal string. In this
# string any special regular expression meta-characters will
# be escaped automatically.
example do
# This creates a Regexp which will match 3 "foo"s.
re = Regexp::English.literal("foo" * 3)
re.match("foofoofoo")[0] # => "foofoofoo"
end
def literal(text); Node::Literal.new(text); end

But I also ask, how can one move the example to some place else in the code?
Wouldn't it be good to label them? Then something like this is possible:

# Creates a Regexp which matches a literal string. In this
# string any special regular expression meta-characters will
# be escaped automatically.
def literal(text); Node::Literal.new(text); end

example :literal do
# This creates a Regexp which will match 3 "foo"s.
re = Regexp::English.literal("foo" * 3)
re.match("foofoofoo")[0] # => "foofoofoo"
end

test :literal do
re = Regexp::English.literal("foo" * 3)
assert_equal("foofoofoo", examples[:literal].call)
end

T.
 
T

trans. (T. Onoma)

On Tuesday 19 October 2004 10:51 am, Eivind Eklund wrote:
| I'm not - these are labelled as "examples", and should IMO primarily
| be viewed as examples.  Examples that happen to be tested, and that
| happen to include some of the test coverage for the program, but
| *primarily* examples, and a part of documentation.

That's a good point.

T.
 
F

Florian Gross

Randy said:
Florian said:
I've coded up test-extract which lets you embed some of your
test-cases cloaked as sample code into your RDoc strings.

It looks like this in practice:
# Creates a Regexp which matches a literal string. In this
# string any special regular expression meta-characters will
# be escaped automatically.
#
# # This creates a Regexp which will match 3 "foo"s.
# re = Regexp::English.literal("foo" * 3)
# re.match("foofoofoo")[0] # => "foofoofoo"
def literal(text); Node::Literal.new(text); end



(Sample from Regexp::English)


I very much like the idea of being able to test examples embedded in the
source file's documentation. A couple of suggestions:

1. Is there some way to allow set-up code that is not part of the
viewable documentation? This would make for clearer examples. Eg. the
above might be changed to something like:

#--
# Init:
# foo = Foo.new(blah, blah);
#++
#
# An example of using Foo.bar()
#
# foo.bar(blek)

def bar(); ...

Well, that's not real pretty, but... the idea is that the example is
more focused for documentation purposes, and all the setup-code is
hidden away.

This sounds like a quite good idea -- currently the setup needs to be
done in the example -- this is okay for most cases, but you don't want
to set up a new instance in every piece of sample code for Classes that
need other resources to be instantiated.

If support for this were to be added to RDoc it would be nice if there
were some kind of marker like "[Setup code hidden]" that could be
clicked to blend in the rest of the code. I think I've seen something
similar used in an online Ruby book already.

Can you think of a way to do this that would not need changes of the
RDoc Ruby code parser? I'll be willing to add support to test-extract,
but I think it is useless when the syntax doesn't work with RDoc. (If we
can't find a way to hide the setup code from RDoc we could maybe make
the syntax self-explanatory so that it can be understood even without
knowing about it.)
2. In addition to showing how something works, it is sometimes
instructive to show what doesn't work. Being able to create examples
that are expected to fail would be useful.

This is possible already: (Sorry for the long sample.)

# Causes a pattern which would otherwise match
# greedily to match non-greedily.
#
# This can only be applied to #count and #optional
# based constructs.
#
# re_greedy = Regexp::English.new do
# literal("<") + something + literal(">")
# end
# re_non_greedy = Regexp::English.new do
# literal("<") + something.minimal + literal(">")
# end
# str = "<html><body>"
# re_greedy.match(str)[0] # => "<html><body>"
# re_non_greedy.match(str)[0] # => "<html>"
#
# This method will do nothing when applied to a Node
# which is already minimal:
#
# re_minimal = Regexp::English.something.minimal
# re_minimal.minimal == re_minimal # => true
#
# However, it will raise a NameError Exception when
# you try to call it on a Regexp Node that can't be
# made non-greedy:
#
# re = Regexp::English.literal("foo")
# re.minimal # raises NameError
def minimal
if self.is_a?(Repeat)
if self.minimal_flag
return self
else
result = self.clone
result.minimal_flag = true
return result
end
else
raise(NameError, "Can't apply minimal")
end
end

You can use the following notations:

# obj.method # raises Exception
# obj.method # raise Exception
# obj.method # ~> Exception

I think the first one is the most clear one.

Another notation that I might add in the future is this one:

# puts "foo" # outputs "foo"

or maybe:

# puts "foo" # outputs foo

I'm not sure about it yet and it will need a bit more work than the
other specification methods, but I think it can be quite useful.

Thanks a lot for giving me feedback on this. It would be great if sample
code as test cases would be commonly adapted.

Regards,
Florian Gross
 
G

gabriele renzi

Mauricio Fernández ha scritto:
Look carefully at the example:

# # This creates a Regexp which will match 3 "foo"s.
# re = Regexp::English.literal("foo" * 3)
# re.match("foofoofoo")[0] # => "foofoofoo"


sidenote: I'd prefer to see this done like:
# This creates a Regexp which will match 3 "foo"s.
# irbprompt>somecode
# =>someresult
# irbprompt>somemore
# =>someother
 
F

Florian Gross

gabriele said:
Mauricio Fernández ha scritto:
Look carefully at the example:

# # This creates a Regexp which will match 3 "foo"s.
# re = Regexp::English.literal("foo" * 3)
# re.match("foofoofoo")[0] # => "foofoofoo"
sidenote: I'd prefer to see this done like:
# This creates a Regexp which will match 3 "foo"s.
# irbprompt>somecode
# =>someresult
# irbprompt>somemore
# =>someother

I think the latter is harder to read, because there is more clutter,
though in theory that style could also be supported by test-extract.

Maybe I can add it later if there is enough demand for it.

Regards,
Florian Gross
 
T

trans. (T. Onoma)

| > Mauricio Fernández ha scritto:
| >> Look carefully at the example:
| >>
| >> # # This creates a Regexp which will match 3 "foo"s.
| >> # re = Regexp::English.literal("foo" * 3)
| >> # re.match("foofoofoo")[0] # => "foofoofoo"
| >
| > sidenote: I'd prefer to see this done like:
| > # This creates a Regexp which will match 3 "foo"s.
| > # irbprompt>somecode
| > # =>someresult
| > # irbprompt>somemore
| > # =>someother
|
| I think the latter is harder to read, because there is more clutter,
| though in theory that style could also be supported by test-extract.
|
| Maybe I can add it later if there is enough demand for it.

Actually goes with your '# outputs ...' notation if you use '# => ...'
instead.

# This creates a Regexp which will match 3 "foo"s.
# irbprompt>somecode # =>someresult
# irbprompt>somemore # =>someother

And I see no good reason to keep the irb prompt so...

# This creates a Regexp which will match 3 "foo"s.
# somecode # =>someresult
# somemore # =>someother

Fairly simple transformation from irb.

T.
 
G

gabriele renzi

trans. (T. Onoma) ha scritto:
| > Mauricio Fernández ha scritto:
| >> Look carefully at the example:
| >>
| >> # # This creates a Regexp which will match 3 "foo"s.
| >> # re = Regexp::English.literal("foo" * 3)
| >> # re.match("foofoofoo")[0] # => "foofoofoo"
| >
| > sidenote: I'd prefer to see this done like:
| > # This creates a Regexp which will match 3 "foo"s.
| > # irbprompt>somecode
| > # =>someresult
| > # irbprompt>somemore
| > # =>someother
|
| I think the latter is harder to read, because there is more clutter,
| though in theory that style could also be supported by test-extract.
|
| Maybe I can add it later if there is enough demand for it.

Actually goes with your '# outputs ...' notation if you use '# => ...'
instead.

# This creates a Regexp which will match 3 "foo"s.
# irbprompt>somecode # =>someresult
# irbprompt>somemore # =>someother

And I see no good reason to keep the irb prompt so...

# This creates a Regexp which will match 3 "foo"s.
# somecode # =>someresult
# somemore # =>someother

Fairly simple transformation from irb.
yes, but that way how would you distinguish code from text... mh.. maybe
considering just lines with #=> ..
 
F

Florian Gross

trans. (T. Onoma) said:
| > Mauricio Fernández ha scritto:
| >> Look carefully at the example:
| >>
| >> # # This creates a Regexp which will match 3 "foo"s.
| >> # re = Regexp::English.literal("foo" * 3)
| >> # re.match("foofoofoo")[0] # => "foofoofoo"
| >
| > sidenote: I'd prefer to see this done like:
| > # This creates a Regexp which will match 3 "foo"s.
| > # irbprompt>somecode
| > # =>someresult
| > # irbprompt>somemore
| > # =>someother
|
| I think the latter is harder to read, because there is more clutter,
| though in theory that style could also be supported by test-extract.
|
| Maybe I can add it later if there is enough demand for it.

Actually goes with your '# outputs ...' notation if you use '# => ...'
instead.

# This creates a Regexp which will match 3 "foo"s.
# irbprompt>somecode # =>someresult
# irbprompt>somemore # =>someother

And I see no good reason to keep the irb prompt so...

# This creates a Regexp which will match 3 "foo"s.
# somecode # =>someresult
# somemore # =>someother

Fairly simple transformation from irb.

Isn't that what we already had above, but with the indentation removed? :)

The indentation also makes RDoc display the text in a fixed-width font
suitable for code BTW.

If the comment had been done without the leading "# " it would not
appear to be part of the example, but of the documentation above it.

Regards,
Florian Gross
 
F

Florian Gross

gabriele said:
trans. (T. Onoma) ha scritto:
yes, but that way how would you distinguish code from text... mh.. maybe
considering just lines with #=> ..

Note that not every line of the sample code has to have a result that is
worth being mentioned.
 
T

trans. (T. Onoma)

' notation if you use '# => ...'
| > instead.
| >
| > # This creates a Regexp which will match 3 "foo"s.
| > # irbprompt>somecode # =>someresult
| > # irbprompt>somemore # =>someother
| >
| > And I see no good reason to keep the irb prompt so...
| >
| > # This creates a Regexp which will match 3 "foo"s.
| > # somecode # =>someresult
| > # somemore # =>someother
| >
| > Fairly simple transformation from irb.
|
| yes, but that way how would you distinguish code from text... mh.. maybe
| considering just lines with #=> ..

Oops, I was just excluding the extra remark space '# ' for brevity. But now I
see that means I have a typo too. This better?

# # This creates a Regexp which will match 3 "foo"s.
# somecode # =>someresult
# somemore # =>someother

But perhaps Mauricio was intending to get rid of the indentation too? In fact
I was wondering about that. How does it know code from comment? What about
something like this:

# Presents a challenge
# ex--
#
# challenge option
#
# There are three options:
#
# jump
# sit
# stand
#
def challenge( option )
# ...
end


T.
 
F

Florian Gross

trans. (T. Onoma) said:
But perhaps Mauricio was intending to get rid of the indentation too? In fact
I was wondering about that. How does it know code from comment? What about
something like this:

# Presents a challenge
# ex--
#
# challenge option
#
# There are three options:
#
# jump
# sit
# stand
#
def challenge( option )
# ...
end

Currently it doesn't. Everything that is indented is assumed to be code.
If you can think of an algorithm that works better than I would be
pleased to know about it.
 
M

Massimiliano Mirra - bard

Eivind Eklund said:
Are you by this saying you are going to abuse Nathaniel's syntax to
group as many of your tests there as you can?

Uh? No. There's no need to, I already write ordinary tests at the
end of the class file and that supports a quick code-test-code cycle
well, I'd only use the example syntax for tests that can serve, well,
as examples.

(Of course Mauricio just showed how the quick cycle can be preserved
with embedded examples anyway, so whatever happens I don't have to
worry about changing my coding habits. Damn you Mauricio, wasn't rpa
enough to drown me in comfort and laziness?)
I don't believe the readability of assert_equal and friends will go to
the same level as an infix operator (which both you and Florian used)
with "getting used to the syntax". If it did, we'd all be programming
in Lisp (and Paul Graham wouldn't say that "prefix operators for maths
still feels weird after 20 years of programming Lisp").

Hmmm, as a little Lisper I think the matter is that prefix notation
here could feel less natural with regard to the surroundings rather
than in and of itself. I remember trying cl-unit with its familiar
assert-equal predicates, which, ok, is prefix anyway, and then finding
another framework which stated conditions like (is (= ...)) which is
even *more* prefix, and I liked that one better.

Anyway, mostly I don't care about prefix vs. infix, but I agree that
seeing `assert_equal' and hearing it internally and making sense of it
requires more brain power than reading `==' or `#=>' and instantly
making sense of it, I'm just not sure that it's that relevant a
quantity of brain power. Here in Rubyland we're used to try and make
0.002 go down to 0.001 whereas elsewhere people got used to live with
2^24. ;-)

Massimiliano
 
T

trans. (T. Onoma)

| > But perhaps Mauricio was intending to get rid of the indentation too? In
| > fact I was wondering about that. How does it know code from comment? What
| > about something like this:
| >
| > # Presents a challenge
| > # ex--
| > #
| > # challenge option
| > #
| > # There are three options:
| > #
| > # jump
| > # sit
| > # stand
| > #
| > def challenge( option )
| > # ...
| > end
|
| Currently it doesn't. Everything that is indented is assumed to be code.
| If you can think of an algorithm that works better than I would be
| pleased to know about it.

Well I'm not sure what your doing presently. You could require an indented
remark.

But I suppose a better option would be more intelligent. What about first
syntax parsing the indented material. If no syntax errors, then good chance
it's Ruby code.

T.
 
F

Florian Gross

trans. (T. Onoma) said:
| > But perhaps Mauricio was intending to get rid of the indentation too? In
| > fact I was wondering about that. How does it know code from comment? What
| > about something like this:
| >
| > # Presents a challenge
| > # ex--
| > #
| > # challenge option
| > #
| > # There are three options:
| > #
| > # jump
| > # sit
| > # stand
| > #
| > def challenge( option )
| > # ...
| > end
|
| Currently it doesn't. Everything that is indented is assumed to be code.
| If you can think of an algorithm that works better than I would be
| pleased to know about it.

Well I'm not sure what your doing presently. You could require an indented
remark.

But I suppose a better option would be more intelligent. What about first
syntax parsing the indented material. If no syntax errors, then good chance
it's Ruby code.

But even your example from above would pass the Syntax Parsing step. And
I think that one might even get false negatives, not only false positives.
 
A

Alexander Kellett

So far, I prefer Florian's approach - however, it may be this works
out OK in a highlighting editor (because def gets highlighted). In
black and white, Florian's is much easier to read, and less overhead,
though.

i much prefer florian's syntax, however, i much prefer the code being
syntax checked along with the file. and i'd like to have the ability
to switch on and off the highlighting of the test code. i can't stand
writing code without syntax highlighting :), í'd consider the discussion
of workarounds to get florian in-comment syntax kind of hackish, however
i do much prefer the "=>" etc syntax to the rather verbose "example {}".
at this point, based on what i've seen i'd use florians version in all
likelyhood, but one of my reasons for this is that florians version
doesn't stop the use of the code where the dependancy isn't found,
whereas until test/unit2 is standard, code using this would require
a dependancy other than pure ruby.

Alex
 
T

trans. (T. Onoma)

On Wednesday 20 October 2004 06:49 am, Florian Gross wrote:
| > But I suppose a better option would be more intelligent. What about first
| > syntax parsing the indented material. If no syntax errors, then good
| > chance it's Ruby code.
|
| But even your example from above would pass the Syntax Parsing step. And
| I think that one might even get false negatives, not only false positives.

True. I "under-spoke". I was thinking that it might make sure those were real
methods too.

This get hairy though, I imagine. Markup is probably the right answer.

T.
 
M

Markus

| > But perhaps Mauricio was intending to get rid of the indentation too? In
| > fact I was wondering about that. How does it know code from comment? What
| > about something like this:
| >
| > # Presents a challenge
| > # ex--
| > #
| > # challenge option
| > #
| > # There are three options:
| > #
| > # jump
| > # sit
| > # stand
| > #
| > def challenge( option )
| > # ...
| > end
|
| Currently it doesn't. Everything that is indented is assumed to be code.
| If you can think of an algorithm that works better than I would be
| pleased to know about it.

Well I'm not sure what your doing presently. You could require an indented
remark.

But I suppose a better option would be more intelligent. What about first
syntax parsing the indented material. If no syntax errors, then good chance
it's Ruby code.

I still don't like the whole idea of executing comments. What if
someone ignorant of your convention writes something like:

# The sudo_shell is a wrapper for running shell commands as root
for
# people who have the rights. It is powerful and dangerous. For
# example, never write anything like:
#
# sudo_shell "cd \;rm -r -f *"
#
# or you'll probably regret it.


-- Markus (back from Costa Rica, which was wonderful!)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,130
Latest member
MitchellTe
Top