Re:Common Lisp, Clojure and Evolution
by mahmud on Sunday February 27, 2011 @10:49AM
(#2268017)
Clojure struct constructor needs keywords badly. Right now it's position-dependent and only way to know what each sub-expression is doing is to look up the definition of the structure.
(struct person 6.3 63 63)
What do the magic numbers mean? Dunno, you need to look up defstruct definition. In Common Lisp, it's:
"Clojure doesn’t have the parse-integer function, but I was quickly able to implement something that did the job by calling out to the Java parseInt method."
This has to be remedied. You need to have native control over basic reading/writing; don't offshore that to another language, even one your language is implemented on-top of.
I agree with the sentiment against ASH (Arithmetic-SHift); seriously, division/multiplication as 2^N shifts is a performance hack, and a useless one at that (smart compilers already do this, and stupid ones are bytecode compilers.)
Common Lisp already has about 9 division operators (yes, NINE) and it would have been a good opportunity to introduce them and their various uses. They are: /, floor, ffloor, ceiling, fceiling, truncate, ftruncate, round, fround -- for integers and floats respectively[1], along with MOD and REM
[1] excellent candidates for removal in future CL with CLOS-based type hierarchy; type-dispatch ftw! With ML-style type annotations it would even be feasible to do type hints inline, like (values (/@double-float 22 7) (/@int 22 7)) using @ because colon is a package separator.
Re:Common Lisp, Clojure and Evolution
by gcv on Sunday February 27, 2011 @01:06PM
(#2268375)
First of all, Clojure has struct-map, which supports keywords, much like default Common Lisp struct constructors.
Second, Clojure's defstruct is on its way out. defrecord provides similar functionality with far better performance. By default, however, it does have the positional-arguments-only flaw. My personal favorite workaround is a small macro from this post: http://groups.google.com/group/clojure/msg/5206fac13144ea99
No comment about numerical operations in Clojure: it's a sensitive topic. :)
Re:Common Lisp, Clojure and Evolution
by whateverer on Sunday February 27, 2011 @04:21PM
(#2269006)
Here: http://clojure.org/data_structures, see the entry for StructMaps. The page on datatypes* also implies heavily that structs have been phased out in favor of records, as no reason to use structs over records is presented.
Re:Common Lisp, Clojure and Evolution
by jb3 on Sunday February 27, 2011 @12:17PM
(#2268250)
Christophe Grand pointed out in the comments that a plain map should be used instead of a struct, so your example in Clojure would be:
{:height 6.3 :age 63 :weight-in-kg 63}
Re:Common Lisp, Clojure and Evolution
by mahmud on Sunday February 27, 2011 @01:12PM
(#2268399)
That works in the short term, but beyond that, Clojure will need to resolve that issue.
Records are not the same thing as hash-tables. A record, or struct, is a single unit value, while a hash-table, or map, is an aggregate container. There is an implicit contract in place; a record is guaranteed to have JUST the fields it's defined to have, while a map can grow at run time (are you going to test for the fields you want and ignore the rest? quack quack! you can't add fields to a record at runtime, so the two are NOT interchangeable. Equality is a transitive relation, while duck-typing is not.)
A record is a generalization of the concept of "value" beyond data types immediately representable by machine. While a hash-table is a generalization of arrays, an aggregate of values, addressable by an index (hash-tables remedy the silly assumption that an index must be of an integral value.)
To give an analogy; it's like asking what's the best way to group a bunch of papers (folder, envlope, binder) and then hearing someone suggest "bookshelf!".
Again, OK short-term, but stinks. Fix the structs; even C has dot and arrow notations, making the field names clear.
Re:Common Lisp, Clojure and Evolution
by w01fe on Sunday February 27, 2011 @07:03PM
(#2269397)
Almost. Record types are checked as part of Clojure's "=", but not as part of Java's ".equals". See [1] and linked material. This means that Foo{:x 1} and Bar{:x 1} will collide in sets and as map keys (of Clojure or Java varieties). This seems a bit icky to me, but seems to be intentional.
Re:Common Lisp, Clojure and Evolution
by lukev on Sunday February 27, 2011 @03:57PM
(#2268934)
Records also provide better performance than hash tables for their defined keys.
You can think of them as a Java class that has certain fields (it's named fields) and also implements the Map interface for additional expandability. Records provide "accessor" methods for their named fields that provide bare-metal JVM performance.
"Clojure doesn’t have the parse-integer function, but I was quickly able to implement something that did the job by calling out to the Java parseInt method."
This has to be remedied. You need to have native control over basic reading/writing; don't offshore that to another language, even one your language is implemented on-top of.
I agree with the sentiment against ASH (Arithmetic-SHift); seriously, division/multiplication as 2^N shifts is a performance hack, and a useless one at that (smart compilers already do this, and stupid ones are bytecode compilers.)
Common Lisp already has about 9 division operators (yes, NINE) and it would have been a good opportunity to introduce them and their various uses. They are: /, floor, ffloor, ceiling, fceiling, truncate, ftruncate, round, fround -- for integers and floats respectively[1], along with MOD and REM
[1] excellent candidates for removal in future CL with CLOS-based type hierarchy; type-dispatch ftw! With ML-style type annotations it would even be feasible to do type hints inline, like (values (/@double-float 22 7) (/@int 22 7)) using @ because colon is a package separator.
Second, Clojure's defstruct is on its way out. defrecord provides similar functionality with far better performance. By default, however, it does have the positional-arguments-only flaw. My personal favorite workaround is a small macro from this post: http://groups.google.com/group/clojure/msg/5206fac13144ea99
No comment about numerical operations in Clojure: it's a sensitive topic. :)
And yes, that flaw is icky; one of the few in Hickey's otherwise excellent track-record in good taste.
* http://clojure.org/datatypes
Records are not the same thing as hash-tables. A record, or struct, is a single unit value, while a hash-table, or map, is an aggregate container. There is an implicit contract in place; a record is guaranteed to have JUST the fields it's defined to have, while a map can grow at run time (are you going to test for the fields you want and ignore the rest? quack quack! you can't add fields to a record at runtime, so the two are NOT interchangeable. Equality is a transitive relation, while duck-typing is not.)
A record is a generalization of the concept of "value" beyond data types immediately representable by machine. While a hash-table is a generalization of arrays, an aggregate of values, addressable by an index (hash-tables remedy the silly assumption that an index must be of an integral value.)
To give an analogy; it's like asking what's the best way to group a bunch of papers (folder, envlope, binder) and then hearing someone suggest "bookshelf!".
Again, OK short-term, but stinks. Fix the structs; even C has dot and arrow notations, making the field names clear.
I will announce this great news to a few of my closest friends :-)
[1] http://dev.clojure.org/jira/browse/CLJ-736
You can think of them as a Java class that has certain fields (it's named fields) and also implements the Map interface for additional expandability. Records provide "accessor" methods for their named fields that provide bare-metal JVM performance.