|
|
 |
 |
 |
 |
Scheme Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
Feeling a bit disturbed by the direction scheme is going
Ok, I've only been using scheme for about 4 months now, so I'm a bit new at it. I have over 30 years experience programming, in languages like Basic, COBOL, C, X86 Assembler, C++, C#, FORTRAN, etc., but this is my first "functional" language. I'm having lots of fun, and was very drawn to the "simplicity" of the syntax. I like the "it just works" mentality. To quote the first paragraph of the various RnRS reports: "Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary." Unfortunately, I am disturbed by a trend that I am seeing in the newer revisions of scheme. Here is what I mean: The most recent report defines lists and vectors. It defines for-each and map to work with lists, and vector-for-each and vector-map to work with maps. It defines length to work with lists, and vector-length to work with vectors. Why have separate forms for vectors? Wouldn't it be simpler just to have for-each, map, and length know that they are working with vectors and "do the right thing"? Since data is typed, that should be easy. Also, you have "> = < >= <=" for numbers, string=?, string<=?, etc. for strings, char=?, char<=? for chars, etc.. Couldn't these also be folded into a single set of forms? So my question is: Are others disturbed by this "explosion of seemingly unnecessary clutter" as well, or perhaps am I missing some "big picture" that makes this all OK? Brian. --
Hi Brian, Interesting observations. I have nowhere near your experience and am just learning Scheme. Take my comments within that context. BTW - I really love Scheme. I get frustrated a lot by having to check the type of an object before applying a procedure. Even more so when some comparison operations fall over (error) while others don't but then don't give the result I was expecting. (equal? 1 "1") ; ==> #f which is what I would expect (eq? 1 "1") ; ==> #f which is what I expect (equal? 1 #\1) ;==> #f what I'd expect since the first argument is a numeric value while the second is a character. (eq? "1" "1"); ==> #f what I now know but not what I first expected. I mean, these are the same string literals. I'm not clever enough to know what is sitting under the hood but to me, something simple like = should specifically mean are these two things the same (irrespective of what type they are). =, eq? char=?, string=?, equal? etc ... from a coding perspective I want to see if the two objects are the same, nothing else. Perhaps there are very good reasons for having each of these different procedures but it escapes me. Further, it makes it a bit more difficult to write "once use many code" - but that may have more to do with my skill with Scheme than the language itself. I'm guessing the reason for these different 'flavours' of comparison operations lies in the history of the language itself. Even though I am relatively unskilled, I can see that I can create very diverse object types on the fly. Still, simplicity and clarity have value. Irrespective of the objects in question I want to know if object x is the same as object y. Nothing more. I'll deal with the contents of the objects in the code. I'm not there yet, but I can see that it should be possible to roll your own comparison procedures that do what I want. And I can see that if '=' was really '= ' across all objects, it may break previously working code. So to answer your question - I can't be disturbed by an explosion of anything when I have no other experience of this language other than what I have now. However, I'd personally prefer some simplification of basic procedures so they do what I want them too. And I can also see the potential harm that a change like this may have on previously stable code. So ... not an answer but an awareness that if this was really something I wanted, then I need to roll my own comparison operations. Kindest regards, Mike "Brian C. Barnes" <bcbar@austin.rr.com> wrote in message news:46412fe9$0$9960$4c368faf@roadrunner.com... | Ok, I've only been using scheme for about 4 months now, so I'm a bit | new at it. I have over 30 years experience programming, in languages | like Basic, COBOL, C, X86 Assembler, C++, C#, FORTRAN, etc., but this | is my first "functional" language. | | I'm having lots of fun, and was very drawn to the "simplicity" of the | syntax. I like the "it just works" mentality. To quote the first | paragraph of the various RnRS reports: | | "Programming languages should be designed not by piling | feature on top of feature, but by removing the weaknesses | and restrictions that make additional features appear necessary." | | Unfortunately, I am disturbed by a trend that I am seeing in the newer | revisions of scheme. Here is what I mean: | | The most recent report defines lists and vectors. It defines for-each | and map to work with lists, and vector-for-each and vector-map to work | with maps. It defines length to work with lists, and vector-length to | work with vectors. | | Why have separate forms for vectors? Wouldn't it be simpler just to | have for-each, map, and length know that they are working with vectors | and "do the right thing"? Since data is typed, that should be easy. | | Also, you have "> = < >= <=" for numbers, string=?, string<=?, etc. for | strings, char=?, char<=? for chars, etc.. Couldn't these also be folded | into a single set of forms? | | So my question is: Are others disturbed by this "explosion of seemingly | unnecessary clutter" as well, or perhaps am I missing some "big | picture" that makes this all OK? | | Brian. | | -- |
Brian C. Barnes wrote: > Why have separate forms for vectors? Wouldn't it be simpler just to > have for-each, map, and length know that they are working with vectors > and "do the right thing"? Since data is typed, that should be easy.
It is easy. In fact, you could write it yourself, testing for the type of the input and invoking the appropriate type-specific procedure. But not everyone wants all code to be generic in this way. If you have the type-specific procedures, you can build generic procedures using them, but doing it the other way around doesn't make sense. > Also, you have "> = < >= <=" for numbers, string=?, string<=?, etc. for > strings, char=?, char<=? for chars, etc.. Couldn't these also be folded > into a single set of forms?
Yes, they could, and some are, such as eqv? and equal?. But the same argument given above applies here. BTW, all these procedures existed in R5RS too, and earlier, so this isn't a new trend. > So my question is: Are others disturbed by this "explosion of seemingly > unnecessary clutter" as well, or perhaps am I missing some "big > picture" that makes this all OK?
The big picture is that Scheme provides building blocks which you can use to build systems that deal with these things in different ways. If you're looking for something higher-level (more generic or automatic) than these core Scheme procedures, there are various choices available. For example, many implementations provide a generic functions feature, which allows you to overload the same procedure name for multiple data types. The (Tiny)CLOS object system is a well-known example of this. There are also various more traditional object systems available for Scheme, which take a different approach to overloading names. Some are class-based, others are prototype-based. If the core Scheme operations were all generic, it would make building some of these systems more difficult, because it would often be necessary to work around and/or hide the generic behavior to get the desired functionality. The monomorphic procedures are the most basic kind, suitable for use as building blocks. Anton
On Tue, 08 May 2007 21:20:26 -0500, Brian C. Barnes <bcbar @austin.rr.com> wrote: > So my question is: Are others disturbed by this "explosion of seemingly > unnecessary clutter" as well, or perhaps am I missing some "big > picture" that makes this all OK? If you think that's bad, check out R6RS. Hah! The reactions I get from people on this latest revision are usually "it's okay," or, "Scheme is going to die, crash and burn from this broken piece of trash." [1] I imagine that the procedures you mentioned, because they are limited to a speciffic type are easier to make faster in an implementation because you do in fact have the ability to streamline them and remove type checks. On the other hand, I don't really know, since I can't imagine it would be that big a deal, since normally a type check is done anyways. -- Aaron Hsu <aaron.@sacrificumdeo.net> "No one could make a greater mistake than he who did nothing because he could do only a little." - Edmund Burke
On Tue, 08 May 2007 23:57:06 -0500, Aaron Hsu wrote: > I imagine that the procedures you mentioned, because they are limited to a > speciffic type are easier to make faster in an implementation because you > do in fact have the ability to streamline them and remove type checks. On > the other hand, I don't really know, since I can't imagine it would be > that big a deal, since normally a type check is done anyways.
Caveat: I've only been using scheme for a couple of months, too, but it seems pretty clear to me: It's not so much a question of type checking as dynamic dispatch. The type-specific functions that scheme has make sense in that they only do one thing (as described in the function definition). Well, that's not quite true in that numbers can be quite different animals, on implementations with a full numeric stack, but by and large... To get the sort of dynamic dispatch that the OP asked for, you need a language that is "objects all the way down", and historically, Scheme has not been that. On the other hand, common lisp claims to be objects all the way down, and it still requires string< vs <, so maybe it's a cultural thing. Cheers, -- Andrew
In article <tZb0i.35497$M.8@news-server.bigpond.net.au>,
"Mike" <mcu87 @bigpond.net.au> wrote: > Hi Brian, > Interesting observations. I have nowhere near your > experience and am just learning Scheme. Take my comments > within that context. > BTW - I really love Scheme. I get frustrated a lot by > having to check the type of an object before applying a > procedure. Even more so when some comparison operations > fall over (error) while others don't but then don't give the > result I was expecting. > (equal? 1 "1") ; ==> #f which is what I would expect > (eq? 1 "1") ; ==> #f which is what I expect > (equal? 1 #\1) ;==> #f what I'd expect since the first > argument is a numeric value while the second is a character. > (eq? "1" "1"); ==> #f what I now know but not what I first > expected. I mean, these are the same string literals.
Scheme strings are mutable so they are not the same literal. Usually if a string-like unique value is desired a symbol is used. > I'm not clever enough to know what is sitting under the hood > but to me, something simple like = should specifically mean > are these two things the same (irrespective of what type > they are). > =, eq? char=?, string=?, equal? etc ... from a coding > perspective I want to see if the two objects are the same, > nothing else.
Ahh, the semantics of "same". Are some "scripting" languages correct for equating the string "1" to the integer 1, and others incorrect? Is "1" + 1 => 2 and "1" + "1" => "11" the catholic interpretation and all others heresy? I don't mean to be-little you just to point out that "same" & "correct" are a little like beauty. (eqv? 1 1.0) ;=> #f (= 1 1.0) ;=> #t The above does make sense. The 2 kinds of numbers are not really equivalent objects but they are equivalent numbers. A better grouping would be: eq?, eqv?, equal? ; "object" equivalence =, char=?, string=? ; "value" equivalence > Perhaps there are very good reasons for having each of these > different procedures but it escapes me. Further, it makes > it a bit more difficult to write "once use many code" - but > that may have more to do with my skill with Scheme than the > language itself.
Umm, I think you are talking about "generic" algorithms, built from "generic" operations. This is difficult in Scheme since it has few "generic" operations. There is no "one, true" method to achieve this with Scheme. However it is done. One method is to pass procedures with the same signature to a "generic" procedure - a procedure parameter for every unique operation. Its is not a coincidence that list-ref, string-ref, & vector-ref have a similar signature: (X-ref Obj Idx) -> Obj. (This observation doesn't scale over all the possible operations but is still a useful technique.)
> I'm guessing the reason for these different 'flavours' of > comparison operations lies in the history of the language > itself. Even though I am relatively unskilled, I can see > that I can create very diverse object types on the fly. > Still, simplicity and clarity have value. Irrespective of > the objects in question I want to know if object x is the > same as object y. Nothing more. I'll deal with the > contents of the objects in the code. > I'm not there yet, but I can see that it should be possible > to roll your own comparison procedures that do what I want. > And I can see that if '=' was really '= ' across all > objects, it may break previously working code. > So to answer your question - I can't be disturbed by an > explosion of anything when I have no other experience of > this language other than what I have now. However, I'd > personally prefer some simplification of basic procedures so > they do what I want them too. And I can also see the > potential harm that a change like this may have on > previously stable code. So ... not an answer but an > awareness that if this was really something I wanted, then I > need to roll my own comparison operations.
If you want type-generic operations in Scheme you must roll-your-own. In practice though it is rarely needed. Still, their absence is annoying. <snip>
In article <pan.2007.05.09.08.02.31.434@areilly.bpc-users.org>, Andrew Reilly <andrew-newsp@areilly.bpc-users.org> wrote:
> On Tue, 08 May 2007 23:57:06 -0500, Aaron Hsu wrote: > > I imagine that the procedures you mentioned, because they are limited to a > > speciffic type are easier to make faster in an implementation because you > > do in fact have the ability to streamline them and remove type checks. On > > the other hand, I don't really know, since I can't imagine it would be > > that big a deal, since normally a type check is done anyways. > Caveat: I've only been using scheme for a couple of months, too, but it > seems pretty clear to me: > It's not so much a question of type checking as dynamic dispatch. The > type-specific functions that scheme has make sense in that they only do > one thing (as described in the function definition). Well, that's not > quite true in that numbers can be quite different animals, on > implementations with a full numeric stack, but by and large... > To get the sort of dynamic dispatch that the OP asked for, you need a > language that is "objects all the way down", and historically, Scheme has > not been that. > On the other hand, common lisp claims to be objects all the way down, and > it still requires string< vs <, so maybe it's a cultural thing.
Sort of a "cultural thing". The < operator implies a total ordering over the domain but such a thing isn't clear for strings (vectors, etc.) whereas it is clear for the reals. Is "A" < "a"? Really, always, everywhere? The number of variations on string ordering defeat a meaning for < similar to that for numbers. Also what does "..." < # mean? Error? False? But one could still have a "generic" greater-than operator, just accepting that the semantics will be rather ad-hoc. It would be useful to have "123" < 124, "A" < "a", etc. but please do not use the '<' symbol for this operation. Maybe '?<?' gets the meaning across.
|
 |
 |
 |
 |
|