I'm new to scheme. I'm wondering how to sort strings in lexicographical order in scheme.
For example:
(sort (list "cat" "apple" "dog"))
(apple cat dog)
In C++, I can have 'A'<'B', but it seems not work in scheme. I have referred online, but most are implemented in popular language, there are very few in scheme. So Can someone provide with an actual code in scheme and explain it? Thank you
An idiomatic answer to this question is going to depend a lot on which scheme implementation you're using. So, for instance, in Racket I would write
(sort (list "cat" "apple" "dog") string<?)
I see that you've tagged this question r5rs, and perhaps you're asking whether you can write this in R5RS scheme. Yes, you definitely can. But it's probably simpler just to use whatever your scheme implementation provides.
Related
I'm new to Scheme and I have a background coding mainly in C++/Java, and a bit of Python. I'm doing exercises in Study and Interpretation of Computer Programs, and I've come across this problem:
The book details the structure of the "if" special form as (if (conditional) (consequent clause) (alternative clause)). However, nothing indicates that an alternative clause MUST be included.
In fact, in the exercise I'm currently stuck on (exercise 1.22, for anyone interested), they provide some code that we are supposed to use in creating a procedure that tests for prime numbers within a given range and gives the amount of time taken to find them.
(define (start-prime-test n start-time)
(if (is-prime n)
(report-prime (- (runtime) start-time))))
This did not work, so I modified it slightly:
(define (start-prime-test n start-time)
(if (is-prime n)
(report-prime (- (runtime) start-time))
(display ""))) ;prints nothing
The first version results in "SchemeError: too few operands..." I modified it to have an alternative clause that essentially does nothing, and I'm no longer getting the error when testing the procedure.
I just want to know whether requiring an alternative clause is standard for most Scheme interpreters, or if it's unique to the one I'm using. I AM currently using two different interpreters, because the first one I used does not include the built-in procedures detailed in the book, so I have noticed there are some major differences in Scheme interpreters. But that's as far as I know, and it's been very hard finding useful information through googling.
Any help would be greatly appreciated; I don't like including "do-nothing" procedures.
In most Scheme interpreters if allows expressions without the "else" part, and that's what the standard says, as pointed by #codybartfast in his answer.
I'm only aware of Racket enforcing the rule that if must always have both the consequent and alternative parts, and it's for a very good reason: it'll help you catch the kind of mistakes that happen when you forget to write the "else" part.
Although it's valid to have if expressions without the alternative part, that only happens when we are writing procedural code (like displaying a result in your example), and that's the kind of programming style we want to avoid when using Scheme (as we favor functional programming).
Having said that, if you're absolutely certain that you want to write procedural code, then you should use when, which doesn't have an else part and unlike if, it can have several expressions inside because it has an implicit begin. This will work:
(define (start-prime-test n start-time)
(when (is-prime n)
(report-prime (- (runtime) start-time))))
I understand R5RS/R6RS are effectively the language standards. They say that the alternate clause is optional:
(if <test> <consequent> <alternate>)syntax
(if <test> <consequent>)syntax
Syntax: <Test>, <consequent>, and <alternate> must be expressions.
Semantics: An if expression is evaluated as follows: first, <test> is
evaluated. If it yields a true value (see section 5.7), then <consequent> is
evaluated and its values are returned. Otherwise <alternate> is evaluated
and its values are returned. If <test> yields #f and no <alternate> is
specified, then the result of the expression is unspecified.
But in 2009 (quite recently for scheme), the language steering commitee said:
Alas: Scheme has the unhappy distinction of being the world's most unportable programming language. It is almost misleading to call Scheme a "programming language;" it would be more accurate to characterise Scheme as a family of dialects, all loosely related by the common features of lexical scope, dynamic typing, list structure, higher-order functions, proper tail-recursion, garbage collection, macros, and (some form of) s-expression based lexical syntax.
So although a formal stanard may exist there seems little expectation that any given implementaion will adhere to that standard. E.g. By default Racket requires the alternate clause. (Although Racket can also support a R6RS compliant dialet.)
Personally I use Racket with the SICP language pack to be consistent with the book.
The one-armed if has indeed been standard in Scheme for a while.
Unfortunately the one-armed if allows one to make a mistake - forgetting the second arm is very easy to do. Some implementations added when and unless to reduce the number of mistakes.
See also: Why is one-armed "if" missing from Racket?
There are many differences between Common Lisp and Scheme such as whether functions and variables share a namespace, whether macros are hygienic, and how strongly functional style is preferred; this shows up in some vocabulary differences such as setq vs set!.
But quite a bit of vocabulary is still shared, such as quote and cons.
I'm looking for a full list of vocabulary shared between the languages. Does such a thing exist?
Alternatively, I could make one myself given the vocabulary of each language, i.e. a list of all the known symbols including language primitives, standard library macros and functions. Do those exist for Common Lisp (as in the standard) and Scheme (as in any RxRS, or failing that, any dialect)?
Get all symbols of Common Lisp:
(sort (loop for sym being each external-symbol of "CL" collect sym)
#'string-lessp)
You are looking for this web page:
http://hyperpolyglot.org/lisp
Whenever I try to use srfi/1 functions like fold and reduce in drracket r5rs language I get an null-list? error. After some research I found that it is due to the fact that the function requires and immutable list but gets a mutable one. How do I create immutable list in r5rs or is this srfi/1 not designed with r5rs in mind?
This is basically reiterating what John said, but it definitely does merit a full answer status. (John, I'll be happy to delete this if you copy this answer verbatim...)
The thing about Racket's R5RS language is that it sticks very strictly to just the R5RS language, and therefore comes with nothing beyond that. (SRFIs could be implemented for the R5RS mutable pairs too, but nobody ever came up with the adapted code.)
In any case, the bottom line here is that R5RS is basically useful only in those rare cases where you want to inflict on yourself the pain of writing using just the basic r5rs language -- which means that you basically can't do much useful things. So especially if you want to get a feel for the language, you'll likely want to play with all kinds of things that go beyond the narrow r5rs world -- and for that you should use #lang racket.
It's also better in terms of "just grokking the language", and you can even apply the same lessons to other Scheme implementations baring in mind that they all come with their own extensions. If you use the limited r5rs language, you'll likely to experience the frustration that comes with such a limited language and this can easily overwhelm any positive experience you might have with it otherwise.
Since the language "racket" uses immutable cons cells, the srfi/1 implementation that comes with the system also uses immutable cons cells.
Since cons cell in R5RS uses mutable cons cells, you can't use the builtin srfi/1 with the R5RS language in DrRacket.
That's is however a small problem.
Download http://srfi.schemers.org/srfi-1/srfi-1-reference.scm and save it in the directory where you have your code.
Open it and insert at the first line:
(define (check-arg . more) #t)
Then in your own code, add the line:
(load "srfi-1-reference.scm")
Now srfi/1 is redefines map (and a few others).
Redefined builtin operations is normally done only
on accident, so the default settings in DrRacket
is to throw an error. Therefore click at the R5RS language
at the bottom left in DrRacket. Choose "Choose language...".
Then click the button "Show Details". The remove the tick
by "Disallow redefinition of initial bindings".
Now the following program runs:
(load "srfi-1-reference.scm")
(fold + 0 '(1 2 3))
and produces 6 as expected.
I imagine Scheme (and perhaps Lisp) could be made more `user friendly' by using a different syntax. For example, instead of nested S-expressions with ugly parentheses, one could devise some kind of syntax closer to some of the more widely used languages (e.g. Java-like without needing to define classes).
It's not necessarily a bad thing if it's more verbose. For example, the syntax may require line separators and commas in the places where many people will expect them, and expect explicit return statements. Also, it doesn't seem that difficult to allow some operators to be used infix style (just obey the generally accepted operator preference rules).
And if it doesn't make things too messy, the syntax could even be backwards-compatible, so that in any place where an expression is expected, a normal S-expression between parentheses can be used.
What are your opinions and ideas about this? And does anything like this exist? (I expect it does, but "Scheme" is a worthless google term, I can't find anything!)
Originally, Lisp was planned to use a syntax called M-Expressions, with S-Expressions being only a transitional solution for easier compiler building. When M-Expressions were ready to be introduces, the programmers who had already taken on Lisp just stayed with what they had become accustomed to, and M-Expressions never caught on.
There is an infix notation in Guile, but it's rarely used. A good Lisp programmer doesn't even see the parens anymore, and prefix notation does have its merits...
I think "sweet expressions" might be one of the more thoughtful approaches to getting rid of the parentheses in Lisp. It apparently even supports macros.
http://www.dwheeler.com/readable/sweet-expressions.html
However, I think most people eventually get over the parentheses or use another language.
Take a look at "sweet-expressions", which provides a set of additional abbreviations for traditional s-expressions. They add syntactically-relevant indentation, a way to do infix, and traditional function calls like f(x). Unlike nearly all past efforts to make Lisps readable, sweet-expressions are backwards-compatible (you can freely mix well-formatted s-expressions and sweet-expressions), generic, and homoiconic.
Sweet-expressions were developed on http://readable.sourceforge.net and there is a sample implementation.
For Scheme there is a SRFI for sweet-expresssions: http://srfi.schemers.org/srfi-110/
Try SRFI 49 for size. :-P
(Seriously, though, as Rafe commented, "I don't think anybody wants this".)
Some people consider Python to be a kind of Scheme with infix notation for operators, algebraic notation for functions and which uses a more "java-like" syntax for representing the language. I don't agree with that assessment, but I can see where the idea comes from.
The big problem with changing the notation for Scheme is that macros become very hard to write (to see how hard, take a look at the Nimrod language or Boo). Instead of working directly with the code as lists, you have to parse the input language first. This usually involves constructing an AST (abstract syntax tree) for the language from the input. When working directly with Scheme, this is unnecessary.
However, you might check out the SIX expression syntax in Gambit Scheme. There's a nice set of slides here which contains a discussion of this:
http://www.iro.umontreal.ca/~gambit/Gambit-inside-out.pdf
But don't tell anyone about it! (The inside joke is that someone suggests writing a Lisp without parentheses and with infix notation about once a day, and someone announces an implementation about once a month.)
There are some languages that do exactly that. For instance: Dylan.
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.