<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Engine Yard Blog &#187; Larry Diehl</title>
	<atom:link href="http://www.engineyard.com/blog/author/larrydiehl/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.engineyard.com/blog</link>
	<description></description>
	<lastBuildDate>Tue, 07 Feb 2012 19:36:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>AppCloud Dashboard Performance Boost</title>
		<link>http://www.engineyard.com/blog/2010/appcloud-dashboard-performance-boost/</link>
		<comments>http://www.engineyard.com/blog/2010/appcloud-dashboard-performance-boost/#comments</comments>
		<pubDate>Mon, 18 Oct 2010 21:25:13 +0000</pubDate>
		<dc:creator>Larry Diehl</dc:creator>
				<category><![CDATA[Engine Yard Cloud]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[appcloud]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=4809</guid>
		<description><![CDATA[<p>If you are an Engine Yard AppCloud customer with a large number of environments, you may have noticed slowly degrading performance recently. Specifically, the dashboard page load time was a bit long, and live instance status &amp; message updates sometimes resulted in a flicker.</p>
<p class="framed"><a href="http://www.engineyard.com/blog/wp-content/uploads/20101005-ptb8ijadd3kdbbabytxtt8kxb3.png-PNG-Image-1465x502-pixels.png" mce_href="http://www.engineyard.com/blog/wp-content/uploads/20101005-ptb8ijadd3kdbbabytxtt8kxb3.png-PNG-Image-1465x502-pixels.png"><img class="size-medium wp-image-4834" title="appcloud-screenshot" src="http://www.engineyard.com/blog/wp-content/uploads/20101005-ptb8ijadd3kdbbabytxtt8kxb3.png-PNG-Image-1465x502-pixels.png" mce_src="http://www.engineyard.com/blog/wp-content/uploads/20101005-ptb8ijadd3kdbbabytxtt8kxb3.png-PNG-Image-1465x502-pixels.png" alt="" width="100%"/><br />Click to view full size.</a></p>
<p>We are pleased to say that as of a recent deploy, customers with many environments can now enjoy a much snappier (70% faster) dashboard.</p>
<p>For the curious, the fix was done by discovering an I/O bottleneck via New Relic and getting rid of it by appropriately using fragment caching.</p>
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2010/appcloud-dashboard-performance-boost/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Hint of Hubris</title>
		<link>http://www.engineyard.com/blog/2010/a-hint-of-hubris/</link>
		<comments>http://www.engineyard.com/blog/2010/a-hint-of-hubris/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 18:00:33 +0000</pubDate>
		<dc:creator>Larry Diehl</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Polyglot Programming]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=3314</guid>
		<description><![CDATA[<p>Ruby is a highly dynamic language with impressive capabilities for runtime redefinition of classes, objects, methods, and variables. Haskell, on the other hand, is a purely functional language that confines mutation within a sophisticated static type system. Given their many differences one or the other may be more suited for whatever problem you might be working on (see <a href="http://en.wikipedia.org/wiki/Polyglot_%28computing%29">polyglot programming</a>), but sometimes, a mix of both would be <em>even</em> better. Thanks to <a href="http://github.com/mwotton/Hubris">Hubris</a>, you now have that option!</p>
<p>Hubris is a gem that allows you to call out to natively compiled Haskell shared objects. In this post, I'll talk a bit more about why you might want to do that, <em>how</em> you'd go about doing that, and share some real world examples.</p>
<h2>So Why Would I Want To Use Haskell?</h2>
<p>It's easy for any decent programmer to spot the many striking differences between Ruby and Haskell, but why a Rubyist might be interested in  Haskell is a question worth asking. There are two primary scenarios:</p>
<h3>1. Native Extensions</h3>
<p>When CPU-intensive algorithms are needed for a task in Ruby, you usually drop down to the C or C++ level to take advantage of the highly optimized code yielded by a C/C++ compiler. Unfortunately, for someone <em>without</em> significant experience in the language, it can be easy to run into memory management woes, not to mention the frustration of dealing with a more hands-on (with respect to memory and explicit typing) language like C.</p>
<p>Haskell is a managed memory language with one of the most powerful type inference capabilities around. What this means is that you can avoid being bothered with explicitly denoting types at function call-sites, and choose whether or not to add types to definitions for the particular function you're working on. Additionally, <a href="http://www.haskell.org/ghc/">GHC</a> (Haskell's most prominent compiler for production applications) produces compiled native code that has performance in the same league as C/C++.</p>
<h3>2. Concurrency</h3>
<p>Many popular languages (especially Object Oriented ones) allow unconstrained mutation of data (e.g. mutator! methods in Ruby). This has always had implications for the difficulty of reasoning in the resulting code. But lately, this has become a bigger problem because it makes reasoning about concurrent program execution a nightmare.</p>
<p>What differentiates Haskell from many other functional languages is that Haskell isolates side effects statically in types rather than dynamically in language constructs. In effect, this means you can statically determine a list of functions/places to look (and eliminate many of the places you <em>don't</em> have to look) when problems related to side effects <em>do</em> come up.</p>
<h3>3. And More</h3>
<p>Haskell  as a whole has many other useful properties, such as implicit laziness, implicit argument currying, a typeclass system for generic programming, various <a href="http://en.wikipedia.org/wiki/Concurrent_Haskell">concurrency constructs including an STM</a> and a wonderful <a href="http://code.haskell.org/ThreadScope/">concurrency debugger</a>... just to name a few. Rubyists who enjoyed <a href="http://mislav.uniqpath.com/poignant-guide/">Why's Poignant Guide to Ruby</a> may enjoy parsing through <a href="http://learnyouahaskell.com/">Learn You a Haskell for Great Good</a>.</p>
<h2>Okay, I Buy It: Now How Can I Do It?</h2>
<p>Now that we've seen <em>why</em> you might want to use Haskell, we'll take a look at how to use Hubris from Ruby. There are two main modes of operation: a way to embed a Ruby string containing Haskell code inline, and a way to load code from a plain Haskell <code>.hs</code> file. Like so:</p>
<pre>class Example
  hubris :inline =&gt; "foo :: Integer -&gt; Integer; foo x= 1330 + x"
end

Example.new.foo # =&gt; 1337</pre>
<pre>class Example
  hubris :source =&gt; "MyHaskell.hs"
end

Example.new.my_awesome_function "go ye forth into a world unknown"</pre>
<p>Note that due to support for the <code>:inline</code> option, you can even experiment with adding new functions dynamically in an irb session (compile errors like type conflicts get spit out for you to read)! In the background, Hubris will compile code to <code>/var/hubris/cache</code> and then link it in to your running Ruby program.</p>
<p>The first time you run the code, it will be a bit slower as it compiles the Haskell, but subsequent runs will load the cached <code>.so</code> files directly. Another nice property is that the already compiled code is compared against a saved hash in order to only recompile when changes have been made.</p>
<p>As the Hubris README demonstrates, a third option is load modules already installed on the system:</p>
<pre>hubris :module =&gt; "Data.ByteString", :packages =&gt; ["bytestring"]</pre>
<p>Hubris comes with an example Rack app that exposes a Haskell implementation of the Fibonacci function. I'll show it to you here as a compact Sinatra app. A likely use case for Rubyists will be to leverage Ruby's mature web development library ecosystem by exposing an API for a compact and optimized Haskell algorithm/program .</p>
<pre>require 'sinatra'
require 'hubris'

helpers do
  hubris :inline =&gt; &lt;&lt;-HASKELL
fibonacci :: Int -&gt; Int
fibonacci n = fibs !! n
  where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
HASKELL
end

get '/:number' do
  fibonacci(params[:number].to_i).inspect
end</pre>
<p>As you can see, sensible conversions between data types in both languages are done automatically. Below is a table of the mappings between Ruby and Haskell types (see the <a href="http://github.com/mwotton/Hubris/blob/master/spec/hubris_spec.rb">Hubris specs</a> for example uses). Try  searching <a href="http://haskell.org/hoogle/">Hoogle</a> (no, that's not a typo) to find Haskell functions supporting types you're interested in.</p>
<table border="1">
<tbody>
<tr>
<th>Ruby</th>
<th>Haskell</th>
</tr>
<tr>
<td>TrueClass/FalseClass</td>
<td>Boolean</td>
</tr>
<tr>
<td>Fixnum/Bignum</td>
<td>Integer</td>
</tr>
<tr>
<td>Float</td>
<td>Double</td>
</tr>
<tr>
<td>String</td>
<td>Data.ByteString</td>
</tr>
<tr>
<td>Array</td>
<td>List</td>
</tr>
<tr>
<td>Hash</td>
<td>Map.Map</td>
</tr>
<tr>
<td><em>value</em> or nil</td>
<td>Maybe</td>
</tr>
<tr>
<td><a href="http://github.com/mwotton/Hubris/issues#issue/15">Not yet</a></td>
<td>Multiple arguments</td>
</tr>
<tr>
<td><a href="http://github.com/mwotton/Hubris/issues#issue/16">Not yet</a></td>
<td>Tuple</td>
</tr>
<tr>
<td><a href="http://github.com/mwotton/Hubris/issues#issue/16">Not yet</a></td>
<td>Algebraic types</td>
</tr>
</tbody>
</table>
<p>Hubris currently lacks support for calling functions with multiple arguments (or tuples or custom algebraic types)—which is a serious drawback. However, this is not by design and you can track the Github issues for those missing features via the links in the table above.</p>
<p>In the future, fine-grained interaction between both languages will be possible. For example, <a href="http://github.com/larrytheliquid/neurosis/blob/5b8e7771e07275dd9ef5795939e679809b3567b0/neurosis_spec.rb">unit testing Haskell functions with RSpec</a>, <em>including</em> those with multiple arguments. For the time being, you can take a more coarse-grained approach by passing a hash of many values to a single interface function in Haskell.</p>
<h2>A Real-World Example</h2>
<p>I'll end my overview by linking to a more complicated example that <a href="http://github.com/larrytheliquid/neurosis">exposes a Ruby webservice to a coarsely-grained Haskell function</a>. Here, a Sinatra web service is passed a JSON string, which is parsed into a Ruby Hash (actually using C via the JSON gem), then passed to a Haskell function, which is converted on the Haskell side to a Map and then returns an <code>[[Int]]</code> List that gets converted into a nested Ruby Array of integers to finally return the web response as a String. (That made for a long and hard to read sentence, but go through it slowly: it makes sense.)</p>
<p>Rather than calling out to a simple Fibonacci function, you call a basic implementation of a <a href="http://en.wikipedia.org/wiki/Multilayer_perceptron">Multi-layer Perceptron Neural Network</a>. <a href="http://hunit.sourceforge.net/HUnit-1.0/Guide.html">HUnit</a> is used for <a href="http://hunit.sourceforge.net/HUnit-1.0/Guide.html">u</a><a href="http://github.com/larrytheliquid/neurosis/blob/master/PerceptronTest.hs">nit testing</a> in Haskell. These tests correspond to values in a <a href="http://github.com/larrytheliquid/neurosis/tree/master/doc/">handwritten derivation of the first epoch of learning the XOR problem</a>. A Ruby <a href="http://github.com/larrytheliquid/neurosis/blob/master/neurosis_spec.rb">integration test</a> drives the whole stack via <a href="http://github.com/brynary/rack-test">rack-test</a> on the XOR problem. A <a href="http://github.com/larrytheliquid/neurosis/blob/master/Rakefile">rake task</a> runs both sets of tests to conveniently validate expected behavior. Explaining the algorithm would be enough content for at least a separate post, but hopefully <a href="http://github.com/larrytheliquid/neurosis">Neurosis</a> can serve as a useful Hubris reference implementation to fiddle around with in the meantime.</p>
<h2>Conclusion</h2>
<p>There are some serious limitations that prevent fine-grained interaction between Ruby and Haskell. Nevertheless, <a href="http://github.com/mwotton/Hubris">Hubris</a> has strong potential as a useful library and can be used today via coarse-grained interfaces. Note that Hubris has been tested to work on MRI 1.8 and 1.9, but <em>should</em> work with any Ruby that conforms to MRI's C API.</p>
<p>Installation of the Haskell-side of the library is a bit of a pain right now, but <a href="http://wiki.github.com/mwotton/Hubris/installation">this wiki page</a> is recording the team's progress as they work on fixing it.</p>
<p>So here we are: it's time to go out and write your own Haskell code, to be called from Ruby (or find a favorite Haskell library to reuse)... that is, if you can make it past installation ;)</p>
<p>As always, leave any questions and comments!
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2010/a-hint-of-hubris/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Cucumber: Step Argument Transforms</title>
		<link>http://www.engineyard.com/blog/2009/cucumber-step-argument-transforms/</link>
		<comments>http://www.engineyard.com/blog/2009/cucumber-step-argument-transforms/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 17:00:24 +0000</pubDate>
		<dc:creator>Larry Diehl</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[BDD]]></category>
		<category><![CDATA[Cucumber]]></category>
		<category><![CDATA[DataMapper]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Transform]]></category>

		<guid isPermaLink="false">http://www.engineyard.com/blog/?p=2311</guid>
		<description><![CDATA[<p><a href="http://cukes.info">Cucumber</a> is a great tool that lets you create something akin to a personalized programming language for testing. If you haven't heard of it yet, refer to previous posts on <a href="http://www.engineyard.com/blog/2009/cucumber-introduction/">basic</a> and <a href="http://www.engineyard.com/blog/2009/cucumber-more-advanced/">advanced cucumber</a>. While I love what Cucumber lets you do, up until now a lack of modularity within step definitions has been the elephant in the room. Dave Astels and I were lucky enough to stumble upon a neat solution to this while pairing recently, so let's take a more specific look at the problem and solution. Note that at the time of writing the feature is only available in the <a href="http://github.com/aslakhellesoy/cucumber">trunk Git version of Cucumber</a>, but expect a release soon.</p>
<h2>Problem: Step Definition Arguments Captured as Strings</h2>
<p>As you write step definitions that capture variable data in the provided regex, you'll remain happy if the target data is naturally represented as a string. The following example uses <a href="http://datamapper.org">DataMapper</a> as its ORM and dm-sweatshop (found in <a href="http://github.com/datamapper/dm-more">dm-more</a>) for fixture factories:</p>
<pre># step definition file
Given /^a new user with username (.+)$/ do |username|
  @user = User.make(:username =&gt; username)
end

Then /^the user is valid$/ do
  @user.should be_valid
end

# feature file
Scenario: valid username
  Given a new user with username larrytheliquid
  Then the user is valid</pre>
<p>However, there are many occasions where the natural data-type for a captured argument may be something other than a string:</p>
<pre># step definition file
Given /^a new user with age (\d+)$/ do |age_string|
  @user = User.make(:age =&gt; age_string.to_i)
end

Then /^the user is valid$/ do
  @user.should be_valid
end

# feature file
Scenario: valid age
  Given a new user with age 22
  Then the user is valid</pre>
<p>The key thing to notice is that it was necessary to convert <code>age_string</code> to an integer because the concept of age is naturally represented here as an integer. While the conversion does not look like much work <em>now</em>, the actual problem lies in modularity. If we would like to refer to age in any subsequent step definitions, we must duplicate the code to coerce the string everywhere... certainly not DRY.</p>
<p>The code we've seen so far is able to get away with going from captured argument string, to the argument with its natural data-type, to an ORM instance representation, without too much pain. This is possible because the structure of the scenarios being written is fairly simple and setup can be performed in a <code>Given</code> that creates an instance variable to be used in a <code>Then</code>. However, there are more complex scenarios where this pattern is not possible.</p>
<pre># step definition file
Given /^a customer user named (\w+)$/ do |username|
  User.gen(:customer, :username =&gt; username)
end

Given /^a support user named (\w+)$/ do |username|
  User.gen(:support, :username =&gt; username)
end

When /^user (\w+) is assigned user (\w+)$/ do |support_username, customer_username|
  support_user = User.first(:username =&gt; support_username)
  customer_user = User.first(:username =&gt; customer_username)
  support_user.assign(customer_user)
end

Then /^user (\w+) should be in user (\w+)'s work queue$/ do |customer_username, support_username|
  support_user = User.first(:username =&gt; support_username)
  customer_user = User.first(:username =&gt; customer_username)
  support_user.work_queue.should include(customer_user)
end

# feature file
Scenario: support assigned a customer
  Given a support user named stoltini
  And a customer user named larrytheliquid
  When user stoltini is assigned user larrytheliquid
  Then user larrytheliquid should be in user stoltini's work queue</pre>
<p>The example above needs to reference specific users in both a <code>When</code> and a <code>Then</code>, and cannot rely upon a single instance variable that sets up state in a <code>Given</code>. The unfortunate result is some pretty nasty duplication of the ORM finder code to lookup each user by their respective usernames in the database.</p>
<h2>Solution: Step Argument Transforms</h2>
<p>The historical problem with Cucumber has always been that it was restricted to yielding strings as step definition arguments, but this is no longer the case. With a new <code>Transform</code> method, we are able to register regular expressions with Cucumber that it will check against arguments <em>before</em> they are yielded to step definitions. In addition to a regex, <code>Transform</code> expects a block that will be passed the raw argument, and whose return value will be used in place of it.</p>
<p>First, lets revisit our original modularity problem in the age example:</p>
<pre># support file
Transform /^age \d+$/ do |step_arg|
  /(\d+)$/.match(step_arg)[0].to_i
end

# step definition file
Given /^a new user with (age \d+)$/ do |age|
  @user = User.make(:age =&gt; age)
end

Then /^the user is valid$/ do
  @user.should be_valid
end</pre>
<p>If you look at the <code>Given</code>, you'll see that we expanded the capture group to include "age" as valuable contextual information. With step argument transforms, such contextual information is important to avoid overly general transforms that affect every argument.</p>
<p>The first argument to <code>Transform</code> uses a regex that anchors the beginning and end. This means that we will only match that specific entire string, rather than accidentally matching other step arguments that happen to contain a partial piece of our regex (of course, you could have more general versions if you wanted to, just tread carefully).</p>
<p>If a registered transform matches an argument of a step definition, that argument will be passed to the block supplied with the transform definition. In the <code>Transform</code> example above, we anchor at the end and just capture the digit, because we already know the structure of our input based on the initial match.</p>
<p>After pulling the information we want out of the match group, we apply our transform, <code>to_i</code>, which is yielded to the <code>Given</code> as the variable <code>age</code>. Note that we chose the name <code>age</code> in our new <code>Given</code> instead of <code>age_string</code> because we are expecting the transform to be applied. Most importantly, any other step definition that captures a group of the form <code>(age \d+)</code> will happily transform <code>age</code> into its natural type, keeping our code nice and DRY. Let's see how step argument transforms change our previous more complex scenario.</p>
<pre># support file
Transform /^user \w+$/ do |step_arg|
  User.first :username =&gt; /(\w+)$/.match(step_arg)[0]
end

# step definition file
Given /^a customer user named (\w+)$/ do |username|
  User.gen(:customer, :username =&gt; username)
end

Given /^a support user named (\w+)$/ do |username|
  User.gen(:support, :username =&gt; username)
end

When /^(user \w+) is assigned (user \w+)$/ do |support_user, customer_user|
  support_user.assign(customer_user)
end

Then /^(user \w+) should be in (user \w+)'s work queue$/ do |customer_user, support_user|
  support_user.work_queue.should include(customer_user)
end</pre>
<p>Here we use a similar strategy to capture groups of the form <code>(user \w+)</code>. The transform applied looks up the user by their username and returns a DataMapper instance. The neat thing is that we can reuse our capture group across multiple different step definitions (the <code>When</code> and the <code>Then</code>), and the more involved duplicated boilerplate code gets packed away in the call to <code>Transform</code>.</p>
<h2>Tips and Tricks</h2>
<p>Scenario outlines and example tables are really cool features of Cucumber that let you specify a lot of different permutations of data in a compact way. However, the feature is also somewhat limited, because it can only yield string data. With step argument transforms, you'll find yourself using the awesome tables more because duplicated transform code is removed so there is less friction to write additional step definitions.</p>
<pre># feature file
Scenario Outline: username validity
  Given a new user with age &lt;age&gt;
  Then the user is &lt;validity&gt;

Scenarios: valid
| age | validity |
| 18  | valid    |
| 21  | valid    |
| 49  | valid    |
| 120 | valid    |
Scenarios: invalid
| age | validity|
| 0   | invalid |
| 1   | invalid |
| 12  | invalid |
| 17  | invalid |

#... plus different steps using age</pre>
<p>Sometimes it may be more convenient to pass a string version of a regex to <code>Transform</code>, so this is supported. Below is an example where the goal is to test properties of a Unix system. Any capture groups that contain <code>path</code> followed by a Unix path are desired to be expanded into their absolute system filepath. The <code>UNIX_PATH_CAPTURE</code> pattern is designed to be regex-interpolated into other regex capture groups, so it is defined as a string to prevent unintentional use as a standalone regex.</p>
<pre># support file
UNIX_PATH_CAPTURE = 'path (?:\w+|\/|\.|-|~)+'

Transform UNIX_PATH_CAPTURE do |step_arg|
  File.expand_path /^path (.*)/.match(step_arg)[0]
end</pre>
<p>To avoid overly confusing dependencies, a step argument may only be transformed once. The <code>Transform</code> defined last gets matching order precedence over previously defined transforms, giving you the ability to "override" previous transforms. As a rule of thumb, define general transforms first and get more specific last. More importantly, appropriately including contextual data in capture groups prevents potentially unexpected transforms.</p>
<h2>Conclusion</h2>
<p>Cucumber has been a fantastic and innovative tool thus far. With step argument transforms, another bit of frustration is removed and your step definitions stay DRY.</p>
<p>As a final note, I'd like to point out how awesome it was to hack out the first version of this with Dave Astels while pairing, test-driven, and in less than an hour... given his BDD/RSpec/Cucumber background =) As mentioned before, we were pairing and ran into a problem that unearthed this feature. Before we knew it the console flashed from red to green.</p>
<p>Happy hacking!
<p><a href="http://www.engineyard.com/blog"><img height="98" width="61" title="logo-engineyard" alt="" class="attachment-post-thumbnail wp-post-image" src="http://www.engineyard.com/blog/wp-content/uploads/logo-engineyard.png"/></a></p>
]]></description>
		<wfw:commentRss>http://www.engineyard.com/blog/2009/cucumber-step-argument-transforms/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>

