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
Shriram
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
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
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.
[...]
> 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
--
Jay McCarthy <j...@cs.byu.edu>
Assistant Professor / Brigham Young University
http://teammccarthy.org/jay
"The glory of God is Intelligence" - D&C 93
-----
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
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
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
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
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
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
FWIW (and this will be unsurprising to some), I'm against that change.
Robby
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))