Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing portable scheme code. Is anything "standard" beyond R5RS itself?

Tags:

scheme

I'm learning scheme and until now have been using guile. I'm really just learning as a way to teach myself a functional programming language, but I'd like to publish an open source project of some sort to reenforce the study— not sure what yet... I'm a web developer, so probably something webby.

It's becoming apparent that publishing scheme code isn't very easy to do, with all these different implementations and no real standards beyond the core of the language itself (R5RS). For example, I'm almost certainly going to need to do basic IO on disk and over a TCP socket, along with string manipulation, such as scanning/regex, which seems not to be covered by R5RS, unless I'm not seeing it in the document. It seems like Scheme is more of a "concept" than a practical language... is this a fair assessment? Perhaps I should look to something like Haskell if I want to learn a functional programming language that lends itself more to use in open source projects?

In reality, how much pain do the differing scheme implementations pose when you want to publish an open source project? I don't really fancy having to maintain 5 different functions for basic things like string manipulation under various mainstream implementations (Chicken, guile, MIT, DrRacket). How many people actually write scheme for cross-implementation compatibility, as opposed to being tightly coupled with the library functions that only exist in their own scheme?

I have read http://www.ccs.neu.edu/home/dorai/scmxlate/scheme-boston/talk.html, which doesn't fill me with confidence ;)

EDIT | Let's re-define "standard" as "common".

like image 677
d11wtq Avatar asked Jun 16 '12 09:06

d11wtq


2 Answers

I believe that in Scheme, portability is a fool's errand, since Scheme implementations are more different than they are similar, and there is no single implementation that other implementations try to emulate (unlike Python and Ruby, for example).

Thus, portability in Scheme is analogous to using software rendering for writing games "because it's in the common subset between OpenGL and DirectX". In other words, it's a lowest common denominator—it can be done, but you lose access to many features that the implementation offers.

For this reason, while SRFIs generally have a portable reference implementation (where practical), some of them are accompanied by notes that a quality Scheme implementation should tailor the library to use implementation-specific features in order to function optimally.

  • A prime example is case-lambda (SRFI 16); it can be implemented portably, and the reference implementation demonstrates it, but it's definitely less optimal compared to a built-in case-lambda, since you're having to implement function dispatch in "user" code.
  • Another example is stream-constant from SRFI 41. The reference implementation uses an O(n) simulation of circular lists for portability, but any decent implementation should adapt that function to use real circular lists so that it's O(1).

The list goes on. Many useful things in Scheme are not portable—SRFIs help make more features portable, but there's no way that SRFIs can cover everything. If you want to get useful work done efficiently, chances are pretty good you will have to use non-portable features. The best you can do, I think, is to write a façade to encapsulate those features that aren't already covered by SRFIs.

There is actually now a way to implement stream-constant in an O(1) fashion without using circular lists at all. Portable and fast for the win!

like image 172
Chris Jester-Young Avatar answered Sep 18 '22 12:09

Chris Jester-Young


Difficult question.

Most people decide to be pragmatic. If portability between implementations is important, they write the bulk of the program in standard Scheme and isolate non-standard parts in (smallish) libraries. There have been various approaches of how exactly to do this. One recent effort is SnowFort.

http://snow.iro.umontreal.ca/

An older effort is SLIB.

http://people.csail.mit.edu/jaffer/SLIB

If you look - or ask for - libraries for regular expressions and lexer/parsers you'll quickly find some.

Since the philosophy of R5RS is to include only those language features that all implementors agree on, the standard is small - but also very stable.

However for "real world" programming R5RS might not be the best fit. Therefore R6RS (and R7RS?) include more "real world" libraries.

That said if you only need portability because it seems to be the Right Thing, then reconsider carefully if you really want to put the effort in. I would simply write my program on the implementation I know the best. Then if necessary port it afterwards. This often turns out to be easier than expected.

like image 22
soegaard Avatar answered Sep 19 '22 12:09

soegaard