[racket] Interesting article

46 views
Skip to first unread message

Eduardo Bellani

unread,
Aug 11, 2010, 12:46:47 PM8/11/10
to Racket mailing list
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

http://programming-puzzler.blogspot.com/2010/08/racket-vs-clojure.html

Any opinions on the subject?

- --
Eduardo Bellani

omnia mutantur, nihil interit.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkxi0/cACgkQSbLl0kCTjGnfxQCfTNJwqzEZKeStOgwoIUsqiRnr
HLoAn3r0zWwINnluhSzwDqqCwN0qbssX
=KaS5
-----END PGP SIGNATURE-----
_________________________________________________
For list-related administrative tasks:
http://lists.racket-lang.org/listinfo/users

Hari Prashanth

unread,
Aug 11, 2010, 3:02:17 PM8/11/10
to Eduardo Bellani, Racket mailing list

We are in the process of releasing a library of functional
data structures that has been pointed out to be missing from
Racket. It will answer many concerns raised there effectively.
FYI as a first step we will be releasing it to PlaneT in next
2 to 3 days.

Hari

Shriram Krishnamurthi

unread,
Aug 11, 2010, 3:14:36 PM8/11/10
to Hari Prashanth, Racket mailing list
Your library is truly impressive, but I don't think it addresses some
of the fundamental issues that the OP talks about (availability in the
core and not as some third-party library, integration with syntax,
good integration of laziness). Maybe you could comment more
specifically, in case I've missed these issues from your
documentation.

Shriram

Hari Prashanth

unread,
Aug 11, 2010, 3:58:21 PM8/11/10
to Shriram Krishnamurthi, Racket mailing list
Thank you. Yes you are right it is not in the core yet and its just
a third party library. But we would want like to move some of the
more useful ones to the core. I didn't comment about it because
I don't know what it would be eventually. So I stopped myself.

Martin DeMello

unread,
Aug 11, 2010, 6:01:04 PM8/11/10
to Shriram Krishnamurthi, Racket mailing list
On Thu, Aug 12, 2010 at 12:44 AM, Shriram Krishnamurthi <s...@cs.brown.edu> wrote:
> Your library is truly impressive, but I don't think it addresses some
> of the fundamental issues that the OP talks about (availability in the
> core and not as some third-party library, integration with syntax,
> good integration of laziness).  Maybe you could comment more
> specifically, in case I've missed these issues from your
> documentation.

What is the racket team's stance on core support for vectors and
hashes, in terms of syntax for literals and making containers act as
functions of their keys? The latter, in particular, would be a huge
win, though it would also be a pretty large change to the language -
I'm interested in what people feel the pros and cons of having it
included would be, independent of the implementation difficulty.

martin

Jay McCarthy

unread,
Aug 11, 2010, 6:09:20 PM8/11/10
to Martin DeMello, Racket mailing list, Shriram Krishnamurthi
On Wed, Aug 11, 2010 at 4:01 PM, Martin DeMello <martin...@gmail.com> wrote:
> What is the racket team's stance on core support for vectors and
> hashes, in terms of syntax for literals and making containers act as
> functions of their keys? The latter, in particular, would be a huge
> win, though it would also be a pretty large change to the language -
> I'm interested in what people feel the pros and cons of having it
> included would be, independent of the implementation difficulty.

There is literal syntax for vectors and hashes:

> (vector 1 2 3)
'#(1 2 3)
> > (hash 1 2)
'#hash((1 . 2))
> (hasheq 1 2)
'#hasheq((1 . 2))
> (hasheqv 1 2)
'#hasheqv((1 . 2))
> (vector-ref `#(1 ,(add1 2) 4) 1)
3

I'm theoretically in favor of containers as standard "ref" functions.
This would be pretty easy to implement [1] although it would slow
everything down.

Many of this person's complaints seem to indicate that they aren't
familiar with the dict or sequence APIs and that those APIs are not
complete enough.

Jay

1. The VM would provide vectors, etc, but they would be exposed to
#lang racket as structs with the prop:procedure property.

--
Jay McCarthy <j...@cs.byu.edu>
Assistant Professor / Brigham Young University
http://teammccarthy.org/jay

"The glory of God is Intelligence" - D&C 93

Deren Dohoda

unread,
Aug 11, 2010, 6:44:28 PM8/11/10
to Eduardo Bellani, Racket mailing list
I am a novice, self-taught programmer. Please forgive this possibly
naive question, but what's the problem? The big post I read seems to
say this one sentence: different containers are different, but they
should act the same.

But, different containers are different for a good reason.

Take a linked list. "map" is a well-known operation, taking a
procedure and a list, and returning a (possibly fresh) list with proc
applied to every element of the original list. Now, take a vector.
What does map mean? I can't answer this question.

1) Well, you chose a vector because it is mutable, so map should
really be something like map! and return void
2) Well, you chose a vector because it is random-access, so this one
exceptional O(n) operation should return a vector for otherwise
random-access use
3) Well, you only do something to every element as processing for more
doing-something-to-every-element so it should return a list with
better filter behavior
4) Well, *I* have no clue what you want, so I'll just create this view
called a "sequence" and give you that (oh yeah it just acts like a
list)
5) Well, *I* have no clue what you want, so I'll just leave it up to
you to make your own map-like function

I can't pick between 1 through 3, because I don't know why someone is
doing something to every element of a vector (curiosity: why didn't
they use a list in the first place?). I don't believe (4) is so much a
"solution" as a way to relocate the problem to post-processing of your
containter-viewed-through-a-sequence rather than pre-processing by
selecting the right function in the first place. (Of course, (5) is
not a solution, either, but a refusal to do anything at all.)

Can someone please elaborate a bit on why this map-vs-vector-map is a
problem? I feel like I am missing something kind of basic here.

Martin DeMello

unread,
Aug 11, 2010, 6:53:35 PM8/11/10
to Deren Dohoda, Racket mailing list
On Thu, Aug 12, 2010 at 4:14 AM, Deren Dohoda <deren....@gmail.com> wrote:
> 4) Well, *I* have no clue what you want, so I'll just create this view
> called a "sequence" and give you that (oh yeah it just acts like a
> list)

[...]

> they use a list in the first place?). I don't believe (4) is so much a
> "solution" as a way to relocate the problem to post-processing of your
> containter-viewed-through-a-sequence rather than pre-processing by
> selecting the right function in the first place.

It's then the compiler's job to specialise your map function for your
container. You get the benefits of conceptually treating the vector as
an abstract sequence, while concretely having your functions
specialised for your specific container, and only having to make the
implementation decision at a single point in the code.

martin

Jay McCarthy

unread,
Aug 11, 2010, 6:57:30 PM8/11/10
to Deren Dohoda, Racket mailing list
I think you are mostly right. There is not an obvious operation like
the list operations for many collections. Nevertheless, we should have
good defaults for making a user's life convenience.

Jay

--

Jay McCarthy <j...@cs.byu.edu>
Assistant Professor / Brigham Young University
http://teammccarthy.org/jay

"The glory of God is Intelligence" - D&C 93

Shriram Krishnamurthi

unread,
Aug 11, 2010, 8:25:10 PM8/11/10
to Deren Dohoda, Racket mailing list
I would venture a guess that it's less about lists vs vectors than
bout lists and vectors versus two other things: "associations" and
"sequences".

-----

Associations:

In many other scripting languages, the distinction between an object,
an association list, a dictionary, and a hash table are all blurred.

Blurring the first of these (objects) with the others is a mistake.
Blurring the other three -- ie, treating everything as a dictionary,
thereby hiding the list representation of an association list, and
leaving it to the run-time system to decide whether or not to
implement things as a hash-table -- strikes me as a win at least for
prototyping.

Even literal-syntactically, hashes work reasonably well:

#hash((a . 5) (b . 7))

is really not much worse than

{a: 5, b: 7}

in the grand scheme of things (and a programmer is always welcome to
implement a reader macro for further convenience).

The lack of an infix syntax for access/set can certainly feel much
more onerous. His vector example is along these lines.

-----

Sequences:

I think one problem when approaching Racket is that, due to the Scheme
legacy, you see an enormous amount of information on lists but not
much else. Some of the data structures like hashes definitely had a
second-class feel them. That is changing with sequences, iterators,
and generators, but:

- The Racket API design seems to value precision (eg, one-valued vs
two-valued) over pure "convenience".

- Sequences still don't feel fully integrated into the language: you
can't pass a sequence where a built-in API might want a list.

- When you read the docs on sequences, hash-tables are listed but sets
aren't. This is because the fine-print talks about *built in* data
structures, which hash-tables are but sets aren't. But it means you
have to remember such stuff.

- The for... forms remind me too much of do. There just don't seem to
be primitives with the simplicity of map/filter/fold for sequences.
Perhaps I'm missing them.

Laziness is a more far-reaching issue. Given that Racket has
generators, perhaps these could be used to build a "lazy" counterpart
to eager sequences: when you know the sequence is finite, and you
intend to visit most or all elements, get a more efficient system by
using the eager versions, otherwise use the lazy ones.

Shriram

Sam Tobin-Hochstadt

unread,
Aug 11, 2010, 10:40:45 PM8/11/10
to Shriram Krishnamurthi, Racket mailing list
On Wed, Aug 11, 2010 at 8:25 PM, Shriram Krishnamurthi <s...@cs.brown.edu> wrote:
>
> - The for... forms remind me too much of do.  There just don't seem to
> be primitives with the simplicity of map/filter/fold for sequences.
> Perhaps I'm missing them.

Personally, I find the `for' macros more concise, except when there's
already a function that I would pass to `map' etc. Compare:

(for/list ([x e]) (f x))
(map (lambda (x) (f x)) e)

I think the bigger problem from a datatype-genericity point of view is
that sequences don't have enough operations (sequence-ref,
sequence-set, etc).
--
sam th
sa...@ccs.neu.edu

Shriram Krishnamurthi

unread,
Aug 11, 2010, 11:06:43 PM8/11/10
to Sam Tobin-Hochstadt, Racket mailing list
> Personally, I find the `for' macros more concise, except when there's
> already a function that I would pass to `map' etc.   Compare:
>
> (for/list ([x e]) (f x))
> (map (lambda (x) (f x)) e)

Your comparison is perhaps a bit unfair (since you've needlessly
eta-expanded the function), but I agree that if the function hasn't
already been written, it's often easier to just "inline" its body.

> I think the bigger problem from a datatype-genericity point of view is
> that sequences don't have enough operations (sequence-ref,
> sequence-set, etc).

I think that's right. It's also the case they aren't admitted all the
places in the core that lists are, right?

Shriram

Jay McCarthy

unread,
Aug 11, 2010, 11:55:45 PM8/11/10
to Sam Tobin-Hochstadt, Racket mailing list, Shriram Krishnamurthi
On Wed, Aug 11, 2010 at 8:40 PM, Sam Tobin-Hochstadt <sa...@ccs.neu.edu> wrote:
> On Wed, Aug 11, 2010 at 8:25 PM, Shriram Krishnamurthi <s...@cs.brown.edu> wrote:
>>
>> - The for... forms remind me too much of do.  There just don't seem to
>> be primitives with the simplicity of map/filter/fold for sequences.
>> Perhaps I'm missing them.
>
> Personally, I find the `for' macros more concise, except when there's
> already a function that I would pass to `map' etc.   Compare:
>
> (for/list ([x e]) (f x))
> (map (lambda (x) (f x)) e)
>
> I think the bigger problem from a datatype-genericity point of view is
> that sequences don't have enough operations (sequence-ref,
> sequence-set, etc).

I am in the middle of adding many more sequence functions to
correspond to list functions.

Jay

> --
> sam th
> sa...@ccs.neu.edu
> _________________________________________________
>  For list-related administrative tasks:
>  http://lists.racket-lang.org/listinfo/users
>

--

Jay McCarthy <j...@cs.byu.edu>
Assistant Professor / Brigham Young University
http://teammccarthy.org/jay

"The glory of God is Intelligence" - D&C 93

Sam Tobin-Hochstadt

unread,
Aug 12, 2010, 7:57:16 AM8/12/10
to Shriram Krishnamurthi, Racket mailing list
On Wed, Aug 11, 2010 at 11:06 PM, Shriram Krishnamurthi <s...@cs.brown.edu> wrote:
>> Personally, I find the `for' macros more concise, except when there's
>> already a function that I would pass to `map' etc.    Compare:
>>
>> (for/list ([x e]) (f x))
>> (map (lambda (x) (f x)) e)
>
> Your comparison is perhaps a bit unfair (since you've needlessly
> eta-expanded the function), but I agree that if the function hasn't
> already been written, it's often easier to just "inline" its body.

I was just trying to use a placeholder expression here - I agree that
when you're just mapping `f' over a list, `map' is more convenient.

>> I think the bigger problem from a datatype-genericity point of view is
>> that sequences don't have enough operations (sequence-ref,
>> sequence-set, etc).
>
> I think that's right.  It's also the case they aren't admitted all the
> places in the core that lists are, right?

Yes, but that's an architectural change that would be much harder to
make. In particular, the whole concept of sequences is a library,
making it difficult or impossible to use it in the true "core".
--
sam th
sa...@ccs.neu.edu

Jay McCarthy

unread,
Aug 12, 2010, 8:34:06 AM8/12/10
to Sam Tobin-Hochstadt, Racket mailing list, Shriram Krishnamurthi
Follow-up with a few more details... I will add:

rename to hash-keys/values
dict functions for the hash functions I added
vector-set*!
sequence-cons, sequence-empty, sequence-filter, etc
for/sequence

Also, I thought of a better way than prop:procedure to get containers
to implicitly ref... we could change apply and #%app. I don't think it
would be slower because the code would already be on the slow 'error'
path, but I don't have a strong opinion on if it is a good idea, so I
don't plan on trying it out until further discussion.

Jay

Robby Findler

unread,
Aug 12, 2010, 9:02:38 AM8/12/10
to Jay McCarthy, Racket mailing list, Shriram Krishnamurthi, Sam Tobin-Hochstadt
On Thu, Aug 12, 2010 at 8:34 AM, Jay McCarthy <jay.mc...@gmail.com> wrote:
> Also, I thought of a better way than prop:procedure to get containers
> to implicitly ref... we could change apply and #%app. I don't think it
> would be slower because the code would already be on the slow 'error'
> path, but I don't have a strong opinion on if it is a good idea, so I
> don't plan on trying it out until further discussion.

FWIW (and this will be unsurprising to some), I'm against that change.

Robby

Noel Welsh

unread,
Aug 12, 2010, 9:42:09 AM8/12/10
to Eduardo Bellani, Racket mailing list
I agree with most of his gripes. Addressing his points about vectors,
I have a fairly extensive library of vectors functions on github

http://github.com/noelwelsh/numeric

It has the same API for vector, evector [extensible vector], and
f64vector. It could easily be extended to flvector but I haven't yet
had the need/time. (Nor the time to properly package it.) I regularly
write numeric algorithms (e.g. discrete cosine transform, which I
wrote yesterday) in a functional system using this library.

The code is written using a compile-time unit system, which is well
...err... something.

API is below in case anyone is interested.

N.

(define-comprehensions
(import 'vector
'in-vector
make-vector
vector?
vector-ref
vector-set!
vector-length)
(export for/vector
for/fold/vector
_
in-vector-reverse))

;;; Constructors

(define-constructors
(import make-vector
for/vector
in-vector
vector-length)
(export vector-ones
vector-zeros
vector-copy
vector-reverse))

;;; Predicates

(define-predicates
(import in-vector vector-length)
(export vector-null? vector-=))

;;; Selectors

(define-selectors
(import for/vector for/fold/vector in-vector vector-ref
vector-length list->vector)
(export vector-select
vector-last
vector-find vector-findi
vector-find-first vector-find-firsti
vector-slice))

;;; Mutators

(define-mutators
(import vector-ref vector-set!)
(export vector-add1! vector-sub1!))

;;; Iterators

(define-iterators
(import for/fold/vector for/vector
in-vector
vector-length)
(export vector-map vector-mapi
vector-fold vector-foldi))

;;; General Functions

(define-functions
(import for/vector
in-vector
vector-set!
vector-ref
vector-length
vector-find-firsti)
(export vector* vector+ vector/ vector-
vector*s vector/s vector+s vector-s
vector-sum vector-product
vector-dot
vector-normalise
vector-max vector-maxi vector-min vector-mini
vector-adjoin vector-append
vector-remove vector-remove-first vector-removei))

Reply all
Reply to author
Forward
0 new messages