It should be easy to emulate the hash table reader at least in function context, by defining a custom DEFUN-wrapping macro that dispatches either to FUNCALL or to GETHASH depending on the data type.
Is this also possible for the SETF expansion? I think it should be, but I hardly ever use the DEFSETF facilities so I'm not sure how.
That's an old Lisp feature to make some data objects having a functional interpretation. In LML for examples arrays in functional position were evaluated as doing AREF.
> It should be easy to emulate the hash table reader at least in > function context, by defining a custom DEFUN-wrapping macro that > dispatches either to FUNCALL or to GETHASH depending on the data type.
I don't think it is that easy...
> Is this also possible for the SETF expansion? I think it should be, > but I hardly ever use the DEFSETF facilities so I'm not sure how.
On Dec 14, 12:01 pm, "Leslie P. Polzer" <leslie.pol...@gmx.net> wrote:
> Clojure, from what I've gathered, lets one access hash tables just by > referring to them in the CAR of an evaluated form:
> (defparameter ht (make-hash-table))
> (ht 'foo) == (gethash 'foo ht)
Actually I feel that as too verbose: (ht 'foo) ->foo-val would be even better. also I want below too for multiple keys selection: (ht '(foo bar baz)) -> (foo-val bar-val baz-val) and possibly even this: (ht (lambda (key) (like (princ-to-string key) "*-bar"))))
> It should be easy to emulate the hash table reader at least in > function context, by defining a custom DEFUN-wrapping macro that > dispatches either to FUNCALL or to GETHASH depending on the data type.
> Is this also possible for the SETF expansion? I think it should be, > but I hardly ever use the DEFSETF facilities so I'm not sure how.
> On Dec 14, 12:01 pm, "Leslie P. Polzer" <leslie.pol...@gmx.net> wrote:> Clojure, from what I've gathered, lets one access hash tables just by > > referring to them in the CAR of an evaluated form:
> > (defparameter ht (make-hash-table))
> > (ht 'foo) == (gethash 'foo ht)
> Actually I feel that as too verbose: > (ht 'foo) > ->foo-val > would be even better. > also I want below too for multiple keys selection: > (ht '(foo bar baz)) > -> (foo-val bar-val baz-val) > and possibly even this: > (ht (lambda (key) (like (princ-to-string key) "*-bar"))))
> > It should be easy to emulate the hash table reader at least in > > function context, by defining a custom DEFUN-wrapping macro that > > dispatches either to FUNCALL or to GETHASH depending on the data type.
> > Is this also possible for the SETF expansion? I think it should be, > > but I hardly ever use the DEFSETF facilities so I'm not sure how.
> > Leslie
If you want to go that route, why not make $ a default hash-table variable and $foo accesses it. Also write $ht.foo to access hash table ht. Then make $h.f!3 set the hash table h, key f to 3. Not that it would look like Lisp, but it sure saves keystrokes.
> It should be easy to emulate the hash table reader at least in > function context, by defining a custom DEFUN-wrapping macro that > dispatches either to FUNCALL or to GETHASH depending on the data type.
> Is this also possible for the SETF expansion? I think it should be, > but I hardly ever use the DEFSETF facilities so I'm not sure how.
> Leslie
It's not that easy. The problem is, that there is no way to override the syntax of a cl funtion call. You can either have a symbol denoting a function or a lambda expression. You can extend the function call protocol though: By implementing an hashtable or array as a funcallable-instance. You could then use FUNCALL on the hashtable:
(funcall *ht* 1)
The missing part could be a macro which enables writing single- namespace lisp code:
LPP> It should be easy to emulate the hash table reader at least in LPP> function context, by defining a custom DEFUN-wrapping macro that LPP> dispatches either to FUNCALL or to GETHASH depending on the data type.
LPP> Is this also possible for the SETF expansion? I think it should be, LPP> but I hardly ever use the DEFSETF facilities so I'm not sure how.
it is fairly easy to do this for custom binding contstructs. something like this:
if you want to use normal lisp binding constructs, that becomes more tricky. you can do this for special variables one way or another. but for lexical bindings that becomes really hard -- basically you need to modify all binding constructs and inject macros via macrolet that will deal with the case where variable name is used like a function. handling setf wil be even more problematic.. but there is actually have little sense -- essentially that will be not a Common Lisp but some new Lisp-1 dialect [*]. perhaps then just port Clojure (or Arc or whatever) to Common Lisp..
> On Dec 14, 12:01 pm, "Leslie P. Polzer" <leslie.pol...@gmx.net> wrote: >> Clojure, from what I've gathered, lets one access hash tables just by >> referring to them in the CAR of an evaluated form:
>> (defparameter ht (make-hash-table))
>> (ht 'foo) == (gethash 'foo ht) > Actually I feel that as too verbose: > (ht 'foo) > ->foo-val > would be even better.
Let’s say we have two hashmaps: (def h1 {:name "Slobodan" :foo 100 :language "Lisp"}) (def h2 {:name "Slodoban" :foo 200 :language "Perl"})
(print :foo-val) ==> will it print 100 or 200? (print (:foo h1)) ==> prints 100 and is not dramatically much verbose.
> also I want below too for multiple keys selection: > (ht '(foo bar baz)) > -> (foo-val bar-val baz-val)
Something similar is available in Clojure: user> (let [{:keys [foo name]} h2] [(inc foo) name]) ==> [201 "Slodoban"]
or user> [(:foo h2) (h2 :name)] [200 "Slodoban"]
When keywords (symbols with a : in the front) were used then these keywords act as getter function. But one can in general also have the collection object first and then the key: ([10 20 30] 1) ==> 20
But your suggestion of (ht '(foo bar baz)) is really not good, as Alex already mentioned. People want to have the list (foo bar baz) as the key for their hash map.
> and possibly even this: > (ht (lambda (key) (like (princ-to-string key) "*-bar"))))
This would not be very orthogonal to what is already available and thus is not a good idea. And how could we decide if it will map over the keys or the values or the key/value pairs?
Why not just (map #(like (str %) "*-bar") (keys ht)) to get all keys that end with "-bar"? Or instead of map you could (first (filter #(like (str %) "*-bar") (keys ht)))
André -- Lisp is not dead. It’s just the URL that has changed: http://clojure.org/
On Dec 14, 3:07 pm, Jochen Schmidt <j...@crispylogics.com> wrote:
> It's not that easy. The problem is, that there is no way to override > the syntax of a cl funtion call. You can either have a symbol denoting > a function or a lambda expression.
Why not?
Consider a syntax transformation via code walker that does something like
> On Dec 14, 3:07 pm, Jochen Schmidt <j...@crispylogics.com> wrote:
> > It's not that easy. The problem is, that there is no way to override > > the syntax of a cl funtion call. You can either have a symbol denoting > > a function or a lambda expression.
> Why not?
> Consider a syntax transformation via code walker that does something > like
Error: The variable FN-OR-HT is unbound. 1 (continue) Try evaluating FN-OR-HT again. 2 Specify a value to use this time instead of evaluating FN-OR-HT. 3 Specify a value to set FN-OR-HT to. 4 (abort) Return to level 0. 5 Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed. Type :bug-form "<subject>" for a bug report template or :? for other options.
Error: The variable FN-OR-HT is unbound. 1 (continue) Try evaluating FN-OR-HT again. 2 Specify a value to use this time instead of evaluating FN-OR-HT. 3 Specify a value to set FN-OR-HT to. 4 (abort) Return to level 0. 5 Return to top loop level 0.
Type :b for backtrace or :c <option number> to proceed. Type :bug-form "<subject>" for a bug report template or :? for other options.
??>> It's not that easy. The problem is, that there is no way to override ??>> the syntax of a cl funtion call. You can either have a symbol denoting ??>> a function or a lambda expression.
> does (foo x) mean a function call or ht lookup? the only way to solve > ambiguity is > to have single namespace.
Yes, and what about this...
(setq car (make-hash-table))
Treating as a symbol is fine (setf (gethash 'a car) 'quux)
(gethash 'a car) => quux
But what happens with
(car '(foo or quux)) ?
It clashes with the CL:CAR function. Is the compiler supposed to understand that the value of the symbol is a hashtable hence effectively producing (gethash ...)? Is the value of CAR (value is changeable) now the hash table? Yes, probably. And what is the value of the function slot? (car '(a b c)) => a or does it now have #'gethash. But what happens if it finds (funcall car 'a).
IMHO, I think this 'extension' is cute, useful in certain circumstances, and not well thought-out. Better to make a macro as noted above. If the generated function (embedded gethash) closes over the hash table, then it's not dependent on the value of the symbol. But allowing DEFPARAMETER or even SETQ strikes me as confusing and not worth the time.
> It should be easy to emulate the hash table reader at least in > function context, by defining a custom DEFUN-wrapping macro that > dispatches either to FUNCALL or to GETHASH depending on the data type.
> Is this also possible for the SETF expansion? I think it should be, > but I hardly ever use the DEFSETF facilities so I'm not sure how.
> Leslie
I don't know if it would be considered "easy", but you might be interested at a blog post by Geoff Wozniak on Exploring Lisp. It's about funcallable objects in general.
This doesn't provide an entire solution, since you'd still need to write a hash table implementation. In your own package, though, you could shadow the CL hash table functions and provide the same interface though your own symbols (make-hash-table, gethash, …).
There are still some issue with the idea though, since CL is a Lisp-2, you end up having to do things such as those in Geoff's post, such as:
> It should be easy to emulate the hash table reader at least in > function context, by defining a custom DEFUN-wrapping macro that > dispatches either to FUNCALL or to GETHASH depending on the data type.
> Is this also possible for the SETF expansion? I think it should be, > but I hardly ever use the DEFSETF facilities so I'm not sure how.
> Leslie
You can achieve it with a sort of such simple macro as the following (a naive implementation without handling of parameters of make-hash- table): (defmacro def-hash-table (name) `(progn (defparameter ,name (make-hash-table)) (defun ,name (key &optional default) (gethash key ,name default)))) which uses Lisp's separation of namespaces.
PS. But, in my opinion, Lisp-n is better, because you virtually always know, what you are dealing with -- a var or a function.
Slobodan Blazeski wrote: > On Dec 14, 12:01 pm, "Leslie P. Polzer" <leslie.pol...@gmx.net> wrote: > > Clojure, from what I've gathered, lets one access hash tables just > > by referring to them in the CAR of an evaluated form:
> > (defparameter ht (make-hash-table))
> > (ht 'foo) == (gethash 'foo ht) > Actually I feel that as too verbose: > (ht 'foo) > ->foo-val > would be even better.
Still too verbose.
JavaScript:
js> h = {foo: 77, bar: 88} [object Object] js> h.foo 77 js> h.bar 88
> also I want below too for multiple keys selection: > (ht '(foo bar baz)) > -> (foo-val bar-val baz-val)
André Thieme <address.good.until.2009.may...@justmail.de> writes: > Slobodan Blazeski schrieb: >> On Dec 14, 12:01 pm, "Leslie P. Polzer" <leslie.pol...@gmx.net> wrote: >>> Clojure, from what I've gathered, lets one access hash tables just by >>> referring to them in the CAR of an evaluated form:
>>> (defparameter ht (make-hash-table))
>>> (ht 'foo) == (gethash 'foo ht) >> Actually I feel that as too verbose: >> (ht 'foo) >> ->foo-val >> would be even better.
> Let’s say we have two hashmaps:
It's quite incredible. Why people aren't trying to add syntaxes to languages such as pascal or C++ to be able to access maps or vectors as if was a function call, but periodically we get asked this kind of crapiness here?
Please, just ignore these questions, until we see them asked in clc++ or similarly in other cl* groups:
What can be done to be able to write:
int f(){ std::map<std::string,int> m; m("toto")=42; return m("toto"); }
> Pascal J. Bourguignon wrote: > > What can be done to be able to write:
> > int f(){ > > std::map<std::string,int> m; > > m("toto")=42; > > return m("toto"); > > }
> This is generally written as
> int f(){ > std::map<std::string,int> m; > m["toto"]=42; > return m["toto"];
> }
> This works because of the following prototype: > mapped_type & operator[](const key_type &);
> Although they could have chosen to define it as > mapped_type & operator()(const key_type &);
Well, is it possible to extend such syntax -- [] -- to handle, for example, multiple keys access at once (as mentioned above in the thread) or default value? AFAIK with [] -- not, because it's hardwired to take only 1 argument. Although, you can do it with (). But once again, can this accessor be extended to handle variable number of keys?..
world.lisp.de> wrote: > On Dec 14, 1:37 pm, Slobodan Blazeski <slobodan.blaze...@gmail.com> > wrote:
> > On Dec 14, 12:01 pm, "Leslie P. Polzer" <leslie.pol...@gmx.net> wrote:> Clojure, from what I've gathered, lets one access hash tables just by > > > referring to them in the CAR of an evaluated form:
> > > (defparameter ht (make-hash-table))
> > > (ht 'foo) == (gethash 'foo ht)
> > Actually I feel that as too verbose: > > (ht 'foo) > > ->foo-val > > would be even better. > > also I want below too for multiple keys selection: > > (ht '(foo bar baz)) > > -> (foo-val bar-val baz-val) > > and possibly even this: > > (ht (lambda (key) (like (princ-to-string key) "*-bar"))))
> > > It should be easy to emulate the hash table reader at least in > > > function context, by defining a custom DEFUN-wrapping macro that > > > dispatches either to FUNCALL or to GETHASH depending on the data type.
> > > Is this also possible for the SETF expansion? I think it should be, > > > but I hardly ever use the DEFSETF facilities so I'm not sure how.
> > > Leslie
> If you want to go that route, why not make $ a default hash-table > variable and $foo accesses it. > Also write $ht.foo to access hash table ht. Then make $h.f!3 set the > hash table h, key f to 3. > Not that it would look like Lisp, but it sure saves keystrokes.
Because I need a general solution. Every instance container is in the same time a function that takes a key, suit of keys or a predicate. (setq lst (list 1 2 3)) (setq arr (array 1 2 3))
> > On Dec 14, 12:01 pm, "Leslie P. Polzer" <leslie.pol...@gmx.net> wrote: > >> Clojure, from what I've gathered, lets one access hash tables just by > >> referring to them in the CAR of an evaluated form:
> >> (defparameter ht (make-hash-table))
> >> (ht 'foo) == (gethash 'foo ht) > > Actually I feel that as too verbose: > > (ht 'foo) > > ->foo-val > > would be even better.
> Let’s say we have two hashmaps: > (def h1 {:name "Slobodan" :foo 100 :language "Lisp"}) > (def h2 {:name "Slodoban" :foo 200 :language "Perl"})
Braces, no way. That's too much syntax already I'm thinking of using () for point-free definitions but that already looks ugly.
> When keywords (symbols with a : in the front) were used then these > keywords act as getter function. But one can in general also have the > collection object first and then the key: > ([10 20 30] 1) ==> 20
> But your suggestion of (ht '(foo bar baz)) is really not good, as Alex > already mentioned. People want to have the list (foo bar baz) as the key > for their hash map.
> > and possibly even this: > > (ht (lambda (key) (like (princ-to-string key) "*-bar"))))
> This would not be very orthogonal to what is already available and thus > is not a good idea. > And how could we decide if it will map over the keys or the values or > the key/value pairs?
Good question. If I have a list : (setq lst (list 1 2 3 4 5)) and I do: (lst #'oddp) what should the result be? (1 3 5) So the predicate loops over container values. For looping over keys there should be something else.
> Why not just (map #(like (str %) "*-bar") (keys ht)) to get all keys > that end with "-bar"? > Or instead of map you could
1st we agreed it's over values. But let's *PRETEND* it's over keys Whats' more understandable: (map #'predicate (keys ht)) or (ht #'predicate)
2nd map is generalized operator it could operate over multiple containers: (map #'> '(1 2 3) '(2 3 4)) while (container key(s)) or (container predicate) is a current container accessor.
I don't like replying to trolls, but since this question is of much interest to me I'll. Thank you Kaz for making this reply visible to me. On Dec 15, 12:27 am, "William James" <w_a_x_...@yahoo.com> wrote:
> Slobodan Blazeski wrote: > > On Dec 14, 12:01 pm, "Leslie P. Polzer" <leslie.pol...@gmx.net> wrote: > > > Clojure, from what I've gathered, lets one access hash tables just > > > by referring to them in the CAR of an evaluated form:
> > > (defparameter ht (make-hash-table))
> > > (ht 'foo) == (gethash 'foo ht) > > Actually I feel that as too verbose: > > (ht 'foo) > > ->foo-val > > would be even better.
That's slightly better for accessing a single element, token count is the same 2 but you don't have to use braces instead have a dot, but how would you access more elements or use a predicate WITHOUT breaking the consistency NOR adding new tokens?
> > also I want below too for multiple keys selection: > > (ht '(foo bar baz)) > > -> (foo-val bar-val baz-val)
This is where your solutions flops. You're unable to access multiple elements with the dot syntax so you're forced into adding a function. h.values_at(...) - 2 tokens just for syntax plus 2 braces ignoring the keys (h ...) - only one token plus 2 braces,ignoring the keys I win.
> > and possibly even this: > > (ht (lambda (key) (like (princ-to-string key) "*-bar"))))
> h.keys.map{|x| x.to_s}.grep(/^ba/)
Lets's see: h.*VALUES?*.map{predicate}- 3 tokens plus 2 braces ignoring the predicate (h predicate) - 1 token plus 2 braces ignoring the predicate
See your cheap ruby tricks doesn't scale well. You already losing 3:1 Now the real challenge? Given ht : keys 1 2 3 '(1 2) :values 1-val 2-val 3-val 1-2-val (h 1 2 '(1 2) (lambda (x) (and (numberp x) (oddp x)))) -> (1-val 2-val 1-2-val (1-val 3-val))