hoodwink.d enhanced
RSS
2.0
XHTML
1.0

RedHanded

User-Defined Literals in Sydney #

by why in inspect

Evan’s just released another Sydney while the Ruby-Core list is alive with bug reports and input from the core team. Nobu spotted a problem with user-defined literals and I was like, “oh, right, I need to try that.”

Add your methods to the PercentExpansion module. So, if you want your own %y, do like:

 require 'yaml'
 module PercentExpansion
   def y( str, m ); YAML::load( str ) end
 end

 METADATA = %y{
   author: _why
   date: 2005-07-13 09:10:12 -05:00
   title: User-defined Literals
 }

Or for fetching a URI:

 require 'open-uri'
 module PercentExpansion
   def fetch( str, m )
     URI.parse( str ).open do |urif|
       urif.read
     end
   end
 end

 ruby_terms = %fetch{http://ruby-lang.org/en/LICENSE.txt}

Sydney bars you from overriding the default literals. Which is probably safe. But, you know, I have to wonder what sort of hacks we’d see if these could be overridden.

Or if the string itself could be overturned. One thought: interpolation could be restyled in midair. R is for recklesssnessss.

said on 13 Jul 2005 at 12:01

Are redefined literals really a good idea? Is

%fetch{http://ruby-lang.org/en/LICENSE.txt}

Really much better than

fetch "http://ruby-lang.org/en/LICENSE.txt"

Perhaps there is a place for them with stuff such as inlining xml, sql, javascript and the like. At the moment though they just seem to add some more syntax.

said on 13 Jul 2005 at 12:07

It’s an example. I really like %y, but yeah %fetch is probably contrived.

said on 13 Jul 2005 at 14:33

I have to admit I want %stuff to disappear. Except for %w, I don’t feel they add so much, and they feel strange for everything else. But user defined %stuff is better than now :)

said on 13 Jul 2005 at 14:53

Really cool idea. Sounds like Ruby**2. This as language feature would be extremely interesting.

I always use ` to define string-like literals in my code. It’s not just another way to call a function, because is carries additional information.

Think further. What about %R/bla/ for a shorthand to /\Abla\z/, something I always need to check input. Even modifiers could be added to strings or system calls.

Or what about a syntax like

'I want a literal > here'h

for text2html conversion, and

'I want a literal > here'H

for reverse. Or regexp heredocs. Or ANSI colors with

puts %red'Error'

Oh the possibilities. Enhanced string features in Ruby are so useful (I always get angry when I’m lost within Java or C that don’t have % or <<- or #{}.) But there is no reason to stop here. As long as is stays dynamic, intuitive and readable (I think %-notations increase readability), I will surely use syntax sugar of that kind.

But I assume matz won’t add it; maybe it’s too much noise.

said on 13 Jul 2005 at 16:57

What’s the m for? What must it respond_to??

said on 13 Jul 2005 at 18:09

How about we just make grammars a first-class abstraction in Ruby, and permit Ruby’s grammar to be arbitrarily extended a la Perl 6? </evil>

said on 13 Jul 2005 at 23:45

I’m sold on this. Check this out:

 module PercentExpansion
   def red( str, m ) # RedCloth, quoted, indented
     RedCloth.new str.strip.gsub( /^ +/, '' )
   end
 end

 def some_redcloth; %red{
   h1. My Day T'day

   Today I lit some candles and played with
   user-defined literals.  My dog got into
   my chapsticks again.
 } end

You’ve got to admit, you’ve always wanted to have strings that automatically gsub( /^ +/, '' ), right?

said on 14 Jul 2005 at 10:42

riffraff: I also use %r{} a lot because escaping slashes is totally way too ugly. I think that percent literals are over all still a good thing—just don’t use them just because you can unless you are writing code that is supposed to be hard to understand…

said on 14 Jul 2005 at 12:26

But do you really gain anything over defining ‘red’ in the kernel and then using:

 def some_redcloth; 
 red """ 
   h1. All Yesterday

   Grilled up some old string.  
   The Cat keeps eatin' all my cheese.
""" 
end

I think part of the power of ruby’s syntax is that you can introduce things like this right now.

said on 14 Jul 2005 at 12:27

netghost: mind you, triple quotes are a python thing they work in ruby just by accident ;)

said on 14 Jul 2005 at 14:19

All this talk of %-quoting inspired me to write the following (which is pure-Ruby, not Sydney-Ruby):


eval %q!dne;)'*b'(kcap.])'10',}"'{q%(rt.q[ lave;q Qq fed!.reverse
''%qQ(%q`''''"""'"'"'"""'''"'"""'""''"""''''''"''"""''"'''"'"''"'"'"'"""'""''"""'''"'"""''''''"''"''''""''"""'""'""""'""'''"'"""''''"'""'"'"''""''"''"""''''''"'''"''"'"'"'"'"""''"'''""'"''""""''''''"'''''"''"'"''''""'""'''""'""'"'""'"'"''""''"''"""'"''''"''"""''"''`)

Feel free to run it, it doesn’t do anything evil.

P.S. Yes, I’m training for next year’s obfuscated Ruby contest.

said on 14 Jul 2005 at 18:56

Mmh…I noticed that the Kernel method variants have a big advantage: They are not limited to literals.

If PercentExpansion was common, people would start to write

%red(#{File.read 'baz.redcloth'})

or something. That’s not good.

How about expanding String instead?

said on 15 Jul 2005 at 01:46

Well done, MrCode! Now write a brainfuck interpreter in one line.

said on 15 Jul 2005 at 01:52

murphy:


module PercentExpansion
  def redf str, m
    %red(#{File.read str})
  end
end

:D

On a side note, in %r(#{string}) (for example), are ( and ) escaped?

said on 15 Jul 2005 at 03:28

this is a great feature, a bit like Lisp Read macros! Hope this gets includeded in Ruby 1.9

said on 18 Jul 2005 at 19:14
Btw, folks, the second argument to the method is the object that the expansion occurs within. This allows you, if you so please, to customize the expansion based on the context. IE:
module PercentExpansion
  def red(str, obj)
      case obj
      when Terminal
         ansi_color(:red, str)
      when HTMLEmitter
         "<red>#{str}</red>" 
      end
  end
end
said on 26 Jul 2005 at 08:58

Noticed this way too late. There’s another implementation of user-defined literals available at http://developer.berlios.de/projects/suby/. There are a few differences with Evan’s version, but this patch should reflect how I envisioned user-defined percent literals when I wrote the RCR (though it does not handle things like %red yet, only single character names like %r).

And to MenTaLguY: we are toying with the idea of making grammars first-class objects in Suby (another Ruby fork, see http://developer.berlios.de/projects/suby/, though the web page certainly needs an update) and allowing Ruby’s grammar to be extended arbitrarily, but mostly due to time shortage the work on Suby is often stalled, and happens in small bursts.

Comments are closed for this entry.