Using scheme in repl.it, several functions don’t appear to exist, such as modulo, remainder, inc. Am I missing something? Do I need to import some library or anything? I know there are various permutations of scheme but as far as I can tell these are actual base scheme functions.
At the time of writing repl.it uses BiwaScheme v0.6.4 under the hood, which is quite incomplete (the most recent version is v0.7.0, by the way.) It does not fully implement a Revised Report for the Scheme language, because procedures such as modulo or remainder are a standard part of the language. According to their implementation status page:
BiwaScheme has most features of R6RS Base library. The biggest features not implemented are errors and syntax-rules (you can use define-macro instead).
In particular, the arithmetic section is listed as "not yet" conforming to the standard. There isn't much you can do about it, apart from switching to a standard-conformant interpreter. May I suggest Racket?
Related
I am willing to learn Scheme. I want to stick to R7RS since it's the last standard. However, it seems that there is a lot of fragmentation on the Scheme current implementations, and most of them staying at R5RS or part of R6RS.
The only one I have found supports part of R7RS is Kawa, but as it runs on JVM, it doesn't support tail call optimization, and that is a strong point against that implementation.
Is the Scheme world really that fragmented that there is not even an R7RS full implementation yet? I am asking, because if there is not, as soon as I catch up, I am planning on building one; but, if there exists one, it would be better not to reinvent the wheel and contribute to that certain implementation.
Please, if you have information, I would appreciate not only answering with names, but also with proper further information (official website of the implementation or even a extract from a mailing group would be useful as a reference).
And by the way, I am not considering Racket, as it's not really Scheme anymore.
The Chairman of R7RS Small Language ("Working Group 1") committee, Alex Shinn, created Chibi Scheme as the standard evolved. I believe it is fully compliant. It is a bytecode compiler.
Larceny has a mostly (totally?) compliant R7RS mode, and compiles to machine code.
I have been playing with Picrin which aims for R7RS compliance, and is very very close. It is a bytecode compiler.
A list of implementations that are aiming for R7RS compliance at the committee's wiki include:
Chibi
Chicken (partial)
Foment
Gauche
Guile (partial)
Husk
Kawa
Larceny
Mosh (partial)
Picrin
Sagittarius
Although the question explicitly excludes Racket from consideration as not being Scheme I will point to Racket package "R7RS" which implements R7Rs small.
There are some small incompatibilities documented on project's page.
I am looking at the Java-written Prolog system, Prova.
https://prova.ws/
But it is not clear about its implementation, a Prolog compiler or Prolog interpreter? I read the manual, but did not found an answer.
There are some rumors that Prova is based on Mandarax. The newest
version seem to be heading in the same direction as SWI-Prolog 7,
i.e. it supports dicts and a dot notation. See also here:
http://prova.ws/confluence/display/REWRITEDEV/Prova+maps+for+defining+slotted+terms
The original Mandarax seems to have been an interpreter, and
in the user manual of Prova we find one sentence that self
declares it as a Prolog interpreter, but no hint for compilation.
But there seems to be a newer version of Mandarax (1.1.0) which was
some kind of compiler, but maybe Prova was already branched out
before the compiler arrived, and its still an interpeter.
So although it self declares as a Prolog interpreter, it is most
likely not an ISO Prolog systems, since for example op/3 is missing.
I guess it uses aa tokenizer with some hard wired operators and a
parser with some hard wired operator expressions. (*)
It might nevertheless offer some goodies, but judging from the
documentation and binary size, they might not be many. Which
is possibly compensated by the ability to directly embed Java
calls by the dot notation:
http://prova.ws/confluence/display/REWRITEDEV/Calling+Java+from+Prova+rulebases
Bye
(*)
The Prova syntax goes even that far, that it requires the end-user
to write fail() instead of fail. A syntax variant that is also
found in the new SWI-Prolog 7, although not with the same drastic
effect on the end-user that he/she would be not anymore allowed to use
atoms as goals.
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".
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!
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.
I write a blog that uses Scheme as its implementation language. Because I don't want to alienate users of any particular implementation of Scheme, I write in a restricted dialect of Scheme that is based on R5RS plus syntax-case macros plus my Standard Prelude. I don't find that overly restrictive for the kind of algorithmic programs that I write, but your needs may be different. If you look at the various exercises on the blog, you will see that I wrote my own regular-expression matcher, that I've done a fair amount of string manipulation, and that I've snatched files from the internet by shelling out to wget (I use Chez Scheme -- users have to provide their own non-portable shell mechanism if they use anything else); I've even done some limited graphics work by writing ANSI terminal sequences.
I'll disagree just a little bit with Jens. Instead of porting afterwards, I find it easier to build in portability from the beginning. I didn't use to think that way, but my experience over the last three years shows that it works.
It's worth pointing out that modern Scheme implementations are themselves fairly portable; you can often port whole programs to new environments simply by bringing the appropriate Scheme along. That doesn't help library programmers much, though, and that's where R7RS-small, the latest Scheme definition, comes in. It's not widely implemented yet, but it provides a larger common core than R5RS.
I know that both Eiffel (the progenitor) and Racket both to implement "Design by Contract" features. Sadly, I am not sure how one would different from the other. Eiffel's DBC is reliant on the OOP paradigm and inheritance, but how would Racket, a very different language account for such a disparity?
Racket's main claim to contract fame is the notion of blame, and dealing with ho function is a big part of that for everyday Racket programming, definitely.
You might also want to check out the first two sections of this paper:
http://www.ccs.neu.edu/scheme/pubs/oopsla01-ff.pdf
First of all, your best source of information at this point is the Racket Guide, which is intended as an introductory text rather than a reference manual. Specifically, there is an extensive chapter about contracts that would help. EDIT: Also see the paper that Robby pointed at, he's the main Racket contract guy.
As for your question -- I don't know much about the Eiffel contract system, but I think that it precedes Racket's system. However (and this is again an "IIRC") I think that Racket's contract system was the first one that introduced higher order contracts. Specifically, when you deal with higher order functions assigning proper blame gets a little more complicated -- for example, if you take a foo function that has a contract of X? -> Y? and you send it a value that doesn't match X? then the client code that sent this value to foo is blamed. But if your function is (X? -> Y?) -> Z? and the X? predicate is not satisfied, then the blame goes to foo itself, not to the client (and if Y? is not satisfied then the blame is still with the client).
I think you're asking, how could a contract system work without OOP and inheritance? As a user of Racket who is unfamiliar with Eiffel, I'm wondering why a contract system would have anything to do with OOP and inheritance. :)
On a practical level I think of Racket contracts as a way to get some of the benefits of static type declarations, while keeping the flexibility of dynamically typed languages. Plus contracts go beyond just types, and can fill the role of asserts.
For instance I can say a function requires one argument that is an exact integer ... but also say that it should be an exact positive integer, or a union of certain specific values, or in fact any arbitrarily complicated test of the passed value. In this way, contracts in Racket combine what you might do with both (a) type declarations and (b) assertions in say C/C++.
One gotcha with contracts in Racket is that they can be slow. One way to deal with this is to use them at first while developing, then remove them selectively especially from "inner-loop" types of functions. Another approach I've tried is to turn them on/off wholesale: Make a pair modules like contracts-on.rkt and contract-off.rkt, where the latter provides some do-nothing macros. Have your modules require a contracts.rkt, which provides all from either of the -on or -off files. This is like compiling in DEBUG vs RELEASE mode.
If you're coming from Eiffel maybe my C/C++ slant on Racket contracts won't be helpful, but I wanted to share it anyway.
Racket is a descendant of Scheme. How is Racket different than R6RS? What did it add, or take away, or is just different?
I understand that Racket is more than a language, it's a platform for languages. But I'm referring to the main Racket dialect.
Racket is ultimately based on R5RS, and not R6RS and not a strict superset of either. I don't think it can be called 'Scheme' because it's not backwards compatible with any Scheme standard.
Most implementations offer extensions, but are otherwise backwards compatible, of course, the compiler that comes with Racket can also run in R5RS or R6RS mode. Valid R5/6RS Scheme that runs in racket mode may either be rejected, cause runtime errors, or behave differently than it should. With that said, the main points where it is not backwards compatible are:
Racket has no set-cdr! and set-car!, rather set-mcar! which only works on pairs specifically created as mutable.
What Racket calls letrec is called letrec* in R6RS and doesn't exist in R5RS, what R5RS and R6RS call letrec doesn't exist in Racket.
In Racket, a lot of things are self-evaluating which would raise an error in R5RS, most importantly the empty list.
Racket is case sensitive, though R6RS is also case sensitive
Racket treats ( ... ) and [ ... ] as equivalent, R5RS does not, but R6RS does.
There are probably more, but on most other parts racket is a superset of Scheme.
It contains immutable lists, as mentioned above. It also contains a structure system that is a bit cleaner than the R6RS record system. It has an object oriented class and object system. It has native support for design by contract. It has a unit system reminiscent of the ML module system, as well as a module system much like the R6RS module system. I'm sure I've forgotten as many things as I've mentioned.
I'm not sure that the rename was useful as anything other than a marketing gimmick, but racket is definitely a distinct dialect of scheme.
The rationale for the name-change from PLT Scheme to Racket is discussed on the Racket site.
The language specification R5RS on the Scheme programming language is based on consensus between the multiple Scheme implementors. This imply that the language is very stable. It also implies that many useful features are not part of the R5RS standard.
Racket has built upon R5RS and extended it greatly. Some extensions are defined as macros, but some features require the support of the runtime system.
Features in Racket not implementable by macros alone:
delimited continuations (more general than call/cc)
continuation marks
threads
places
ffi
The module and macro system are much more general than the RnRS specification.
Together with #lang reader/language specification makes it possible to define custom languages (with custom syntax) and use them with normal Racket programs.
In a few cases Racket has constructs whose behaviour deviates from R5RS. The most obvious one is making cons construct an immutable pair (mcons constructs a mutable pair). One advantage of a having immutable pairs, is that length now runs in O(1) amortized time.
Racket includes a lot of really nice language constructs not included in R6RS scheme, like "match".
For one big example, Racket lists are immutable by default whereas Scheme's are mutable. Racket also includes a lot of standard libraries (e.g. Web Server) that other Schemes do not.