s c h e m a t i c s : c o o k b o o k

/ StringChapter / Cookbook.StringTabs

This Web

TOC (with recipes)

Other Webs



Schematics Home
Sourceforge Page
Original Cookbook

Scheme Links

Scheme FAQ
Scheme Cross Reference
Scheme48 SCM
MIT Scheme scsh
JScheme Kawa
Chicken Guile
Bigloo Tiny
Gambit LispMe

Lambda the Ultimate

Expanding and Compressing Tabs


You want to convert spaces in a string to tabs, or vice versa.


You can define this by searching for tabs and expanding them as they're found. 500 Can't connect to (connect: Connection refused)


Python includes an expandtabs() method, but Scheme doesn't. This is probably because the tab/space distinction is very important in Python source code, but not so in Scheme. Still, it's a useful thing to do sometimes. The tricky thing about tab expansion is that a tab doesn't translate directly into a fixed number of spaces; you have to calculate the number of spaces for each tab to reach the next tabstop. Tabstops divide the string into equal partitions of the length specified, and the action of a tab character is to move forward to the next tabstop. For example, if your tabstop is 4 and you have the string "12345\t678\t", the first tab converts to 3 spaces and the 2nd converts to one space, e.g. "12345 678 ". This solution uses a named let to iterate over the string, building up alternate sequences of spaces and non-tab runs of characters. On each loop, if we've reached the end of the string without finding another tab, then we append the remainder of the string to the other parts and fold them together with string-append. Otherwise, we calculate the number of spaces that this tab expands to, then loop with the tab expansion and the current run of non-tab characters appended onto the result list.

-- GordonWeakliem - 27 Apr 2004

This implementation feels too complicated, but I tried a number of approaches and this was the only correct one I could come up with.

-- GordonWeakliem - 27 Apr 2004

Here's an alternate that's a bit different. 500 Can't connect to (connect: Connection refused)

-- GordonWeakliem - 28 Apr 2004

Gordon, do you have any test cases for the above procedure. I'd like to try implementing my own version but the output of your versions isn't what I expected, so I'm not sure of the desired functionality.

-- NoelWelsh - 30 Apr 2004

Here's the test cases. I generated the expected values by running them through Python's expandtabs(), the tabstop is 8.

500 Can't connect to (connect: Connection refused)

-- GordonWeakliem - 30 Apr 2004

Below is my solution. BTW, there was a superfluous make-test-suite in the test suite above. I've removed it.

500 Can't connect to (connect: Connection refused)

To make this solution faster, an efficient growable vector would be a good replacement for the list used in result. It would be interesting to benchmark the current solutions.

-- NoelWelsh - 07 May 2004

This particular topic looks more like a reusable library call than a code pattern to me...

500 Can't connect to (connect: Connection refused)

http://www.neilvandyke.org/tabexpand-scm/ :)

-- NeilVanDyke - 09 May 2004

I removed my versions. They were solving the wrong problem.

-- JensAxelSoegaard - 09 May 2004

Neil van Dyke's library version, linked above, exploits the clever idea of using string ports to accumulate the output string. This (hopefully) provides an equivalent to the "efficient growable vector" that Noel Welsh suggested above, and allows the following simplification of Noel's version:

500 Can't connect to (connect: Connection refused)

I cheated and un-abstracted Noel's helper functions, because they were so small. May the gods of abstraction forgive me. I also opted to use the function signature defined by Neil's library, which includes a starting column parameter, and uses the following wrapper functions to support omission of the tabstop and col parameters:

500 Can't connect to (connect: Connection refused)

-- AntonVanStraaten - 20 Oct 2005

TopicType: Recipe
ParentTopic: StringRecipes
TopicOrder: 080

Copyright © 2004 by the contributing authors. All material on the Schematics Cookbook web site is the property of the contributing authors.
The copyright for certain compilations of material taken from this website is held by the SchematicsEditorsGroup - see ContributorAgreement & LGPL.
Other than such compilations, this material can be redistributed and/or modified under the terms of the GNU Lesser General Public License (LGPL), version 2.1, as published by the Free Software Foundation.
Ideas, requests, problems regarding Schematics Cookbook? Send feedback.
/ You are Main.guest