The Artima Developer Community
Sponsored Link

Scala Buzz
Implementing String#scan in scala

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Zemian Deng

Posts: 49
Nickname: zdeng
Registered: Jan, 2008

Zemian Deng is the creator of SweetScala web framework
Implementing String#scan in scala Posted: Oct 31, 2008 12:30 PM
Reply to this message Reply

This post originated from an RSS feed registered with Scala Buzz by Zemian Deng.
Original Post: Implementing String#scan in scala
Feed Title: thebugslayer
Feed URL: http://www.jroller.com/thebugslayer/feed/entries/atom?cat=%2FScala+Programming
Feed Description: Notes on Scala and Sweet web framework
Latest Scala Buzz Posts
Latest Scala Buzz Posts by Zemian Deng
Latest Posts From thebugslayer

Advertisement
I kind of like Ruby's String#scan method and wonder how hard is it to make that possible in Scala. So I gave it a try. At the end, I want something like this to work:
//String scan test
val testList = List("407-123-4567",
	"407.123.4567",
	"407 123 4567",
	"407 123-4567",
	"(407) 123 4567",
	"(407) 123 4567"
	)
for(phone <- testList)
	println(phone.scan("""\d"""))

for(phone <- testList)
	println(phone.scanGroup("""(\d{4}|\d{3})"""))
So the trick is to add #scan and #scanGroup to the existing java.lang.String class that will do the text extraction and return an List of matched string. Here is the implementation(needs to place above code if on same file):
class StringHelper(val orig : String){		
	//create a matcher object then pass to user function
	private def matcher(pattern : String, input : String)(f : java.util.regex.Matcher => Unit) = 
		f(java.util.regex.Pattern.compile(pattern).matcher(input))

	def scan(pattern : String) = {
		var ls : List[String] = Nil
		matcher(pattern, orig){ m => while(m.find) ls = m.group(0) :: ls }
		ls.reverse
	}
		
	def scanGroup(pattern : String) = { 
		var ls : List[List[String]] = Nil
		matcher(pattern, orig){ m => 
			if(m.groupCount > 0)
				while(m.find){
					var groupls : List[String] = Nil
					for(i <- 1 to m.groupCount)
						groupls = m.group(i) :: groupls
					ls = groupls.reverse :: ls
				}
		}
		ls.reverse
	}
}
implicit def stringHelper(s : String) = new StringHelper(s)
Scala will use stringHelper to convert to the new instance of StringHelper whenever java.lang.String#scan or #scanGroup is found. This is done "implicitly" hence the keyword used, so that our main entry program can remain simple. I noticed that Ruby version can return wither array of string, or a array of array when grouping is used. This is a perfect example of the flexibility of dynamic language that can be dangerous if not used correctly. One can break a provided code block just by giving a different pattern. In Scala, these two return types are distinct, and therefore I have two separated method for handling them. To me it's much more clear and less buggy at runtime. The result looks like this:
List(4, 0, 7, 1, 2, 3, 4, 5, 6, 7)
List(4, 0, 7, 1, 2, 3, 4, 5, 6, 7)
List(4, 0, 7, 1, 2, 3, 4, 5, 6, 7)
List(4, 0, 7, 1, 2, 3, 4, 5, 6, 7)
List(4, 0, 7, 1, 2, 3, 4, 5, 6, 7)
List(4, 0, 7, 1, 2, 3, 4, 5, 6, 7)
List(List(407), List(123), List(4567))
List(List(407), List(123), List(4567))
List(List(407), List(123), List(4567))
List(List(407), List(123), List(4567))
List(List(407), List(123), List(4567))
List(List(407), List(123), List(4567))
If one needs to turn a list back into a string(or the join method), Scala provides a List#mkString that can do the same.

Read: Implementing String#scan in scala

Topic: New Scala Plugin for NetBeans 6.5 RC2 Is Packed Previous Topic   Next Topic Topic: Scala for NetBeans Screenshot#14: Refined Color Theme

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use