Passing Places (or: Pointers in Lisp?)

Discussion of Common Lisp
Post Reply
Jesdisciple
Posts: 26
Joined: Thu Feb 04, 2010 5:56 pm

Passing Places (or: Pointers in Lisp?)

Post by Jesdisciple » Wed Feb 10, 2010 8:48 pm

With the below code I'm getting this output:

Code: Select all

"m" 
#S(HASH-TABLE :TEST FASTHASH-EQUAL)
"m" 
#S(HASH-TABLE :TEST FASTHASH-EQUAL ("n" . "m"))
I was really hoping to see the second line be the same as the fourth, as the "place" returned by gethash seems to act like a C pointer. Is there some way to activate such behavior, or am I completely off-base?

Code: Select all

(defun foo ()
  (let ((bar (make-hash-table :test #'equal :size 4)))
    (lambda (baz quux)
	  (let ((corge (gethash baz bar)))
      (setf corge quux)
      (print quux)
      (print bar)
      (setf (gethash baz bar) quux)
      (print (gethash baz bar))
      (print bar)))))
(funcall (foo) "n" "m")
I'm off my grokker.
- Chris

nuntius
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: Passing Places (or: Pointers in Lisp?)

Post by nuntius » Wed Feb 10, 2010 9:30 pm

It took me a few reads to figure out what you want. The issue you're seeing is the "magic" of setf expanders. Setf is actually a macro that looks at the place form and outputs special modifying code appropriate for that place.

Read the description in
http://www.lispworks.com/documentation/ ... _setf_.htm
and the symbol-value example in
http://www.lispworks.com/documentation/ ... defset.htm

Then read CLHS section 5.1.
http://www.lispworks.com/documentation/ ... y/05_a.htm

At that point, you should understand exactly what's going on.

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: Passing Places (or: Pointers in Lisp?)

Post by ramarren » Thu Feb 11, 2010 12:15 am

Jesdisciple wrote:I was really hoping to see the second line be the same as the fourth, as the "place" returned by gethash seems to act like a C pointer. Is there some way to activate such behavior, or am I completely off-base?
There are no locatives in Common Lisp, which would be first class places. There were on Lisp Machines, but unfortunately they were not included in CL. Which means that places that SETF uses are not first class, but, as nuntius had written, part of SETF macro.

The way to achieve something approximating them is to either use SYMBOL-MACROLET for cases when the lexically scoped access to place is sufficient or create an anonymous closure wrapping the setting of a place and funcall that.

Jesdisciple
Posts: 26
Joined: Thu Feb 04, 2010 5:56 pm

Re: Passing Places (or: Pointers in Lisp?)

Post by Jesdisciple » Thu Feb 11, 2010 8:16 am

nuntius wrote:The issue you're seeing is the "magic" of setf expanders. Setf is actually a macro that looks at the place form and outputs special modifying code appropriate for that place.
Yeah, I realized that as I lay in bed last night. :o :idea:

Ramarren: Wouldn't SYMBOL-MACROLET only call GETHASH multiple times? I was hoping to only go searching my hashtable for that index one time. However, I think I understand how a closure could do that... EDIT: Wait, no I don't. I was trying to use GETHASH to both set and then get the value.
I'm off my grokker.
- Chris

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: Passing Places (or: Pointers in Lisp?)

Post by ramarren » Thu Feb 11, 2010 9:09 am

Jesdisciple wrote:Ramarren: Wouldn't SYMBOL-MACROLET only call GETHASH multiple times? I was hoping to only go searching my hashtable for that index one time. However, I think I understand how a closure could do that... EDIT: Wait, no I don't. I was trying to use GETHASH to both set and then get the value.
SYMBOL-MACROLET would mean that (SETF GETHASH) would be called every time you set a hashtable, the same with closure. Do note that (SETF GETHASH) and GETHASH are separate functions. (setf (gethash ...) ...) is just a syntax to call the former.

In general, Common Lisp doesn't allow holding pointers into the inside of datastructures (which would be the primary uses of locatives), so there is no way to avoid the full set in hashtable. Well, looking at SBCL source (the great thing about open source Lisps, you can just use M-. in Slime and jump straight into the internals), the last key lookup is cached. But in general you cannot "save your place".

If your performance is bottlenecked by key hashing then your algorithm is likely suboptimal, and if it is not then why worry about it?

Jesdisciple
Posts: 26
Joined: Thu Feb 04, 2010 5:56 pm

Re: Passing Places (or: Pointers in Lisp?)

Post by Jesdisciple » Thu Feb 11, 2010 9:23 am

Oh well. I found a way to only access it once anyway. I only set under one condition, so I just passed the return value of SETF on through and used the else clause (alright, it's probably not a "clause" - "form"?) to return the get'ed value.
Ramarren wrote:If your performance is bottlenecked by key hashing then your algorithm is likely suboptimal, and if it is not then why worry about it?
Because I don't know as much computer science as I probably should but have been trained to optimize wherever I see the potential. =p
I'm off my grokker.
- Chris

Post Reply