Reader Anomaly?

1 view
Skip to first unread message

Randall R Schulz

unread,
Nov 29, 2008, 9:30:47 AM11/29/08
to clo...@googlegroups.com
Hi,

What happened here?

user=> (take 20 (interpose '.' "The quick brown fox"))
(\T . \h . \e . \space . \q . \u . \i . \c . \k . \space .)


Naturally, I meant to use a character literal as the first argument to
interpose, but my C / Java habits led me to use the apostrophes instead
of the proper character literal notation.

Is it a reader bug? (That the second apostrophe appeared to be ignored.)


Randall Schulz

Robert Pfeiffer

unread,
Nov 29, 2008, 9:36:59 AM11/29/08
to Clojure
Hi,

On 29 Nov., 15:30, Randall R Schulz <rsch...@sonic.net> wrote:
> Hi,
>
> What happened here?

String literals evaluate to themselves. Quoting prevents evaluation.
When you evaluate a quoted string, you get just the string.

user=> '"hello"
"hello"
user=> "hello"
"hello"
user=> (= "a" '"a")
true

This behaviour is similar to that of number literals.

user=> (= 3 '3)
true

hth, Robert Pfeiffer

Stephen C. Gilardi

unread,
Nov 29, 2008, 9:45:57 AM11/29/08
to clo...@googlegroups.com

On Nov 29, 2008, at 9:30 AM, Randall R Schulz wrote:

Is it a reader bug? (That the second apostrophe appeared to be ignored.)

It wasn't ignored. It quoted the string.

I've been interested in a way to see what the reader returns for things like this in the past.

It turns out we can get that using macroexpand:

user=> (prn (macroexpand '(interpose '.' "The quick brown fox")))
(interpose (quote .) (quote "The quick brown fox"))

(I hadn't thought of macroexpand expanding reader macros as well as non-reader macros, but that's the effect here.)

--Steve

Randall R Schulz

unread,
Nov 29, 2008, 9:47:52 AM11/29/08
to clo...@googlegroups.com
On Saturday 29 November 2008 06:36, Robert Pfeiffer wrote:
> Hi,
>
> On 29 Nov., 15:30, Randall R Schulz <rsch...@sonic.net> wrote:
> > Hi,
> >
> > What happened here?
>
> String literals evaluate to themselves. Quoting prevents evaluation.
> When you evaluate a quoted string, you get just the string.

Right. My residual preconceptions continued to keep me from seeing what
really happened.

Thanks.

RRS

Randall R Schulz

unread,
Nov 29, 2008, 9:55:27 AM11/29/08
to clo...@googlegroups.com
On Saturday 29 November 2008 06:45, Stephen C. Gilardi wrote:
> On Nov 29, 2008, at 9:30 AM, Randall R Schulz wrote:
> > Is it a reader bug? (That the second apostrophe appeared to be
> > ignored.)
>
> It wasn't ignored. It quoted the string.

Yeah, Robert made me see that.


> I've been interested in a way to see what the reader returns for
> things like this in the past.
>
> It turns out we can get that using macroexpand:
>
> user=> (prn (macroexpand '(interpose '.' "The quick brown fox")))
> (interpose (quote .) (quote "The quick brown fox"))
>
> (I hadn't thought of macroexpand expanding reader macros as well as
> non-reader macros, but that's the effect here.)

I think the reader is doing "expanding" on reader macros. Macro-expand
is just nilpotent when no macros are in play.

In this case, it's no different than just printing the list you passed
to macroexpand:

user=> '(interpose '.' "The quick brown fox")


(interpose (quote .) (quote "The quick brown fox"))


It's a good technique, though, to see what the compiler is going to be
asked to translate after all players between the form as submitted and
the compiler have done their thing.


> --Steve


Randall Schulz

Stephen C. Gilardi

unread,
Nov 29, 2008, 9:59:50 AM11/29/08
to clo...@googlegroups.com

On Nov 29, 2008, at 9:55 AM, Randall R Schulz wrote:

In this case, it's no different than just printing the list you passed 
to macroexpand:

user=> '(interpose '.' "The quick brown fox")
(interpose (quote .) (quote "The quick brown fox"))

It's a good technique, though, to see what the compiler is going to be 
asked to translate after all players between the form as submitted and 
the compiler have done their thing.

Right you are on both counts. Thanks very much!

--Steve

Randall R Schulz

unread,
Nov 29, 2008, 10:29:36 AM11/29/08
to clo...@googlegroups.com
On Saturday 29 November 2008 06:55, Randall R Schulz wrote:
> ...

>
> It's a good technique, though, to see what the compiler is going to
> be asked to translate after all players between the form as submitted
> and the compiler have done their thing.

Or is it?

Can you tell what a newbie I am? I'm working my way through Stuart H.'s
book. I'm on the sequence section (4.2) and just got to "for". Here's
what I did / found:

user=> (doc for)
-------------------------
clojure.core/for
([seq-exprs expr])
Macro
List comprehension. ...

(take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))
nil


So seeing that "for" is a macro, I thought I'd see what it produces. I
started with the example included in the doc string:

user=> (macroexpand '(take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y])))
(take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))


So next I tried macroexpand -ing just the (for ...) sub-form:

user=> (macroexpand '(for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))
(let* [iter__3869 (clojure.core/fn iter__33
[s__34] (clojure.core/when-first [x s__34] (if true
(clojure.core/let [iterys__3867 (clojure.core/fn iter__35
[s__36] (clojure.core/when-first [y s__36] (if (< y x)
(clojure.core/lazy-cons [x y] (iter__35 (clojure.core/rest s__36)))
nil))) fs__3868 (iterys__3867 (range 1000000))] (if fs__3868
(clojure.core/lazy-cat fs__3868 (iter__33 (clojure.core/rest
s__34))) (recur (clojure.core/rest s__34)))) nil)))] (iter__3869
(range 100000000)))


I'm somewhat confused by this, but I gather it has something to do
with "take" being lazy?


> > --Steve


Randall Schulz

Randall R Schulz

unread,
Nov 29, 2008, 10:34:34 AM11/29/08
to clo...@googlegroups.com
On Saturday 29 November 2008 07:29, Randall R Schulz wrote:
> On Saturday 29 November 2008 06:55, Randall R Schulz wrote:
> > ...
> >
> > It's a good technique, though, to see what the compiler is going to
> > be asked to translate after all players between the form as
> > submitted and the compiler have done their thing.
>
> Or is it?
>
> ... I'm working my way through Stuart H.'s book.

> I'm on the sequence section (4.2) and just got to "for".
> Here's what I did / found:
>
> ...

>
> So seeing that "for" is a macro, I thought I'd see what it produces.
> I started with the example included in the doc string:
>
> user=> (macroexpand '(take 100 (for [x (range 100000000) y (range
> 1000000) :while (< y x)] [x y]))) (take 100 (for [x (range 100000000)
> y (range 1000000) :while (< y x)] [x y]))
>
>
> So next I tried macroexpand -ing just the (for ...) sub-form:
>
> user=> (macroexpand '(for [x (range 100000000) y (range 1000000)
> :while (< y x)] [x y])) (let* [iter__3869 (clojure.core/fn iter__33
> [s__34] (clojure.core/when-first [x s__34] (if true
> ...
>
>
> I'm somewhat confused by this, but I gather it has something to do
> with "take" being lazy?

And, continuing my exploration, the confirmation of this hunch comes
shortly after, in section 4.3.

This does, at least, impose a caveat on the use of macroexpand as a tool
for understanding what your code really says (and does).


Randall Schulz

Stephen C. Gilardi

unread,
Nov 29, 2008, 10:35:58 AM11/29/08
to clo...@googlegroups.com

On Nov 29, 2008, at 10:29 AM, Randall R Schulz wrote:

I'm somewhat confused by this, but I gather it has something to do
with "take" being lazy?

The last note in the doc for macroexpand explains it:

user=> (doc macroexpand)
-------------------------
clojure.core/macroexpand
([form])
  Repeatedly calls macroexpand-1 on form until it no longer
  represents a macro form, then returns it.  Note neither
  macroexpand-1 nor macroexpand expand macros in subforms.
nil

In this first case, "for" is a subform.

There's a nice description of going further here:


--Steve

Randall R Schulz

unread,
Nov 29, 2008, 10:43:57 AM11/29/08
to clo...@googlegroups.com

OK. So it's not the laziness of "take," but rather the nature of
macroexpand.

Thanks for the reference. I'll review that post.


> --Steve


Randall Schulz

Reply all
Reply to author
Forward
0 new messages