Re: What exactly is a form in Clojure?

2015-12-28 Thread David Sletten
Ray,

The question of what a form is is actually quite an important part of grasping 
Lisp/Clojure. Earlier versions of Lisp used the term S-expression (symbolic 
expression) extensively. But during the process of defining Common Lisp, the 
term was dropped in favor of the notion of forms. Stuart Shapiro wrote a Common 
Lisp book that you may find useful in studying Clojure as well: 
http://www.cse.buffalo.edu/~shapiro/Commonlisp/

In the book’s preface he defines these two terms:
S-expression - syntactic units, sequences of characters that form the written 
version of Lisp programs and data structures.
Form - a Common Lisp object that can be evaluated

In terms of the REPL (read-eval-print loop), an S-expression is the input to 
the reader, and a form is the output of the reader, which then becomes the 
input to eval. An S-expression is syntax. A form is some sort of representation 
in memory. So a simple rule of thumb is that S-expressions in Lisp often 
contain parentheses, but there are no parentheses in forms.

Here are a couple more formal definitions, again from a Common Lisp perspective:
http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_f.htm#form
form n. 1. any object meant to be evaluated. 2. a symbol, a compound form, or a 
self-evaluating object. 3. (for an operator, as in ``<> form'') a 
compound formhaving that operator as its first element. ``A quote form is a 
constant form.’'


A self-evaluating object would be something like a numeric literal: 2.4 or a 
string “Yo!”. Compound forms are further defined:
http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_c.htm#compound_form
compound form n. a non-empty list which is a form: a special form, a lambda 
form, a macro form, or a function form.

Remember that these Common Lisp definitions don’t line up exactly with Clojure, 
but they are illuminating.

Have all good days,
David Sletten

On Dec 28, 2015, at 11:16 AM, Ray Toal <ray.t...@gmail.com> wrote:

> I think of it this way too but was really trying to get a formal definition, 
> if one exists.
> 
> While I've not seen a formal grammar of Clojure anywhere, I have looked at
> 
> 
> https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java
> 
> which seems to show that forms can be a lot of things, including 
> READ_FINISHED and READ_EOF, which probably aren't intended for public 
> consumption. :)
> 
> The actual read() function (or method, as this is all written in Java), 
> looked promising but was hard to decipher.
> 
> Maybe the term is intentionally vague? I was hoping it wasn't. But the fact 
> that it is hard to find a hard definition of it makes me wonder.
> 
> Thanks
> 
> 
> On Monday, December 28, 2015 at 5:08:36 AM UTC-8, Gregg Reynolds wrote:
> 
> On Dec 28, 2015 6:58 AM, "Ray Toal" <ray@gmail.com> wrote:
> >
> > Throughout the Clojure documentation there are many references to forms.
> >
> > I know about special forms, macros, vars, symbols, keywords, integers, 
> > doubles, ratios, sets, maps, lists, vectors, booleans, nil, etc.
> >
> > What exactly, though, is a form?
> 
> A syntactic unit, as opposed to a lexical unit?  Left paren is a lexical 
> unit, to "read it you have to find the following balanced right paren, and if 
> everything in between is syntactically correct you have a list form.  At 
> least that's how I think of it.
> 
> Gregg
> 
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: why Clojure/Lisp is so fast

2014-02-18 Thread David Sletten
The OP almost certainly intended CLISP to mean Common Lisp.  While the 
CLISP implementation of Common Lisp is a decent platform (Conrad Barski 
features it in his book _Land of Lisp_, for example), it is not the fastest 
implementation. Their documentation acknowledges as much: 
http://www.clisp.org/propaganda.html 
See the section CLISP Performance at the bottom of the page.

Have all good days,
David Sletten

On Feb 18, 2014, at 10:37 PM, Mars0i marsh...@logical.net wrote:

 It really depends on the benchmark and the programmer, and sometimes on the 
 computer.  And on what a person chooses to report. Here are some benchmarks, 
 probably only representative of very special cases, that show Java beating 
 Clojure in many cases, Java and SBCL both beating each other in some cases, 
 etc.  (For my work, I have found SBCL to be a lot faster than CLISP, but 
 again, it probably depends on what you're doing.)
 
 http://benchmarksgame.alioth.debian.org/
 
 Other cases would be different.  (None of this conflicts with Mikera's 
 insightful comments.)
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 --- 
 You received this message because you are subscribed to the Google Groups 
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/groups/opt_out.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Difficulty understanding (new?) behavior of identical?

2012-05-05 Thread David Sletten
Can anyone explain this change?
(clojure-version)  = 1.2.0
(let [x 8.9] (identical? x x))  = true   

Compared to:
(clojure-version) = 1.4.0
(let [x 8.9] (identical? x x)) = false

Thanks.

David Sletten

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Difficulty understanding (new?) behavior of identical?

2012-05-05 Thread David Sletten

On May 5, 2012, at 3:06 PM, Daniel Solano Gómez wrote:

 On Sat May  5 14:53 2012, David Sletten wrote:
 Can anyone explain this change?
 (clojure-version)  = 1.2.0
 (let [x 8.9] (identical? x x))  = true
 
 Compared to:
 (clojure-version) = 1.4.0
 (let [x 8.9] (identical? x x)) = false
 
 Well, this is certainly an interesting phenomenon.  What is happening
 here is part of Clojure's primitive optimisations introduced in Clojure
 1.3.
 
 Before Clojure 1.3, the code:
 
 (let [x 8.9] (identical? x x))
 
 Roughly can be thought of expanding to something like:
 
 (let [x (Float. 8.9)] (identical? x x))
 
 Since x is an object, it is indeed identical to itself.
 
 In Clojure 1.3, the code could be thought of evaluating to something
 like:
 
 (let [x (float 8.9)] (identical? (Double. x) (Double. x)))
 
 The x remains unboxed, so that when it is passed to the function call,
 which presumably has no primitive-hinted forms, it much be boxed each
 time it is an argument, and the resulting objects are not identical.
 
 To see more of the same in action (in Clojure 1.3 and above):
 
 (let [x 127] (identical? x x))  ;= true
 (let [x 128] (identical? x x))  ;= false
 
 The JVM has an optimisation such that boxed versions of small integers
 get boxed to cached instances.  However for integers with large enough
 magnitudes, the JVM produces new objects.

Thanks for your response Daniel. You explain WHAT is apparently happening here. 
However, I am still struggling to understand WHY this is the new behavior. 

The documentation for 'identical?' states:  Tests if 2 arguments are the same 
object. To me, (identical? x x) asks whether 2 references to the same object 
(the referent of x) are identical. Clojure 1.4's response suggests that in some 
cases, within a given scope, a local can refer to 2 different things. To be 
charitable, this is a counterintuitive result. It's obvious that (identical? 
(Double. x) (Double. x)) should return false, but that's not what I'm asking. 
To suggest that x is not identical to x (within the same scope where they refer 
to the same thing) violates one of the most fundamental laws of logic.

You give interpretations of what is happening under the covers in both pre- and 
post-1.3 Clojure above. Your explanation appears to correspond to the observed 
behavior, but how did you come to this realization? Can you point me to where 
this issue is documented? I don't find any clues in the Clojure literature.

I see the following example in _The Joy Of Clojure_ (pg. 71):
(let [x 'goat y x] (identical? x y)) = true

As you point out, this is also the behavior with cached integers (-128 = n  
127). However, the following does not make the issue any clearer:
(let [x 123] (identical? x x)) = true
(let [x 1234] (identical? x x)) = false
(let [x 1234N] (identical? x x)) = true

(let [x 8.9M] (identical? x x)) = true
(let [x (Double. 8.9)] (identical? x x)) = true
(class 8.9) = java.lang.Double

Furthermore, in _Clojure Programming_ (pg. 433) the authors write: [identical?] 
corresponds directly to == in Java. This is clearly not true in the example I 
presented. This code will print 'true' in all 4 cases:
Double d1 = 8.9;
Double d2 = d1;

double d3 = 8.9;
double d4 = d3;

System.out.println(d1 == d1);
System.out.println(d1 == d2);
System.out.println(d3 == d3);
System.out.println(d3 == d4);

Of course, looking at the source for 'identical?' vindicates what these authors 
have written:
(defn identical? [x y]
  (clojure.lang.Util/identical x y))

In clojure.lang.Util:
static public boolean identical(Object k1, Object k2){
return k1 == k2;
}

So apparently as far as Java is concerned, my example should return 'true'. 
Therefore something must be occurring in the reader that results in the 
explanation which you gave.

To be fair, the Common Lisp standard seems goofy to me on this issue too. The 
analogous operator is EQ, documented here:
http://www.lispworks.com/documentation/HyperSpec/Body/f_eq.htm

Of note is the example below:
 (let ((x 5)) (eq x x))
=  true
OR=  false
This states that a conforming system may return either a true or a false value 
in this case. This doesn't make any more sense to me than what Clojure is 
doing, but all of the Common Lisp implementations I've tested (Allegro, 
Clozure, SBCL, CLISP) do return T as I expected.

David Sletten


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Difficulty understanding (new?) behavior of identical?

2012-05-05 Thread David Sletten
Fantastic Daniel. Your thorough analysis has cleared up my confusion. I see now 
that Java is partly to blame for this idiosyncratic behavior.

Furthermore, I agree that this is a relatively unlikely use of 'identical?'. 
Considering all of the usual concerns when comparing floating-point numbers, 
this is probably not worth getting worked up about.

Thanks,
David Sletten

On May 5, 2012, at 5:14 PM, Daniel Solano Gómez wrote:

 On Sat May  5 16:43 2012, David Sletten wrote:
 Thanks for your response Daniel. You explain WHAT is apparently
 happening here. However, I am still struggling to understand WHY this
 is the new behavior. 
 
 Yes, this is indeed a valid question.  I think the answer is that this
 particular behaviour is an unintended side effect of the performance
 optimizations introduced in Clojure 1.3.  By refusing to box numeric
 primitives until it's absolutely necessary, the results are generally
 much better performance for arithmetic code.
 
 The documentation for 'identical?' states:  Tests if 2 arguments are
 the same object. To me, (identical? x x) asks whether 2 references to
 the same object (the referent of x) are identical. Clojure 1.4's
 response suggests that in some cases, within a given scope, a local
 can refer to 2 different things. To be charitable, this is a
 counterintuitive result. It's obvious that (identical? (Double. x)
 (Double. x)) should return false, but that's not what I'm asking. To
 suggest that x is not identical to x (within the same scope where they
 refer to the same thing) violates one of the most fundamental laws of
 logic.
 
 Well, arguably, this is part of the unfortunate fallout of the JVM's
 disjoint type system between objects and primitives.  The key thing to
 realise is that before Clojure 1.3, (let [x 2] …) resulted in x
 referring to an object that contains the value of 2.  In Clojure 1.3 and
 newer, the x in (let [x 2] …) now refers to a primitive long with the
 value 2.
 
 You give interpretations of what is happening under the covers in both
 pre- and post-1.3 Clojure above. Your explanation appears to
 correspond to the observed behavior, but how did you come to this
 realization? Can you point me to where this issue is documented? I
 don't find any clues in the Clojure literature.
 
 I don't think it's documented, not as such.  I just happen to be
 familiar with a lot of implementation details.
 
 I see the following example in _The Joy Of Clojure_ (pg. 71):
 (let [x 'goat y x] (identical? x y)) = true
 
 As you point out, this is also the behavior with cached integers (-128
 = n  127). However, the following does not make the issue any
 clearer:
 (let [x 123] (identical? x x)) = true
 
 As we have established, the JVM's cache kicks in for this.
 
 (let [x 1234] (identical? x x)) = false
 
 This is outside the range of the cache, the boxed values of x are
 different.
 
 (let [x 1234N] (identical? x x)) = true
 
 Here, you are explicitly creating a clojure.lang.BigInt, an object.
 
 (let [x 8.9M] (identical? x x)) = true
 (let [x (Double. 8.9)] (identical? x x)) = true
 (class 8.9) = java.lang.Double
 
 Again for these, you are explicitly creating objects.
 
 Furthermore, in _Clojure Programming_ (pg. 433) the authors write:
 [identical?] corresponds directly to == in Java. This is clearly not
 true in the example I presented. This code will print 'true' in all 4
 cases:
Double d1 = 8.9;
Double d2 = d1;
 
double d3 = 8.9;
double d4 = d3;
 
System.out.println(d1 == d1);
System.out.println(d1 == d2);
System.out.println(d3 == d3);
System.out.println(d3 == d4);
 
 Of course, looking at the source for 'identical?' vindicates what these 
 authors have written:
 (defn identical? [x y]
  (clojure.lang.Util/identical x y))
 
 In clojure.lang.Util:
 static public boolean identical(Object k1, Object k2){
return k1 == k2;
 }
 
 So apparently as far as Java is concerned, my example should return
 'true'. Therefore something must be occurring in the reader that
 results in the explanation which you gave.
 
 Not quite, you get the same behaviour in Java if you have to autobox the 
 values like Clojure does:
 
 public class Equals {
  static boolean eq(Object lhs, Object rhs) {
return lhs == rhs;
  }
 
  public static void main(String[] args) {
// prints true
System.out.println(eq(1, 1));
 
// prints true
System.out.println(eq(127, 127));
 
// prints false
System.out.println(eq(128, 128));
  }
 }
 
 
 To be fair, the Common Lisp standard seems goofy to me on this issue
 too. The analogous operator is EQ, documented here:
 http://www.lispworks.com/documentation/HyperSpec/Body/f_eq.htm
 
 Of note is the example below:
 (let ((x 5)) (eq x x))
 =  true
 OR=  false
 This states that a conforming system may return either a true or a
 false value in this case. This doesn't make any more sense to me than
 what Clojure is doing, but all of the Common Lisp implementations

Re: Correct way to define the else clause of a cond form?

2011-07-06 Thread David Sletten

Conrad,

The syntax of 'cond' is actually pretty straightforward. Following the symbol 
'cond' you have pairs of predicate forms and consequent expressions. The 'cond' 
form evaluates each predicate in turn until one evaluates to true and then 
returns the value of the corresponding consequent form. Many 'cond' forms have 
a default value that is returned when none of the predicates succeed. Remember 
that in Clojure only the value 'false' and the value 'nil' are considered 
false. Everything else is true. By convention we use the keyword ':else' as a 
'predicate' for the default case. Since ':else' is neither 'false' nor 'nil', 
it is considered to be true, and if the 'cond' form reaches the ':else' clause, 
then the default value will be returned.

Given these restrictions, only a) and c) are syntactically correct. And even 
they don't do what you want.

 a)
 
 (cond
   (= total 20) 8.75
   (or (amount  20) (= country US) 9.75)
   (else 10.0))
 

Here we have:
predicate | consequent
(= total 20) | 8.75
(or (amount  20) (= country US) 9.75) |  (else 10.0)

Unfortunately, (else 10.0) winds up as the consequent of the 2nd predicate. 
Furthermore, 'else' is not a Clojure operator. Unless you've defined a function 
or macro named 'else' you will get an error.

 b)
 
 (cond
   (= total 20) 8.75
   (or (amount  20) (= country US) 9.75)
   :default 10.0)
 

predicate | consequent
 (= total 20) | 8.75
 (or (amount  20) (= country US) 9.75) | :default
 10.0 | ???

These are not paired up properly.

 c)
 
 (cond
   (= total 20) 8.75
   (or (amount  20) (= country US) 9.75)
   10.0 )

predicate | consequent
 (= total 20)  | 8.75
 (or (amount  20) (= country US) 9.75) | 10.0

Not what you expected...

 
 d)
 
 (cond
   (= total 20) 8.75
   (or (amount  20) (= country US) 9.75)
   :else 10.0 )

predicate | consequent
 (= total 20)  | 8.75
 (or (amount  20) (= country US) 9.75) |  :else
 10.0 | ???

Not syntactically correct.

Here's what you want to use:
(cond
  (== total 20) 8.75
  (or ( amount 20) (= country US)) 9.75
  :else 10.0)

(Note that '==' is the proper predicate for numerical equality.)

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Correct way to define the else clause of a cond form?

2011-07-06 Thread David Sletten

On Jul 6, 2011, at 10:58 PM, Conrad Taylor wrote:

 On Jul 6, 7:33 pm, Benny Tsai benny.t...@gmail.com wrote:
 Could you please post the entire form, including the code surrounding the
 cond form (since total, amount, and country need to be defined somewhere)?
 
 Benny, that was just sample code to zero in on the initial issue.  I'm
 working
 through the SICP with a lot of pain but here's what I have so far:
 
 (def us-coins (list 50 25 10 5 1))
 (def uk-coins (list 100 50 20 10 5 2 1 0.5))
 
 (defn first-denomination [ coin-values ] (first coin-values))
 
 (defn except-first-denomination [ coin-values ] (rest coin-values))
 
 (defn no-more? [coin-values] (nil? coin-values))
 
 (defn cc [amount coin-values]
   (cond
   (= amount 0) 1
(or ( amount 0) (no-more? coin-values)) 0
  :else (+ (cc amount (except-first-denomination coin-values))
   (cc (- amount (first-denomination coin-
 values)) coin-values
 

Part of the problem is that Clojure uses a slightly different syntax for 'cond' 
than Scheme (and Common Lisp) do. In particular, Common Lisp more frequently 
allows for side effects, so rather than a single consequent value Common Lisp's 
COND encloses its consequent expressions in a an additional layer of 
parentheses. Clojure discourages side effects, so it's reasonable to think in 
terms of a single expression as a consequent. The need for enclosing 
parentheses disappears.

Beware that the predicate 'nil?' tests whether an object is 'nil'. You probably 
want to use the predicate 'empty?' to test whether your coin list is empty.


Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Translating Java code with nested for loops

2011-06-29 Thread David Sletten

On Jun 29, 2011, at 1:45 AM, David Sletten wrote:
 
 (defn compute-contrib [daily-values total-values]
   (loop [contrib []
  daily-values daily-values
  total-values total-values]
 (if (empty? daily-values)
   contrib
   (recur (conj contrib (* (first daily-values) (reduce (fn [sum 
 total-value] (* sum (+ (/ total-value 100.0) 1.0)))
1.0
(rest 
 total-values
  (rest daily-values)
  (rest total-values )
 

Arrgghh! Now you've got me doing it too... :)

Replace 'sum' with 'product':
(defn compute-contrib [daily-values total-values]
  (loop [contrib []
 daily-values daily-values
 total-values total-values]
(if (empty? daily-values)
  contrib
  (recur (conj contrib (* (first daily-values) (reduce (fn [product 
total-value] (* product (+ (/ total-value 100.0) 1.0)))
   1.0
   (rest 
total-values
 (rest daily-values)
 (rest total-values )


Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Translating Java code with nested for loops

2011-06-28 Thread David Sletten

On Jun 28, 2011, at 8:20 PM, Bhinderwala, Shoeb wrote:
 The inputs are two arrays of type double of the same length – dailyValues and 
 totalValues. The output is the array contrib of the same length.
 
 
 int n = dailyValues.length;
 
 for (int i = 0; i  n; i++)
 
 {
 
 sum = 1.0;
 
 for (int j = i + 1; j  n; j++)
 
 {
 
 sum *= (1.0 + (totalValues[j] / 100.0));
 
 }
 
 contrib[i] = sum * dailyValues[i];
 
 }
 

1. Are you sure that this does what you want it to?
2. What does it do?

There are two obvious red flags with the code:
-You have a variable called 'sum' which is really a product.
-You never use index 0 of totalValues

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Translating Java code with nested for loops

2011-06-28 Thread David Sletten

On Jun 28, 2011, at 11:37 PM, David Sletten wrote:

 
 On Jun 28, 2011, at 8:20 PM, Bhinderwala, Shoeb wrote:
 The inputs are two arrays of type double of the same length – dailyValues 
 and totalValues. The output is the array contrib of the same length.
 
 
 int n = dailyValues.length;
 
 for (int i = 0; i  n; i++)
 
 {
 
 sum = 1.0;
 
 for (int j = i + 1; j  n; j++)
 
 {
 
 sum *= (1.0 + (totalValues[j] / 100.0));
 
 }
 
 contrib[i] = sum * dailyValues[i];
 
 }
 
 
 1. Are you sure that this does what you want it to?
 2. What does it do?
 
 There are two obvious red flags with the code:
 -You have a variable called 'sum' which is really a product.
 -You never use index 0 of totalValues
 

Assuming that your code is correct, the following reproduces your results:
(defn compute-contrib [daily-values total-values]
  (loop [contrib []
 daily-values daily-values
 total-values total-values]
(if (empty? daily-values)
  contrib
  (recur (conj contrib (* (first daily-values) (reduce (fn [sum 
total-value] (* sum (+ (/ total-value 100.0) 1.0)))
   1.0
   (rest 
total-values
 (rest daily-values)
 (rest total-values )

In the outer loop you are working with each element of dailyValues and 
consecutively smaller subsequences of totalValues. In the inner loop you repeat 
a calculation using each of the remaining elements of totalValues starting with 
a seed value of 1.0.

The Clojure implementation uses 'loop' to traverse each of the input sequences. 
On each iteration we use 'reduce' to do the work of the inner loop (notice that 
'reduce' is working with (rest total-values) rather than simply total-values 
itself, so we discard the first element each time just as your inner loop 
does), multiply that by the current element of interest in daily-values and 
then accumulate the result by conjoining it with our result 'contrib'.

The mental shift that you need to make involves forgetting about the index 
variables i and j and thinking instead about what the loops are accomplishing. 
If an inner loop is collapsing a sequence to a single result as above, then 
'reduce' is what you want to use. Other inner loops might require 'map' or 
'filter' depending on the computation.

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Cons vs List vs. ISeqs

2011-06-24 Thread David Sletten

On Jun 24, 2011, at 7:35 PM, Tim Robinson wrote:

 I'm under the impression that traditional lisps have a greater
 distinction between a cons operation vs. a list operation.
 Specifically I had believed that consing was a more efficient and
 better performing operation than using list.
 

This is not true, but it is also not relevant. In historical Lisps, the list 
datatype is a singly-linked list consisting of nodes known as CONS cells. In 
Common Lisp, for example, the predicate (listp obj) is simply equivalent to the 
test (typep obj '(or cons null)). A list is either a (chain of) CONS or the 
empty list. Notice that this implicitly includes improper lists (dotted 
pairs) such as (cons 1 2). In Clojure, on the other hand, it is illegal for the 
second argument to 'cons' to be an atom:
(cons 1 2) =
java.lang.IllegalArgumentException: Don't know how to create ISeq from: 
java.lang.Integer

A Lisp form such as (list 1 2 3) is just a series of calls to cons: (cons 1 
(cons 2 (cons 3 '(.

 Is this true? and if so, given both the Cons and Lists are actually
 both just seqs in Clojure, does the above statement still hold true in
 the Clojure world?
 

As I mentioned, the correspondence between LIST and CONS in traditional Lisps 
is not really relevant in Clojure, where the emphasis is on the sequence 
abstraction. A sequence simply satisfies an interface that provides a 'first' 
element, the 'rest' of the sequence, and allows you to construct ('cons') a new 
sequence from an existing one. Lists and vectors are two concrete sequence 
types, and they have significant differences in terms of behavior and 
performance. But in Clojure you can 'cons' using a list or a vector. So the 
rules are a little different from other Lisps.


Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Small Problem: Which Strings Differ at One Location

2011-05-30 Thread David Sletten

On May 30, 2011, at 3:55 PM, joshua-choi wrote:

 Let's say that I have a set of strings, each three English letters
 long.
 
 How can I determine which strings differ only at one location (e.g.
 xxe and xbe)?
 
 Right now, I'm writing a loop that sequentially compares every string
 to every other string. I think that there's a better way, but I don't
 know where to start.


I haven't given too much thought to performance here, but this collects all 
strings which differ only at one position. The program removes successive 
characters from each string and groups those that are the same after that 
deletion. For example,
abc, dbc, zbc are all reduced to bc when the first letter is removed. 
Thus, all three strings would be grouped together rather than pairwise. 
'match-position' groups related strings and weeds out singletons.

(defn remove-nth [s n]
  (str (subs s 0 n)
   (subs s (inc n

(defn match-position [words i]
  (remove (fn [coll] (= (count coll) 1))
  (map (fn [[key val]] (map second val))
   (group-by first
 (map (fn [s] [(remove-nth s i) s])
  words)

(match-position [abc abd aed axf zqr zbc aqd] 0) = ((abc 
zbc))
(match-position [abc abd aed axf zqr zbc aqd] 1) = ((abd aed 
aqd))
(match-position [abc abd aed axf zqr zbc aqd] 2) = ((abc 
abd))

(match-position [abc abd aed axf zqr zbc aqd qbd tbd tqr] 
0) = ((abc zbc) (abd qbd tbd) (zqr tqr))


Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: every-nth

2010-11-24 Thread David Sletten

On Nov 24, 2010, at 11:45 PM, Ken Wesson wrote:

 On Wed, Nov 24, 2010 at 11:11 PM, Baishampayan Ghose b.gh...@gmail.com 
 wrote:
  I just needed a function for every-nth element in a sequence.. I know it
 can be trivially implemented as ..
 (defn every-nth [n coll]
   (letfn [(evn [cn s]
 (when s
   (if (= cn 1)
 (lazy-seq (cons (first s) (evn n (next s
 (evn (dec cn) (next s)]
 (evn n coll)))
 But I remember seeing inbuilt function .. can anybody help me find it?
 
 take-nth should do the job -
 http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/take-nth
 
 And it can be even more trivially implemented as (map first (partition
 n coll)). :)
 

(map first (partition 1 n coll))


 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: every-nth

2010-11-24 Thread David Sletten
I stand corrected. I thought it required another arg. Yours was right already.

On Nov 24, 2010, at 11:53 PM, David Sletten wrote:

 
 On Nov 24, 2010, at 11:45 PM, Ken Wesson wrote:
 
 On Wed, Nov 24, 2010 at 11:11 PM, Baishampayan Ghose b.gh...@gmail.com 
 wrote:
 I just needed a function for every-nth element in a sequence.. I know it
 can be trivially implemented as ..
 (defn every-nth [n coll]
  (letfn [(evn [cn s]
(when s
  (if (= cn 1)
(lazy-seq (cons (first s) (evn n (next s
(evn (dec cn) (next s)]
(evn n coll)))
 But I remember seeing inbuilt function .. can anybody help me find it?
 
 take-nth should do the job -
 http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/take-nth
 
 And it can be even more trivially implemented as (map first (partition
 n coll)). :)
 
 
 (map first (partition 1 n coll))
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: sort-by reverse order?

2010-11-21 Thread David Sletten
Alex,

There might be some useful info here:
http://www.gettingclojure.com/cookbook:sequences#sorting


Have all good days,
David Sletten


On Nov 22, 2010, at 12:07 AM, Alex Baranosky wrote:

 So for the case I had that method worked.  I wonder though if I had wanted to 
 sort by multiple keys, with some of the keys sorting in reverse order and 
 others in regular order, how I could do that...  Say last name ascending, 
 date of birth descending for example.
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en





-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: string interpolation

2010-11-20 Thread David Sletten
The cool way is to use Tom Faulhaber's cl-format in clojure.pprint:
http://clojure.github.com/clojure/#clojure.pprint

(use '[clojure.contrib.pprint :only (cl-format)])
(cl-format true This is a ~A string.~% 'funky)
This is a funky string.

I have a mini-tutorial plus links here:
http://www.gettingclojure.com/cookbook:sequences#commas

Have all good days,
David Sletten

On Nov 20, 2010, at 6:00 PM, HiHeelHottie wrote:

 
 I think ruby has nice string interpolation.  You can put the following
 in a textfield that a user can modify
 
 This is a #{adjective} string.
 
 Then, you can take that string, put it in quotes and have ruby
 evaluate it as a string.  What is the clojure way of doing something
 similar.  Presenting something like
 
 This is a  adjective  string
 
 and then wrapping that in (str ) before evaluating it in clojure seems
 less attractive.
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en






-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread David Sletten

On Nov 17, 2010, at 9:22 AM, Stuart Halloway wrote:

 In 1.2, functions were always looked up through their vars. While this is a 
 low-cost operation, it does not allow maximum performance.
 
 In 1.3, function calls are compiled through their vars. If function a calls 
 function c inside its body, there is no runtime lookup of the var c. However, 
 each function makes a (very low cost) check on entry to see if anything has 
 been recompiled. If so, the function is recompiled. This enables the dynamic 
 repl interaction that you would expect from a lisp, with great performance.
 
 When, as in your example, a var b refers to var a, there is no function call, 
 hence no hook point at which to make the check. If you want b to point to the 
 new a, redef b. 
 

Stu,

This doesn't seem consistent with what Alyssa is reporting. She's getting a 
weird mix of both old 'a' and new 'a':
 = (defn a
([x] x)
([x y] (+ (a x) (a y
 #'user/a

 = (a 1 2)
 3

 = (def b a)
 #'user/b

 = (b 1 2)
 3

 = (defn a [x]
(- x))
 #'user/a

 = (b 1 2)
 -3

Let's call the original function assigned to 'a' a0 and the new one a1. After 
'a' has been redefined to a1, 'b' still refers to a0. So the 2nd call to 'b' 
invokes a0 with two args (in fact, a1 only takes one arg now). But within a0 
itself the references to 'a' are being resolved at runtime to a1 now, not as 
references to a0 as before.

Are you saying that inside a0 Clojure detects that 'a' means something else now 
and recompiles a0 to point to a1?

In any case, this behavior seems weird.

Have all good days,
David Sletten

 Stu
 
 Notice that when I redefined a, I only included one arity.  If b were
 updated with the fn that a was redefined to, then (b 1 2) should have
 thrown an exception.  Instead, it used the old definition of a but
 within that definition pointed to the new definition of a.  This is
 internally inconsistent.
 
 I'm not proposing making all function definitions lexically bound.
 Yes, that would destroy interactive coding.
 
 But to be internally consistent, self-references should be lexical.
 
 In any case, I am using Github master and I thought I was using 1.2.
 1.2 has self-references lexically bound, as David Sletten points out,
 which I agree is the correct behavior.  But something has happened on
 1.3 alpha that has changed that.  I don't know if it's intentional or
 not.
 
 Thanks,
 Alyssa Kwan
 
 On Nov 16, 6:01 pm, David Nolen dnolen.li...@gmail.com wrote:
 But that would destroy one of the most useful features Lisp has to offer,
 interactive coding.
 
 Live coding would be impossible w/o this behavior as you would need to find
 and update all callers. Yuk.
 
 David
 
 On Tue, Nov 16, 2010 at 5:26 PM, Alyssa Kwan alyssa.c.k...@gmail.comwrote:
 
 
 
 I ran into this while working on making functions durable.  Here's a
 contrived example:
 
 = (defn a
([x] x)
([x y] (+ (a x) (a y
 #'user/a
 
 = (a 1 2)
 3
 
 = (def b a)
 #'user/b
 
 = (b 1 2)
 3
 
 = (defn a [x]
(- x))
 #'user/a
 
 = (b 1 2)
 -3
 
 Is this what people expect?  I would think that the original
 definition of a, which is self-referencing, should point to itself no
 matter what it's named, not get resolved at invoke-time to see what
 the var is currently resolving to.
 
 Thanks,
 Alyssa Kwan
 
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.comclojure%2bunsubscr...@googlegroups.com
  
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http

Re: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-16 Thread David Sletten

On Nov 16, 2010, at 5:26 PM, Alyssa Kwan wrote:

 I ran into this while working on making functions durable.  Here's a
 contrived example:
 
 = (defn a
 ([x] x)
 ([x y] (+ (a x) (a y
 #'user/a
 
 = (a 1 2)
 3
 
 = (def b a)
 #'user/b
 
 = (b 1 2)
 3
 
 = (defn a [x]
 (- x))
 #'user/a
 
 = (b 1 2)
 -3
 

I'm confused here. Are you saying that this is what _you_ expect to see? 
Because that's not how Clojure actually behaves. 

You assign the function 'a' to 'b', and 'b' continues to refer to the original 
function after you redefine 'a'. So your second call to (b 1 2) still returns 3.

That's interesting since the function assigned to 'b' (the original version of 
'a') retains the self-reference after 'a' is redefined. The call to 'a' in 'b' 
still refers to the original 'a'. In other words, Clojure is not looking up the 
current value of 'a' when 'b' is invoked.

But that is what happens with non-self-referencing functions (There must be a 
clearer way to say that...a function which references a function other than 
itself):
(defn d [x y] (* x y))
(defn c [x] (d x 2))
(def f d)
(defn e [x] (f x 2))
user= (c 5)
10
user= (e 5)
10

(defn d [x y] ( x y))
user= (c 5)
false
user= (e 5)
10

Here the value of (c 5) changes depending on how 'd' is defined, whereas 'f' 
continues to refer to the original definition.

I suppose the answer comes from expanding 'defn':
(macroexpand '(defn a
  ([x] x)
  ([x y] (+ (a x) (a y )
= (def a (.withMeta (clojure.core/fn a ([x] x) ([x y] (+ (a x) (a y (.meta 
(var a

(macroexpand '(defn c [x] (d x 2)))
= (def c (.withMeta (clojure.core/fn c ([x] (d x 2))) (.meta (var c

And the documentation (http://clojure.org/special_forms#fn) says:
If a name symbol is provided, it is bound within the function definition to the 
function object itself, allowing for self-calling, even in anonymous functions.

So I guess technically the self-referential 'a' in the function definition 
actually refers to the name inside the 'fn' form not the variable that is 
getting def'd?
 

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Passing arguments from clojure to java

2010-11-16 Thread David Sletten

On Nov 16, 2010, at 5:49 PM, unst...@gmail.com wrote:

 This seems like such an obvious question, but I can't seem to find the
 answer anywhere. I don't understand why this would not be included in
 the java_interop section of the clojure documentation.
 
 Is it possible to pass a clojure vector to a java function that
 requires a java vector as an argument? Apparently not since:
 
 (javax.swing.table.DefaultTableModel. [I B] 0) fails.
 
 What is the idiomatic way to do this?
 

It looks as though your constructor takes either a java.util.Vector or an array 
of Object[].

To make a String[] array out of a Clojure vector 
(clojure.lang.PersistentVector):
(into-array String [I B])

So you wind up with this:
(javax.swing.table.DefaultTableModel. (into-array String [I B]) 0)
#DefaultTableModel javax.swing.table.defaulttablemo...@3ebc312f

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-16 Thread David Sletten
Ok, now I get it. The results you included weren't a hypothetical example, you 
were simply using a different version of Clojure. So in your 1.3 version, the 
second (b 1 2) does return -3?

Are the macro expansions of 'defn' different?


Have all good days,
David Sletten

On Nov 16, 2010, at 10:52 PM, Alyssa Kwan wrote:

 Notice that when I redefined a, I only included one arity.  If b were
 updated with the fn that a was redefined to, then (b 1 2) should have
 thrown an exception.  Instead, it used the old definition of a but
 within that definition pointed to the new definition of a.  This is
 internally inconsistent.
 
 I'm not proposing making all function definitions lexically bound.
 Yes, that would destroy interactive coding.
 
 But to be internally consistent, self-references should be lexical.
 
 In any case, I am using Github master and I thought I was using 1.2.
 1.2 has self-references lexically bound, as David Sletten points out,
 which I agree is the correct behavior.  But something has happened on
 1.3 alpha that has changed that.  I don't know if it's intentional or
 not.
 
 Thanks,
 Alyssa Kwan
 
 On Nov 16, 6:01 pm, David Nolen dnolen.li...@gmail.com wrote:
 But that would destroy one of the most useful features Lisp has to offer,
 interactive coding.
 
 Live coding would be impossible w/o this behavior as you would need to find
 and update all callers. Yuk.
 
 David
 
 On Tue, Nov 16, 2010 at 5:26 PM, Alyssa Kwan alyssa.c.k...@gmail.comwrote:
 
 
 
 I ran into this while working on making functions durable.  Here's a
 contrived example:
 
 = (defn a
 ([x] x)
 ([x y] (+ (a x) (a y
 #'user/a
 
 = (a 1 2)
 3
 
 = (def b a)
 #'user/b
 
 = (b 1 2)
 3
 
 = (defn a [x]
 (- x))
 #'user/a
 
 = (b 1 2)
 -3
 
 Is this what people expect?  I would think that the original
 definition of a, which is self-referencing, should point to itself no
 matter what it's named, not get resolved at invoke-time to see what
 the var is currently resolving to.
 
 Thanks,
 Alyssa Kwan
 
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.comclojure%2bunsubscr...@googlegroups.com 
 
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Clojure typing test

2010-11-15 Thread David Sletten
The StackOverflowError jumps over the lazy seq.

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Performance of seq on empty collections

2010-11-15 Thread David Sletten

On Nov 15, 2010, at 4:41 PM, Alan wrote:

 Yes, the API *does* suggest using seq to check for emptiness. (empty?
 x) is implemented as (not (seq x)). You certainly won't ever get
 improved performance by using empty? - at best you break even, most of
 the time you lose. For example:
 

The only way the API could suggest using 'seq' to check for emptiness is by not 
having a function called 'empty?'. It's irrelevant that 'empty?' is merely 
implemented as (not (seq)). The function is there for a reason. Are you 
suggesting that it's deprecated? If you would like to focus on a premature 
optimization of this sort, go right ahead. I will stick with the more 
meaningful function name.  If I'm testing whether or not a sequence is empty I 
will use 'empty?'.
 
 
 Of course performance isn't usually the main driver, so if you feel
 empty? really is more expressive in your case, go for it. But the OP
 seems to care about performance, and suggesting empty? is off the
 mark.
 

Apparently you didn't read what I wrote. I didn't suggest that using 'empty?' 
would solve the OP's performance issue. I simply pointed out that he was 
testing two opposite things.

 On Nov 14, 11:42 am, David Sletten da...@bosatsu.net wrote:
 On Nov 14, 2010, at 2:16 PM, Eric Kobrin wrote:
 
 In the API it is suggested to use `seq` to check if coll is empty.
 
 Your timing results raise some interesting questions, however, the API 
 doesn't suggest using 'seq' to check if a collection is empty. That's what 
 'empty?' is for. The documentation note suggests (for style purposes 
 apparently) that you use 'seq' to test that the collection is not empty. So 
 to be precise you are testing two different things below. For instance, 
 (identical? coll []) is true when coll is an empty vector. (seq coll) is 
 true when coll is not empty. The correct equivalent would be to test (empty? 
 coll).
 
 Of course, this doesn't change the results. I get similar timings with 
 empty?:
 user= (let [iterations 1] (time (dotimes [_ iterations]
 (identical? [] []))) (time (dotimes [_ 
 iterations] (empty? []
 Elapsed time: 2.294 msecs
 Elapsed time: 2191.256 msecs
 nil
 user= (let [iterations 1] (time (dotimes [_ iterations] 
  
  

(identical?  ))) (time 
 (dotimes [_ iterations] (empty? 
 Elapsed time: 2.657 msecs
 Elapsed time: 4654.622 msecs
 nil
 user= (let [iterations 1] (time (dotimes [_ iterations] 
  
  

(identical? () ( (time 
 (dotimes [_ iterations] (empty? ()
 Elapsed time: 2.608 msecs
 Elapsed time: 2144.142 msecs
 nil
 
 This isn't so surprising though, considering that 'identical?' is the 
 simplest possible test you could try--do two references point to the same 
 object in memory? It can't get any more efficient than that.
 
 Have all good days,
 David Sletten
 
 
 
 I was working on some code recently found that my biggest performance
 bottleneck was calling `seq` to check for emptiness. The calls to
 `seq` were causing lots of object allocation and taking noticeable CPU
 time. I switched to using `identical?` to explicitly compare against
 the empty vector and was rewarded with a drastic reduction in
 execution time.
 
 Here are some hasty tests showing just how big the difference can be:
 
 user= (let [iterations 1] (time (dotimes [_ iterations]
 (identical? [] []))) (time (dotimes [_ iterations] (seq []
 Elapsed time: 3.512 msecs
 Elapsed time: 2512.366 msecs
 nil
 user= (let [iterations 1] (time (dotimes [_ iterations]
 (identical?  ))) (time (dotimes [_ iterations] (seq 
 Elapsed time: 3.898 msecs
 Elapsed time: 5607.865 msecs
 nil
 user= (let [iterations 1] (time (dotimes [_ iterations]
 (identical? () ( (time (dotimes [_ iterations] (seq ()
 Elapsed time: 3.768 msecs
 Elapsed time: 2258.095 msecs
 nil
 
 Has any thought been given to providing a faster `empty?` that is not
 based on seq?
 
 Thanks,
 Eric Kobrin
 
 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with 
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post

Re: Performance of seq on empty collections

2010-11-14 Thread David Sletten

On Nov 14, 2010, at 2:16 PM, Eric Kobrin wrote:

 In the API it is suggested to use `seq` to check if coll is empty.

Your timing results raise some interesting questions, however, the API doesn't 
suggest using 'seq' to check if a collection is empty. That's what 'empty?' is 
for. The documentation note suggests (for style purposes apparently) that you 
use 'seq' to test that the collection is not empty. So to be precise you are 
testing two different things below. For instance, (identical? coll []) is true 
when coll is an empty vector. (seq coll) is true when coll is not empty. The 
correct equivalent would be to test (empty? coll).

Of course, this doesn't change the results. I get similar timings with empty?:
user= (let [iterations 1] (time (dotimes [_ iterations]
(identical? [] []))) (time (dotimes [_ 
iterations] (empty? []
Elapsed time: 2.294 msecs
Elapsed time: 2191.256 msecs
nil
user= (let [iterations 1] (time (dotimes [_ iterations]


  
   (identical?  ))) (time (dotimes 
[_ iterations] (empty? 
Elapsed time: 2.657 msecs
Elapsed time: 4654.622 msecs
nil
user= (let [iterations 1] (time (dotimes [_ iterations]


  
   (identical? () ( (time (dotimes 
[_ iterations] (empty? ()
Elapsed time: 2.608 msecs
Elapsed time: 2144.142 msecs
nil

This isn't so surprising though, considering that 'identical?' is the simplest 
possible test you could try--do two references point to the same object in 
memory? It can't get any more efficient than that.

Have all good days,
David Sletten

 
 I was working on some code recently found that my biggest performance
 bottleneck was calling `seq` to check for emptiness. The calls to
 `seq` were causing lots of object allocation and taking noticeable CPU
 time. I switched to using `identical?` to explicitly compare against
 the empty vector and was rewarded with a drastic reduction in
 execution time.
 
 Here are some hasty tests showing just how big the difference can be:
 
 user= (let [iterations 1] (time (dotimes [_ iterations]
 (identical? [] []))) (time (dotimes [_ iterations] (seq []
 Elapsed time: 3.512 msecs
 Elapsed time: 2512.366 msecs
 nil
 user= (let [iterations 1] (time (dotimes [_ iterations]
 (identical?  ))) (time (dotimes [_ iterations] (seq 
 Elapsed time: 3.898 msecs
 Elapsed time: 5607.865 msecs
 nil
 user= (let [iterations 1] (time (dotimes [_ iterations]
 (identical? () ( (time (dotimes [_ iterations] (seq ()
 Elapsed time: 3.768 msecs
 Elapsed time: 2258.095 msecs
 nil
 
 Has any thought been given to providing a faster `empty?` that is not
 based on seq?
 
 Thanks,
 Eric Kobrin
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en






-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Slogan help

2010-11-13 Thread David Sletten
This is kind of a silly question, but I found this in my Clojure notes from 
last year:
Contemporary
Lisp
Optimized for the
JVM:
Un-
Restricted
Expressiveness

I can't remember whether I created it or I found it somewhere...

Has anyone seen this phrase before? I can't find it on Google.

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Being not Lisp is a feature?

2010-11-09 Thread David Sletten
I don't want to start any language wars, but this is funny:
http://gosu-lang.org/comparison.shtml

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Why isn't there a fold-right?

2010-11-07 Thread David Sletten
You could define a naive 'foldr' like this:
(defn foldr [f coll]
  (if (empty? (rest coll))
(first coll)
(f (first coll) (foldr f (rest coll )

(foldr list '(1 2 3 4)) = (1 (2 (3 4)))
(foldr - [1 2 3 4]) = -2

However, this is not a tail-recursive function and will be limited by the size 
of the stack.

An alternative involves reversing the sequence and applying the function with 
its arguments reversed. Then we can just pretend that we are doing a left fold 
and use 'reduce':
(defn foldr [f coll]
  (reduce (fn [x y] (f y x)) (reverse coll)))

Or for those of you who prefer that other people won't be able to read your 
code:
(defn foldr [f coll]
  (reduce #(f %2 %1) (reverse coll)))

Have all good days,
David Sletten

On Nov 5, 2010, at 10:03 PM, Yang Dong wrote:

 Maybe because Clojure has a vector, and conj conjoins new elements to
 the end of the vector, so there's mere little use of fold-right. But,
 fold-right is an abstraction tool, missing it in the core is kind of
 pity.
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en







-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: figuring out sets

2010-10-31 Thread David Sletten
From a mathematical perspective the essential aspect of a set is its 
extension, namely what elements are contained in the set. This leads 
immediately to the property of uniqueness you mentioned. But the fundamental 
operation is 'contains?'. In other words, does the set contain some object or 
not? 

In order to search a vector to answer this question we have to perform a linear 
search. Thus, the longer the vector, the longer this search could take. In 
Clojure, sets are ultimately constructed out of hash tables, which allows a 
constant time check to see whether an object is a key and therefore a member of 
the set. The fact that the keys in a hash table are unique is a useful side 
benefit, but I believe that an efficient 'contains?' method is the main reason 
for their choice.

All of the other set operations (union, intersection, etc...) are derived from 
our ability to determine whether or not an element is present in some set.

In case you haven't found it yet, there is a section on Sets on the data 
structures page:
http://clojure.org/data_structures
Note especially that you have a choice between hash-set and sorted-set.

Also check out the documentation for clojure.set:
http://clojure.github.com/clojure/clojure.set-api.html

Have all good days,
David Sletten



On Oct 31, 2010, at 10:55 PM, tonyl wrote:

 I guess I should've look harder (and ask more in the irc ;) it is a
 data structure and has a set fn too. #{} is just a reader macro for
 syntactic sugar. And the difference of usage between sets and vectors
 are they sets can't have duplicates.
 This is great, clojure group with irc chat, good learning.
 
 On Oct 31, 9:35 pm, tonyl celtich...@gmail.com wrote:
 I've been wondering if sets are actually a defined data structure like
 vectors and maps or are they a result of an expansion of the dispatch
 macro? I was wondering since it uses the dispatch macro and AFAIK
 there is no api fn to create them like hash-maps to create maps,
 vector/vec for vectors, or list for lists.
 
 Another thing I am trying to figure out is, are they really needed?
 vectors seem to fill in anytime sets could be used, unless I am
 missing something here.
 
 Any information would be appreciated.
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: How to simplify cond statements

2010-10-28 Thread David Sletten
Andrei,

You could just bind another local variable in the loop form:
(loop [ps pairs
   ret {}
   ffps (ffirst ps)]
  (cond (empty? ps) ret
(some-test ffps) (recur (rest ps) (add-to-result ret ffps) (ffirst 
(rest ps)))
:true (recur (rest ps) (do-sth-else ret ffps) (ffirst (rest ps )

I think I like Andrew's solution better though.

But you probably want to use 'reduce' instead of 'loop' anyway:
(reduce (fn [ret [key val]] (if (some-test key) (add-to-result ret key) 
(do-sth-else ret key))) {} pairs)

Notice how you can destructure each pair in a convenient way.

BTW, do you really mean to call 'add-to-result' and 'do-sth-else' with a map 
and a key but no value?

Have all good days,
David Sletten

On Oct 28, 2010, at 8:49 PM, andrei wrote:

 Hi,
 
 I have a code similar to this:
 
 (def pairs (list [1 :a] [2 :b] [3 :c]))
 ...
 (loop [ps pairs, ret {}]
(cond (empty? ps) ret
 (some-test (first (first ps))) (recur (rest ps) (add-to-
 result ret (first (first ps
 :true (recur (rest ps) (do-smth-else ret (first (first
 ps))
 
 You can see that string (first (first ps)), which actually gets first
 element of a first vector in pairs, occur many times. I can't move it
 before cond, since ps may be empty and evaluating of (first (first
 ps)) will produce an error (ok, it won't, but in general case it may).
 Is there another way to simplify code to not repeat one form several
 times?
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en






-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


I eat parentheses for breakfast

2010-10-27 Thread David Sletten
Some of you might enjoy the music video for the new Land of Lisp book:
http://www.youtube.com/watch?v=HM1Zb3xmvMcfeature=player_embedded

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


I eat parentheses for breakfast

2010-10-27 Thread David Sletten
Some of you might enjoy the music video for the new Land of Lisp book:
http://www.youtube.com/watch?v=HM1Zb3xmvMcfeature=player_embedded

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: precise numbers

2010-10-16 Thread David Sletten
Steven,

Thanks for your comments. You bring up some interesting points, however, you 
also raise some more questions.

First, you criticize my use of the variable name 'epsilon'. Of course, this 
usage is entirely consistent with its ubiquitous use in mathematics. I am 
designating a(n) (arbitrarily) small positive number used as a bound on the 
difference of x and y. I am well aware of the more restricted use that you are 
emphasizing:
* (apropos-list 'epsilon)

(DOUBLE-FLOAT-EPSILON DOUBLE-FLOAT-NEGATIVE-EPSILON LONG-FLOAT-EPSILON
 LONG-FLOAT-NEGATIVE-EPSILON SHORT-FLOAT-EPSILON SHORT-FLOAT-NEGATIVE-EPSILON
 SINGLE-FLOAT-EPSILON SINGLE-FLOAT-NEGATIVE-EPSILON EPSILON)

In fact, two articles referenced in this thread also use 'epsilon' in exactly 
the way I have:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
http://adtmag.com/Articles/2000/03/16/Comparing-Floats-How-To-Determine-if-Floating-Quantities-Are-Close-Enough-Once-a-Tolerance-Has-Been.aspx?Page=1

But if you would prefer to use the word 'tolerance' or some such term and 
reserve 'epsilon' (more properly 'machine epsilon') for the concept you have in 
mind, then I'll go along with that (and I won't even complain about you using 
the word 'mantissa' :-) ).

More significantly, your discussion of scaling epsilon (your meaning, I 
presume) got me thinking. Is it strange that we are using a decimal fraction 
for our tolerance? Should we be thinking in terms of a binary fraction, i.e., 
rather than 1/10 we use 1/131072. In other words (Math/pow 2 -17) rather 
than (Math/pow 10 -5):
(Math/pow 10 -5) = 9.999E-6
(Math/pow 2 -17) = 7.62939453125E-6

Or are you saying that we should specifically be scaling (machine) epsilon 
rather than some arbitrary tolerance? As you mentioned this is not as easy in 
Clojure/Java as in Common Lisp.

Could we define 'scaled-epsilon' something like this?
(defn log2 [x]
  (/ (Math/log x) (Math/log 2)))
(def epsilon
 (loop [eps 1.0]
   (if ( (+ eps 1.0) 1.0)
 (recur (* eps 0.5))
 eps)))
(defn scaled-epsilon [x]
  (* epsilon (Math/pow 2 (Math/floor (log2 x )

And finally, what is your response to the OP? You define 'same?' but place 
several caveats on its use. Are you warning that there is no general-purpose 
solution?


Have all good days,
David Sletten

On Oct 16, 2010, at 7:05 PM, Steven E. Harris wrote:

 cej38 junkerme...@gmail.com writes:
 
 (defn float=
  ([x y] (float= x y 0.1))
  ([x y epsilon]
 (let [scale (if (or (zero? x) (zero? y)) 1 (Math/abs x))]
   (= (Math/abs (- x y)) (* scale epsilon )
 
 You're scaling epsilon incorrectly here. Epsilon defines the smallest
 value that yields a value greater than one when added to one. If you're
 not using it along with one, you're using it incorrectly.
 
 What you need to do is scale epsilon by having its exponent match the
 value with which you want to use it, while maintaining its mantissa. The
 C library offers functions ldexp()¹ and frexp()² to split and scale the
 exponent of a floating point number, respectively; Common Lisp offers
 DECODE-FLOAT³ and SCALE-FLOAT for the same purpose.
 
 I don't know of any standard functions in Java -- or Clojure -- that
 allow one to destructure a floating point number like this. It's
 possible to use Float#floatToRawIntBits(), an understanding of IEEE 754,
 and tweezers to get there.
 
 If you assume you have a function called `scaled-epsilon' that accepts
 the exemplar value with which you intend to use epsilon,
 
  (defn scaled-epsilon [n] ...)
 
 you can use the following function `same?' to compare your floating
 point values, assuming they're nonnegative:
 
 ,
 | (defn same?
 |   [m n]
 |   (if ( n m)
 |   (sufficiently-close? n m)
 |   (sufficiently-close? m n)))
 | 
 | (defn- sufficiently-close?
 |   [smaller larger]
 |   (or (zero? larger)
 |   (if (zero? smaller)
 |   ( larger (scaled-epsilon 0.0)))
 |   (zero? (- 1 (/ smaller larger)
 `
 
 Note too that scaling epsilon must take into account whether you intend
 to add it or subtract it from some companion number. It's common to use
 the word epsilon to mean some fudge factor without considering what
 the value really means for a floating point number. Indeed, using it
 properly in Java is still too difficult. 
 
 
 Footnotes: 
 ¹ http://www.dinkumware.com/manuals/?manual=compleatpage=math.html#frexp
 ² http://www.dinkumware.com/manuals/?manual=compleatpage=math.html#ldexp
 ³ 
 http://www.lispworks.com/documentation/HyperSpec/Body/f_dec_fl.htm#decode-float
  
 http://www.lispworks.com/documentation/HyperSpec/Body/f_dec_fl.htm#scale-float
 
 -- 
 Steven E. Harris
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group

Re: precise numbers

2010-10-14 Thread David Sletten

On Oct 14, 2010, at 12:07 PM, cej38 wrote:

 I am kinda sorry that I started this whole thing.  I don't need
 another lesson in limits.  The simple fact of the matter is that, in
 my code, I run into a place where I have a comparison (= some-value
 (some-function some-data)), the function, data, and value can change.
 In a use case that I am interested in, I run into the problem stated,
 
 user= (= 0.0001 (- 12.305 12.3049))
 false
 
 I am OK with replacing the = function with something like float=
 discussed above, but whatever I change it two needs to work.  If
 anyone has found a way, that reliably works, please post it here.
 Further, , , =, and = would also be appreciated.  Thank you.
 
 

If you define 2 of them, then you get the rest for free. We already have float=:
(defn float=
  ([x y] (float= x y 0.1))
  ([x y epsilon]
 (let [scale (if (or (zero? x) (zero? y)) 1 (Math/abs x))]
   (= (Math/abs (- x y)) (* scale epsilon )

If x  y, then in our case x should be more than epsilon below y:
(defn float
  ([x y] (float x y 0.1))
  ([x y epsilon]
 (let [scale (if (or (zero? x) (zero? y)) 1 (Math/abs x))]
   ( x (- y (* scale epsilon ))

(defn float=
  ([x y] (or (float x y) (float= x y)))
  ([x y epsilon] (or (float x y epsilon) (float= x y epsilon

(defn float
  ([x y] (not (float= x y)))
  ([x y epsilon] (not (float= x y epsilon

(defn float=
  ([x y] (or (float x y) (float= x y)))
  ([x y epsilon] (or (float x y epsilon) (float= x y epsilon

Then you determine how strict epsilon needs to be:
(float 12.3049 12.305) = false
(float 12.3049 12.305 1e-6) = true
(float= 12.305 12.3049) = true
(float= 12.305 12.3049 1e-6) = false
(float 12.305 12.3049 1e-6) = true



Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: precise numbers

2010-10-13 Thread David Sletten

On Oct 12, 2010, at 5:44 PM, Brian Hurt wrote:

   For example, in base 10, 1/3 * 3 = 0.9...  

It may seem counterintuitive, but that statement is perfectly true.
1 = 0....

That's a good test of how well you understand infinity.

Of course, the problem arises when we truncate the string of 9's, which we must 
invariably do in a computer-based representation.

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: precise numbers

2010-10-13 Thread David Sletten
Here's a slightly more informal argument. Suppose you challenge me that 1 is 
not equal to 0.... What you are saying is that 1 - 0.... is not equal 
to 0, i.e., the difference is more than 0. But for any positive value 
arbitrarily close to 0 I can show that 0.999... is closer to 1 than that. If 
you were to say that the difference is 0.1, I could show that 0.999...  0.9 so 
the difference is smaller. For every 0 you added to your challenge: 0.1, 0.01, 
0.001 I could provide a counterexample with another 9: 0.9, 0.99, 0.999, ... In 
other words, there is no positive number that satisfies your claim, so equality 
must hold.

Have all good days,
David Sletten

On Oct 13, 2010, at 6:36 PM, Matt Fowles wrote:

 Felix~
 
 You are correct that the sequence of numbers
 
 0.9
 0.99
 0.999
 ...
 
 asymptotically approaches 1; however, the number 0.... (with an infinite 
 number of 9s) is equal to 1.  The formal proof of this is fairly tricky as 
 the definition of the real number is usually done as an equivalence class of 
 Cauchy sequences; a simplified version of the proof can be thought of as 
 follows:
 
 For any two real numbers a and b there exists an infinite number of real 
 numbers c such that a  c  b.  However, there do not exist any numbers 
 between 0.9... and 1, thus they must be same number.
 
 As it turns out, it took mathematicians a long time to nail down formally 
 exactly what we naively think of as numbers.
 
 Matt
 
 On Wed, Oct 13, 2010 at 6:27 PM, Felix H. Dahlke f...@ubercode.de wrote:
 On 13/10/10 22:28, David Sletten wrote:
 
  On Oct 12, 2010, at 5:44 PM, Brian Hurt wrote:
 
For example, in base 10, 1/3 * 3 = 0.9...
 
  It may seem counterintuitive, but that statement is perfectly true.
  1 = 0....
 
  That's a good test of how well you understand infinity.
 
 I'm clearly not a mathematician, but doesn't 0.9... asymptotically
 approach 1, i.e. never reaching it? How is that the same as 1?
 
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: precise numbers

2010-10-12 Thread David Sletten
This discussion may help:
http://www.gettingclojure.com/cookbook:numbers#comparing-floats

Have all good days,
David Sletten

On Oct 12, 2010, at 12:17 PM, cej38 wrote:

 I keep running into this type of problem:
 
 user= (- 12.305 12.3049)
 9.9976694E-5
 
 The computer (probably the JVM) has just lied to me.  Any fourth grade
 student will know that this does not equal 0.0001.  This would be less
 of a problem is the JVM was consistent; if it were consistent then the
 following equality would be true:
 
 user= (= 0.0001 (- 12.305 12.3049))
 false
 
 Now it has lied to me again!
 
 I need a method to reliably compare two numbers.  My first choice
 would be to have the JVM compute (- 12.305 12.3049) correctly.
 Barring that, I need a way to, without fail, compute the truthfulness
 of the following: =, , , =, =.
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en






-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: precise numbers

2010-10-12 Thread David Sletten
I suggest you read the article a bit more closely. Here are the details of your 
specific case.

The number that you are typing as 12.305 is actually being stored in the 
computer as this:
1100.010011110100001011110100001011100

This number is actually this fraction:
1731774794212311/140737488355328

So here is the true value in decimal:
12.304715782905695959

It is not possible to represent 12.305 any closer than that on conventional 
hardware.

Likewise your 12.3049 is this:
1100.01001110110011010010100010001100111001110

Which is this fraction:
3463521440926951/281474976710656

Or in decimal:
12.304848840923025272

This is the best approximation for 12.3049.

When you scale epsilon (0.1) by about 12, you can see that these two 
numbers are equal as expected in the sense defined by float=.

Have all good days,
David Sletten

On Oct 12, 2010, at 2:53 PM, cej38 wrote:

 On Oct 12, 12:50 pm, David Sletten da...@bosatsu.net wrote:
 This discussion may 
 help:http://www.gettingclojure.com/cookbook:numbers#comparing-floats
 
 I originally tried something like float= described in the link, I give
 the definition here
 
 (defn float=
  ([x y] (float= x y 0.1))
  ([x y epsilon]
 (let [scale (if (or (zero? x) (zero? y)) 1 (Math/abs x))]
   (= (Math/abs (- x y)) (* scale epsilon )
 
 And the truth-table that was given with the function definition:
 
 (float= 0.01 0.0) = false
 (float= 0.001 0.0) = false
 (float= 0.0001 0.0) = false
 (float= 0.1 0.0) = true
 
 
 And this works for the problem that I discussed before
 user= (float= 0.0001 (- 12.305 12.3049))
 true
 
 
 But I can come up with a use case where it fails:
 
 user= (float= 12.3049 12.305)
 true
 
 
 The problem is that the IEEE specification does a great job of
 comparing floats, but does a crap job of doing simple math on them.
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Is This Function Idiomatic Clojure?

2010-10-07 Thread David Sletten

On Oct 7, 2010, at 2:29 AM, Stefan Rohlfing wrote:

 Dear Clojure Group,
 
 Following an Enlive tutorial I wanted to implement a function 'd-map'
 that takes an arbitrary number of [:key (list of values)] parameters
 like this:
 
 (d-map [:headline [this is me] ]
   [:points [1 2 3] ]
   [:comments [10 20 30] ])
 
 
 and returns a collection of [:key value] vectors where each value is
 grouped with its respective key:
 
 [ [:headline this] [:headline is] [:headline me]
  [:points 1] [:points 2] [:points 3]
  [:comments 10] [:comments 20] [:comments 30] ]
 
 
 I could only come up with the following implementation for 'd-map'.
 Although it works it just does not 'feel' elegant of even very
 functional:
 
 (defn d-map [ kfps]
  (let [keys (map first kfps)
fns   (map second kfps)]
(loop [keys keys fns fns res []]
  (if (seq keys)
   (recur (rest keys) (rest fns)
   (into res (map (fn [x] [(first keys) x]) (first
 fns
   res

If you treat a map as a sequence it will yield the vectors you are handling 
explicitly:
(map identity {:a [1 2 3] :b [4 5 6]}) = ([:a [1 2 3]] [:b [4 5 6]])

So it might be more convenient to pass in a map and do something like this:
(defn d-map [m]
  (apply concat
 (map (fn [[key val-list]]
(map (fn [val] [key val])
 val-list))
  m)))

(d-map {:headline [this is me]
:points [1 2 3]
:comments [10 20 30]})
([:headline this] [:headline is] [:headline me] [:points 1] [:points 2] 
[:points 3] [:comments 10] [:comments 20] [:comments 30])


Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Attribution in the cookbook

2010-10-06 Thread David Sletten
As I mentioned before, I have no intention of being the sole contributor to the 
Clojure Cookbook site. In a few days we plan to open it up so that anyone may 
contribute recipes (or fix mine :-) ). However, in the meantime I have already 
included a little bit of material from other people.

Specifically I added a couple of examples gleaned from this mailing list:
http://www.gettingclojure.com/cookbook:sequences#winnow

I haven't asked for permission (sorry Adrian and Rich) because I'm not 
presenting the material as my own and it's taken from what's already a very 
public source (which I've indexed). If anyone has a problem with this I will 
remove their content.

I have also incorporated some suggestions made in the comments at the site 
(thanks Sean, matti, and tebeka) without asking permission. Presumably these 
readers added their thoughts for the purpose of improving the examples.

What are your thoughts on this issue? Am I out of line, or is this a reasonable 
policy?

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Changing keys in a map

2010-10-01 Thread David Sletten

On Oct 1, 2010, at 1:57 AM, Sean Corfield wrote:

 On Thu, Sep 30, 2010 at 12:52 AM, David Sletten da...@bosatsu.net wrote:
 Huh?! How many solutions do you want? You're starting to annoy me Sean.
 
 Sorry dude. I think it's really insightful to see lots of different
 solutions to small point problems like this when you're learning a
 language - particularly when the issue of idiom is being discussed.
 I've certainly found this thread educational and I hope I'm not
 annoying too many people :)
 

Sean, Sean...I was just making fun of your signature. :)

Keep up the questions!

 
 If you're not annoying somebody, you're not really alive.
 -- Margaret Atwood

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Changing keys in a map

2010-09-30 Thread David Sletten

On Sep 30, 2010, at 2:53 AM, Baishampayan Ghose wrote:

 I have a need to convert maps in the following ways:
 
 Given a map with keyword keys, I need a map with uppercase string keys
 - and vice versa.
 
 { :stuff 42 :like 13 :this 7 } = { STUFF 42 LIKE 13 THIS 7 }
 
 What about this -
 
 (into {} (for [[k v] { :stuff 42 :like 13 :this 7 }]
   [(.toUpperCase (name k)) v]))
 

One small suggestion based on something Christophe Grand once pointed out:
(defn string-keys [m]
  (into (empty m) (for [[k v] m] [(.toUpperCase (name k)) v])))

(defn keyword-keys [m]
  (into (empty m) (for [[k v] m] [(keyword (.toLowerCase k)) v])))

This will preserve the type of the map.
(string-keys { :stuff 42 :like 13 :this 7 } ) = {THIS 7, LIKE 13, STUFF 
42}
(keyword-keys (string-keys { :stuff 42 :like 13 :this 7 } )) = {:stuff 42, 
:like 13, :this 7}


Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Changing keys in a map

2010-09-30 Thread David Sletten

On Sep 30, 2010, at 3:40 AM, Sean Corfield wrote:

 On Thu, Sep 30, 2010 at 12:30 AM, Mark Engelberg
 mark.engelb...@gmail.com wrote:
 Except that if you use .toUpperCase, you have to remember to type hint
 the input.  Any time you call a Java method without type hinting, you
 take a significant performance hit.  The wrapper function takes care
 of that for you.
 
 Good to know, thanx Mark.
 
 Keep 'em coming folks, this is exactly what I was hoping for when I
 posted the question.
 

Huh?! How many solutions do you want? You're starting to annoy me Sean.

Hmm, I guess you must really be alive. :)

 
 If you're not annoying somebody, you're not really alive.
 -- Margaret Atwood

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: How to write this in Clojure? Example from PAIP

2010-09-29 Thread David Sletten

On Sep 29, 2010, at 3:55 AM, nickikt wrote:

 
 
 (defun find-all (item sequence rest keyword-args
 key (test #'eql) test-not allow-other-keys)
  Find all those elements of sequence that match item,
  according to the keywords.  Doesn't alter sequence.
  (if test-not
  (apply #'remove item sequence
 :test-not (complement test-not) keyword-args)
  (apply #'remove item sequence
 :test (complement test) keyword-args)))
 

Both Clojure and Common Lisp have a function to remove a value from a sequence. 
However, the CL version supports quite a few more options, which accounts for 
the complexity of this FIND-ALL function. 

The function 'remove' in both languages obviously has to take an item to look 
for and a sequence to search. But the CL version also accepts various keyword 
arguments that tailor how it behaves. There is a default test which determines 
whether the item matches a given element, but another test can be specified by 
the :test keyword. This allows for various flavors of equality when matching. 
There is also a :test-not keyword which works in the opposite sense. You can 
see both of those keywords above. The CL version also accepts other keywords 
such as :start, :end, :from-end, :count, and :key.

In the section after the lambda-list keyword key above you can see that 
FIND-ALL also accepts :test and :test-not keywords, with a default :test of the 
function EQL. The lambda-list keyword allow-other-keys is used to show that 
FIND-ALL will also accept the other REMOVE keywords and pass them along.

Before the key section, however, there is the rest section. What actually 
happens is that every argument passed to FIND-ALL, besides the first two 
required arguments, is captured as a list in the variable KEYWORD-ARGS. CL also 
processes the :test and :test-not keyword arguments separately, but they and 
their keywords are also bundled up in KEYWORD-ARGS. This makes it easy to pass 
everything along to REMOVE via the APPLY form.

Here is a Clojure implementation that is pretty true to the spirit of the CL 
version. All of the optional arguments are captured in the list 'keyword-args', 
but we also break out the keywords into a map:
(defn find-all [item coll  keyword-args]
  (let [keywords (apply hash-map keyword-args)]
(if (:test-not keywords)
  (remove (fn [elt] ((:test-not keywords) item elt)) coll)
  (remove (fn [elt] (not ((:test keywords) item elt))) coll


Since we want to find things that match our criterion we reverse the sense of 
the :test and remove things that fail our criterion. But we have to do the 
opposite with the :test-not case here since Clojure's 'remove' doesn't 
understand that :test-not is the opposite of :test. Notice also that we can 
call 'remove' directly (without 'apply') since we aren't passing in a list of 
keywords.
(find-all 1 '(1 2 3 2 1) :test =) = (1 1)
(find-all 1 '(1 2 3 2 1) :test not=) = (2 3 2)
(find-all 1 '(1 2 3 2 1) :test-not =) = (2 3 2)

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: How to write this in Clojure? Example from PAIP

2010-09-29 Thread David Sletten

On Sep 29, 2010, at 11:01 AM, Meikel Brandmeyer wrote:

 Hi,
 
 a slight enhancement for 1.2: Clojure now supports keyword arguments
 directly.
 
 (defn find-all
  [item coll  {:keys [test test-not] :or {test =}}]
  (if test-not
(remove #(test-not item %) coll)
(filter #(test item %) coll)))

That's really nice Meikel. I was trying to remember how to do the new keywords, 
but I couldn't find an example. You have the default value for :test in there 
too. Interesting idea to replace 'remove not' with 'filter'.

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Literal collection of numbers - prefer list or vector?

2010-09-26 Thread David Sletten

On Sep 26, 2010, at 10:42 AM, Steven E. Harris wrote:

 ataggart alex.tagg...@gmail.com writes:
 
 Vectors also permit evaluation of the literal collection's elements:
 
 user= [(+ 1 2) (+ 3 4)]
 [3 7]
 user= '((+ 1 2) (+ 3 4))
 ((+ 1 2) (+ 3 4))
 
 That's a false distinction. You used `quote' rather than
 `list'. Macroexpand your form to see:
 
 ,
 | user (quote ((+ 1 2) (+ 3 4)))
 | ((+ 1 2) (+ 3 4))
 `
 

Umm, kind of...The single quote is a macro character not a real macro. 
Therefore it's not subject to macroexpansion as macros are. Unfortunately the 
Clojure reader normally conspires against you to hide what's really going on. 
The reader silently converts 'pung to (quote pung) prior to evaluation, so you 
have to come at it in a roundabout way:
(read-string '((+ 1 2) (+ 3 4)))  = (quote ((+ 1 2) (+ 3 4)))
(count (read-string '((+ 1 2) (+ 3 4 = 2
(class (read-string '((+ 1 2) (+ 3 4 = clojure.lang.Cons
(first (read-string '((+ 1 2) (+ 3 4 = quote

At least the Clojure printer is cooperating here. In Common Lisp the printer 
helps hide QUOTE too in the first line here:
? (read-from-string '(+ 1 2))
'(+ 1 2)
8
? (first (read-from-string '(+ 1 2)))
QUOTE
? (length (read-from-string '(+ 1 2)))
2

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


ANN: Clojure Cookbook

2010-09-26 Thread David Sletten
Ladies and Gentlemen,

I present for your viewing pleasure the Clojure Cookbook (beta :) ):
http://www.gettingclojure.com/cookbook:clojure-cookbook

Gregg Williams has set up a framework at Getting Clojure to gather material, 
primarily focused on newbies, on how to flatten the learning curve. 

The cookbook is a part of that vision. Inspired of course by O'Reilly's Perl 
Cookbook, the cookbook aims to present concrete examples along with brief 
discussions of specific tasks a new Clojure programmer might want to 
accomplish. The cookbook should complement the existing Clojure books and other 
documentation and provide additional examples that the other resources don't 
have time or space to consider.

At this point I have seeded the cookbook with approximately 20 recipes. I want 
to emphasize that I hope this will be a community resource with others 
providing content or even fixing my explanations where they are incorrect or 
off target. At the moment the cookbook is essentially read-only aside from the 
comments section at the bottom of each page. But once we get a sense of the 
community response the site will be opened for anyone to contribute. 

Please take a look at the site and let us know what works and what needs to be 
fixed. And start thinking up your own recipes.

Thanks.

Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Byte Literals

2010-09-24 Thread David Sletten
Ah, right. Thanks. I'm not keeping up with my Clojure version numbers...

On Sep 24, 2010, at 1:52 AM, Rasmus Svensson wrote:

 There's also 'bytes', 'byte-array' and 'into-array':
 
 (byte-array (map byte [1 2 3]))
 (into-array Byte/TYPE (map byte [1 2 3]))
 
 // raek
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Byte Literals

2010-09-23 Thread David Sletten
I'm not quite sure what you're asking. Clojure doesn't have byte literals, but 
you can use the function 'byte' to coerce an int literal:
(map class [2 3 4]) = (java.lang.Integer java.lang.Integer java.lang.Integer)
(map class (map byte [2 3 4])) = (java.lang.Byte java.lang.Byte java.lang.Byte)

Or you can create a Java byte[] array:
(def a (make-array Byte/TYPE 3))

But you still have to coerce:
(aset a 0 (byte 2)) = 2
(aset a 0 2) =
java.lang.IllegalArgumentException: argument type mismatch (NO_SOURCE_FILE:0)


Have all good days,
David Sletten

On Sep 24, 2010, at 12:31 AM, HiHeelHottie wrote:

 
 Is there a way to create a vector of byte literals eg. [64 69 72] as
 bytes?
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en





-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Little LISPer and Ten Commandments

2010-09-22 Thread David Sletten
That book is amazing. Enjoy working through it, it will stretch your mind.

However, keep in mind that their emphasis is on getting a feel for how 
recursion works. Real world Clojure code (any Lisp really) de-emphasizes 
recursion to some extent. Particularly with regard to list (sequence) 
processing (the name Lisp comes from List processing after all), Clojure has 
a powerful library of functions that handle much of what the book implements 
recursively. For example, if you would like to apply a function f to each 
element in a list you could write code similar to the book:
(defn my-map [f l]
  (cond (empty? l) '()
:else (cons (f (first l)) (my-map f (rest l )

(my-map inc '(1 2 3 4 5)) = (2 3 4 5 6)

Here we apply the First Commandment--is the list l empty? If so, return an 
empty list. Otherwise, apply the function to the first element of the list and 
recursively process the rest of the list.

We could accomplish the same thing more succinctly in Clojure like this:
(map inc '(1 2 3 4 5)) = (2 3 4 5 6)

Clojure has a built-in 'map' function which iterates over each element in a 
sequence, not merely lists:
(map dec [2 4 6 8]) = (1 3 5 7)
(map #(Character/toUpperCase %) Is this not pung?) = (\I \S \space \T \H \I 
\S \space \N \O \T \space \P \U \N \G \?)

Furthermore, the book is pretty much using a dialect of Lisp called Scheme, and 
the semantics are a little different from Clojure. For instance, Clojure does 
not have the concept of 'atom'.

It may actually be easier to work through the book in a Scheme environment (I 
used Common Lisp though). But what you learn there will help you later with 
Clojure.

In fact, if you are brave here is some of the material from chapter 9 dealing 
with the Y-Combinator implemented in Clojure. It's pretty weird:
http://groups.google.com/group/clojure/browse_thread/thread/c9bd4e79e5877a66

Have all good days,
David Sletten

On Sep 21, 2010, at 6:38 PM, ax2groin wrote:

 Newbie here, to both LISP and Clojure. A friend has lent me a copy of
 The Little LISPer and I've started working through it, using some
 web resources to translate it into clojure.
 
 My questions: How relevant are the ten commandments? What modification
 need to be made ... either to the commandments or to your code in
 clojure?
 
 I ask because the first commandment (always ask null?) hasn't
 translated directly into any single statement for me. I can achieve
 the same with (or) to navigate the difference between nil and () in
 clojure, but sure that difference is in there for a reason.
 
 Any other input on the other commandments or using the book in
 general?
 
 Thanx
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en







-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: misunderstanding collection

2010-08-25 Thread David Sletten
Hi Glen,

You have two separate problems here. The question of understanding collections 
isn't really that tricky. Your variable 'signals' is simply a 2-element list. 
Conceptually it's no different than: (a b). But in your case each element is 
itself a 3-element list. An equivalent would be: ((a b c) (d e f)). But again, 
in your case, each of those 2nd-level elements is itself a 4-element list. So 
your list has 3 levels with numbers at the bottom.

If you map across signal, you will handle the two 3-element lists:
(map count signal) = (3 3)

To get to the next level, we need another map:
(map (fn [level-1] (map count level-1)) signal) = ((4 4 4) (4 4 4))

Finally, we can get to the numbers themselves:
(map (fn [level-1] (map (fn [level-2] (map class level-2)) level-1)) signal) = 
(((java.lang.Integer java.lang.Integer java.lang.Integer java.lang.Integer) ...

Let's take a look at the second problem before we finish above. Your example 
with 'reduce' is:
(map #(map reduce + %) signal)

But we can't bundle it that way. 'reduce' is a 2-arg (optionally 3-arg) 
function, however, you are asking 'map' to apply 'reduce' to the 2 sequences 
'+' and the value of '%'. Of course, '+' is not a sequence. What you need 
instead is this:
(map #(map (fn [coll] (reduce + coll)) %) signal) = ((10 14 18) (18 22 26))

Now 'reduce' takes each of the sublists in '%' as an arg and does its work.

You might find it easier to work with such nested structures by using named 
functions to process each level. Or at the very least be careful about choosing 
names and layout:
(map (fn [level-1]  


   
 (map (fn [level-2] (reduce + level-2)) 


  
  level-1)) 


  
  signal) 

That's a lot easier for me to understand.

Have all good days,
David Sletten

On Aug 25, 2010, at 10:06 AM, Glen Rubin wrote:

 After toying around at the REPL I realize that I have been working
 with a heretofore invalid understanding of collections.  For example,
 working with the following collection(s):
 
 signal:
 (((1 2 3 4) (2 3 4 5) (3 4 5 6)) ((3 4 5 6) (4 5 6 7) (5 6 7 8)))
 
 I wanted to sum each individual list: e.g. (1 2 3 4) = (10)
 
 I thought I could do this as follows:
 
 (map #(map reduce + %) signal)
 
 This resulted in an error, so trying to comprehend why I ran the
 following:
 
 (map #(map identity (take 1 %)) signal)
 
 which results in,
 (((1 2 3 4)) ((3 4 5 6)))
 
 So, clojure sees 'signal' as 2 collections, whereas I thought it was a
 single collection.  This makes me concerned that I have been doing
 everything wrong thus far and getting computational errors. :(  So,
 how should I sum each individual list in the above collections?
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en






-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: trouble using nested map fn

2010-08-23 Thread David Sletten
There may be some value in the intellectual exercise to try something like your 
solution, but I think this is far more tractable if you use meaningful variable 
names:
(map (fn [group scalars] (map (fn [trial] (map (fn [signal scalar] (* signal 
scalar)) trial scalars)) group)) signal target)

You have one top-level list in 'target' for each top-level list in 'signal', so 
clearly the outer map must pair them. However, you want each 'target' sublist 
to be applied to several sublists, so you need the next map to iterate across 
the 2nd-level lists in 'signal'. Finally, the innermost map must do the actual 
work pairing each 'signal' and 'scalar'.


Have all good days,
David Sletten

On Aug 23, 2010, at 11:26 AM, Glen Rubin wrote:

 I am trying to write a fn to correlate 2 signals using 3 nested map
 fn.  I have 2 collections of data.  THe first group of signals called
 target looks something like this.
 
 
 target:
 ( (1,2,3,4) (2,3,4,5) ...)
 
 
 The second collection is called signal and looks like this:
 
 signal:
 ( ((1,2,3,4)(2,3,4,5)(3,4,5,6)) ((2,3,4,5)(3,4,5,6)(4,5,6,7)) ... )
 
 
 I would like to take the first list in target and multiply it by
 every list in the first group of signal.  And then continue on
 processing the second list, etc...
 
 which would result in something like:
 
 ( ((1,4,9,16)(2,6,12,20)(3,8,15,24)) ((4,9,16,25) (6,12,20,30)
 (8,15,24,35)) ... )
 
 I try a nested map fns like this, but can't get it to work:
 
 
 (map #(map #(map * %1 %2) %1 %2) target signal)
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en






-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Simple Regex Question

2010-08-21 Thread David Sletten
Does this make the processing a little clearer?
#(?=([ ab]))?([ab])\2*

Have all good days,
David Sletten

On Aug 21, 2010, at 10:02 PM, CuppoJava wrote:

 Wow that's so short! Thanks Chouser! I will abstain from showing the
 awful hack that I've been working with currently.
  -Patrick
 
 On Aug 21, 8:45 pm, Chouser chou...@gmail.com wrote:
 On Sat, Aug 21, 2010 at 7:11 PM, CuppoJava patrickli_2...@hotmail.com 
 wrote:
 Hi Everyone,
 
 I'm extremely stuck on this simple regex question, which I'm sure
 someone with a little more experience will be able to write in a
 second. I would really appreciate the help.
 
 Given a string consisting of a's, b's, and spaces:  aaa bbb abb ab
 bb
 
 I want to tokenize this into string's of a's and b's.
  eg. aaa, bbb, a, bb, a, b, bb
 
 AND also, I have to be able to tell which of the strings of b's was
 preceded with an a, and which was preceded by a space.
 
 (- aaa bbb abb ab bb
   (re-seq #(?=(.))?(\w)\2*)
   (map (fn [[s pre]] {:s s, :pre pre})))
 
 returns a lazy seq:
 ({:s aaa, :pre nil}
  {:s bbb, :pre  }
  {:s a, :pre  }
  {:s bb, :pre a}
  {:s a, :pre  }
  {:s b, :pre a}
  {:s bb, :pre  })
 
 --Chouserhttp://joyofclojure.com/
 



-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: [noob] Using dochars

2010-08-20 Thread David Sletten
Hi Mark,

What the documentation means is that you give dochars a name for a variable 
and a string to process. It then iterates over each character in the string 
using 'name' as a variable representing the character, so that each of the (0 
or more) forms in the body can do something with the character by referring 
to name:
(dochars [ch Is this not pung?]
  (print (Character/toUpperCase ch)))

However, what you probably want to do is use 'map' to transform one string to 
another:
(map (fn [ch] (Character/toUpperCase ch)) Is this not pung?) = (\I \S \space 
\T \H \I \S \space \N \O \T \space \P \U \N \G \?)

But now we've wound up with a sequence rather than a string specifically, so we 
need one more step:
(apply str (map (fn [ch] (Character/toUpperCase ch)) Is this not pung?)) = 
IS THIS NOT PUNG?

Have all good days,
David Sletten

On Aug 20, 2010, at 4:25 AM, probertm wrote:

 Hi...
 
 New here to Clojure-land and loving what I am seeing, though I am not
 getting some of the forms yet.
 
 Can someone help me with contrib.str-utils2/dochars?  I have a need to
 iterate over each character in a string and this seems to be a macro
 that will do that (I suppose I could create my own map function but
 that kind of misses the point ;) ).
 
 The doco says
 
  Usage: (dochars bindings  body)
  bindings = [name string]
  Repeatedly executes body, with name bound to each character in
 string.
 
 which I don't really understand.  Any examples gratefully accepted.
 
 TIA .. mark.
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: questions about float operations

2010-08-20 Thread David Sletten
This may help explain things:

http://groups.google.com/group/clojure/msg/325228e8b66923ac

Have all good days,
David Sletten

On Aug 20, 2010, at 8:26 AM, bufo wrote:

 I am currently learning clojure by reading The Joy of Clojure and I
 have 2 questions on float opertions:
 
 - why does (+ 4.2 8.4) return 12.601 and (+ 1.5 2.6) 4.1?
 Since 4.2, 8.4 and (+ 4.2 8.4) are java Doubles why does it not behave
 as expected? What does clojure do in the background?
 
 - I also have a question regarding float precison in big operations,
 consider the following code:
 (defn ope [a b] (+ a (* b (Math/sqrt b
 
 (reduce ope (range 100))
 3.9501039E14
 
 vs
 
 (loop [i 1 x 0]
  (if ( i 100)
x
(recur (inc i) (ope x i
 4.0501039E14 (which is what we get if we do a for loop in
 java)
 
 I had the same problem in haskell, why are the two results different?
 
 Thanks in advance!
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en





-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Please help! Really simple function not working.

2010-08-10 Thread David Sletten
Carlos,

I think this is pretty much what you had in mind:
(defn count-zeros [l]
  (cond (empty? l) 0
(zero? (first l)) (inc (count-zeros (rest l)))
:else (count-zeros (rest l

(count-zeros '(9 8 6 0 1 2 0 5)) = 2
(count-zeros '(9 8 6)) = 0
(count-zeros '()) = 0

Of course the above version is not tail-recursive. However, once you're written 
a straightforward recursive function it is often easy to see how to rewrite it 
(using an accumulator here) to take advantage of Clojure's recur:
(declare count-zeros-aux)

(defn count-zeros [l]
  (count-zeros-aux l 0))

(defn- count-zeros-aux [l result]
  (cond (empty? l) result
(zero? (first l)) (recur (rest l) (inc result))
:else (recur (rest l) result)))

Here the base function presents the same interface to the user, and the private 
auxiliary function takes an additional accumulator argument.

You could accomplish pretty much the same thing by defining two versions with 
different arities:
(defn count-zeros
  ([l] (count-zeros l 0))
  ([l result]
 (cond (empty? l) result
   (zero? (first l)) (recur (rest l) (inc result))
   :else (recur (rest l) result

Or you could simplify things by using loop:
(defn count-zeros [l]
  (loop [num-list l
 result 0]
(cond (empty? num-list) result
  (zero? (first num-list)) (recur (rest num-list) (inc result))
  :else (recur (rest num-list) result

Have all good days,
David Sletten

On Aug 9, 2010, at 8:24 PM, Carlos Torres wrote:

 Hi to everyone,
 
 I'm trying to create a function that takes a simple list and returns the 
 number of zeros in the list.
 So I'm assuming that they will enter a list containing only numbers.
 This is what I have so far, but it only works when the list empty. Can 
 somebody tell me what I'm missing?
 
 (defn count-zeros
   Returns the numbers of zero in a simple sequence of numbers
   [list1]
   (cond
 (empty? list1) 0
 (not (zero? (first list1))) 0
 :else
 (recur (+ 1 (count-zeros (rest list1))
 
 --Carlos
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en







-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: noob q: infinite loop recur

2010-08-10 Thread David Sletten

On Aug 9, 2010, at 11:52 PM, chepprey wrote:
 
 (defn show [words]
   (let [word (first words)]
   (do
   (println word)
   (if (nil? word)
   (println DONE)
   (recur (rest words))
 
 (show '(some sample words))
 
 ... this shows the 3 words, then DONE, and terminates.

Your program works but maybe not the way you think it does. The first issue is 
related to an idiosyncrasy of other Lisps compared to Clojure. It's easy to 
understand the basic behavior of 'first' and 'rest':
(first '(a b c)) = a
(rest '(a b c)) = (b c)

However, what happens when we look at the empty list?
(first '()) = nil
(rest '()) = ()

Notice how Clojure returns two different values here. Other Lisps (such as 
Common Lisp) define FIRST/REST of the empty list to both be NIL (i.e., the 
empty list itself). So it is common in other Lisps to test for the end of a 
list using the equivalent of 'nil?', namely the function NULL. But in Clojure 
if we are traversing a list and looking for the end, the correct function is 
'empty?'. 
(nil? '()) = false
(empty? '()) = true

Furthermore, in your example you are testing whether the current first element 
is nil rather than checking that the list itself is empty. Your test should be 
(if (empty? words) ...). Your program eventually terminated because once your 
list was empty the first element was evaluated to be nil as above.

 
 But originally, I was trying to use loop/recur.  If I replace the
 let with loop in the above code, it goes into an infinite loop.  I
 assume there's something different in the scoping/binding rules with
 loop, but I can't find a good explanation of what.  I read in
 Programming Clojure, regarding loop, that it ...works like let,
 establishing bindings and then evaluating exprs...
 

This is a separate issue. It is true that 'loop' establishes bindings, however, 
it is your responsibility to update those bindings on each iteration through 
the loop by means of the 'recur' form. Your 'recur' confuses the distinction 
between the variables 'words' and 'word'. On the initial loop iteration, the 
variable 'word' is assigned the value of the first element of 'words'. But on 
the next iteration (and all others) your recur passes the rest of 'words' as 
the new value of 'word'. So in your example we wind up with this:
1. word - some
2. word - (sample words)

Obviously this 2-element list is never 'nil?', and the recur form keeps 
reassigning the same value forever.

Instead, you need to rebind the variable 'words' to subsequent tails of the 
original list:
(defn show [words]
  (loop [l words]
(println (first l))
(if (empty? l)
  (println DONE)
  (recur (rest l)

And you probably want to test for the end of list before you print anything:
(defn show [words]
  (loop [l words]
(if (empty? l)
  (println DONE)
  (do
(println (first l))
(recur (rest l ))



Have all good days,
David Sletten




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: shortcut for for comprehension

2009-04-21 Thread David Sletten


On Apr 20, 2009, at 12:19 PM, Michael Hunger wrote:


 Is it possible to use :while to shortcut a for macro when a certain  
 number of yiels have happened?

 e.g. (for [x (range 1000) :when (= (rem x) 1) :while (number of  
 yields = 10)]

 so i want only the first 10 results.

Is it possible? Yes...
(let [yields (ref 0)]
   (for [x (range 1000) :when (when (odd? x) (dosync (ref-set yields  
(inc @yields))) true) :while (= @yields 10)] x)) =
(1 3 5 7 9 11 13 15 17 19)

Is it advisable? No.


 Or should I just use (take 10 ) on the for ?

Definitely yes.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: howto update with a constant when a function is expected?

2009-04-16 Thread David Sletten


On Apr 15, 2009, at 11:30 PM, bOR_ wrote:


 Hi all,

 some functions (like map, or update-in) expect a function to be
 applied on a value. In the case where the update I want is merely a
 constant, is there a short way to write it?

 (map (fn [n] :new) (list :old1 :old2 :old3))  works

 (map :new (list :old1 :old2 :old3)) unfortunately doesn't work in the
 way I would hope (gives nil nil nil)


There are a number of possible answers here depending on what you're  
trying to do. The one that corresponds literally to your approach is  
this:
(map (constantly :new) (list :old1 :old2 :old3))
'constantly' creates a function which simply ignores its arguments  
and returns the value provided.

But if all you are really doing is creating a sequence of a given  
length containing a constant element, then this is more straightforward:
(repeat (count (list :old1 :old2 :old3)) :new)

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: howto update with a constant when a function is expected?

2009-04-16 Thread David Sletten


On Apr 16, 2009, at 1:57 AM, bOR_ wrote:


 (fn [n] :new) or (constantly :new) was what I was looking for.

 Just found out the two are not exactly the same. Hmm. I guess I should
 have expected this from the docstring. Anyway, thanks all!

 Clojure= (map (constantly (ref nil)) (range 10))
  50 (#Ref clojure.lang@1417690 #Ref clojure.lang@1417690
 #Ref clojure.lang@1417690 #Ref clojure.lang@1417690 #Ref
 clojure.lang@1417690 #Ref clojure.lang@1417690 #Ref
 clojure.lang@1417690 #Ref clojure.lang@1417690 #Ref
 clojure.lang@1417690 #Ref clojure.lang@1417690)

  51 Clojure= (map (fn [n] (ref nil)) (range 10))
  52 (#Ref clojure.lang@1e32382 #Ref clojure.lang@1304043
 #Ref clojure.lang@cb07ef #Ref clojure.lang@176086d #Ref
 clojure.lang@234265 #Ref clojure.lang@dc1f04 #Ref
 clojure.lang@1784427 #Ref clojure.lang@c272bc #Ref
 clojure.lang@1fac852 #Ref clojure.lang.Ref...@1758cd1)



In that case, here's something that reads more clearly to me:
(take 10 (repeatedly #(ref nil))) =
(#r...@66036e: nil #r...@6b6b13: nil #r...@42c747: nil  
#r...@2943ff: nil #r...@2f4fc5: nil #r...@1e4683: nil  
#r...@a761ce: nil #r...@622e6: nil #r...@2689a7: nil #r...@173b39:  
nil)

Also, in your second example above, I think it's more idiomatic to  
write (fn [_] (ref nil)) to demonstrate that you're ignoring the  
argument.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Fixing Documentation Errors

2009-04-07 Thread David Sletten

What is the mechanism for reporting errors in documentation?

For instance, the doc string is in the wrong place for 'rational?'.  
And 'quot' and 'rem' take parameters 'num' and 'div', but the  
documentation talks about denominators rather than divisors.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Simple dosync/alter question

2009-04-06 Thread David Sletten


On Apr 6, 2009, at 9:02 AM, bgray wrote:


 I have a some what (I believe) easy question.  Could someone let me
 know what I'm doing wrong?  A simplified version of what I'm trying to
 do looks like this:

 user= (def foo (ref 0))
 #'user/foo
 user= (defn square [x] (* x x))
 #'user/square
 user= (defn square-ref [x] (dosync (alter foo square x)))
 #'user/square-ref
 user= (square-ref 2)
 java.lang.IllegalArgumentException: Wrong number of args passed to:
 user$square (NO_SOURCE_FILE:0)


Paul and David N. have already given you the right advice. But to  
help you understand why your square-ref function didn't work, compare  
it to this:
(defn square-ref [x] (dosync (alter foo (fn [_] (square x)

Do you see the difference?

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Nested loops

2009-04-04 Thread David Sletten

I'm working on a spell checker that attempts to suggest corrections  
from a given dictionary. One of the heuristics is to see if inserting  
a character at each point in the given string results in a recognized  
word. So I have an outer loop that moves across each position in the  
string and an inner loop that tests a-z at that point. In Common Lisp  
I use this:
(defun word-insertion (s)
   (let ((s1 (make-string (1+ (length s)   ; Copy the input and  
make room for an extra char
 (setf (subseq s1 1 (length s1)) s)
 (dotimes (i (length s1) nil)  ; Outer loop
   (unless (zerop i) (setf (char s1 (1- i)) (char s (1- i
   (dotimes (j (1+ (- (char-code #\z) (char-code #\a   ;  
Inner loop
 (setf (char s1 i) (code-char (+ j (char-code #\a
 (let ((index (binary-search s1))) ; Check in the  
dictionary for a match
   (when index (return-from word-insertion index )));  
Done if match found

The main point is that I can use two DOTIMES forms, one nested inside  
the other, and I can exit either at any point. I actually exit the  
entire function as soon as I find a match via RETURN-FROM.

Clojure has 'dotimes', but from what I understand there is no way to  
exit prematurely?

The obvious alternative is to nest a couple of 'loop' forms:
(defn g [p q]
   (loop [i 0]
 (if (= i p)
   nil
   (do
 (loop [j 0]
   (if (= j q)
 nil
 (do
   (prn (list i j))
   (recur (inc j )
 (recur (inc i ))

The loop/recur pairs seem to establish outer and inner recursion  
points (I can't really tell from the macro expansion), and this  
function behaves as expected. This approach appears to be equivalent  
to something like this:
(defn f [p q]
   (letfn [(outer [i]
 (if (= i p)
   nil
   (do
 (inner i 0)
 (outer (inc i )
   (inner [i j]
 (if (= j q)
   nil
   (do
 (prn (list i j))
 (inner i (inc j )]
 (outer 0)))

Again the important thing is that I can terminate the inner loop  
based on my own condition. However, it seems that in the outer loop I  
have to capture the value of the inner loop directly. I can't simply  
leave both loops:
(defn word-insertion [s]
   (let [s1 (make-array Character/TYPE (inc (count s)))]
 (System/arraycopy (.toCharArray s) 0 s1 1 (count s))
 (loop [i 0]
   (if (= i (count s1))
 nil
 (do
   (when-not (zero? i)
 (aset s1 (dec i) (nth s (dec i
   (let [match (loop [j 0]
 (if (= j (inc (- (int \z) (int \a
   nil
   (do
 (aset s1 i (char (+ j (int \a
 (let [match (binary-search (String. s1))]
   (if match
 match
 (recur (inc j )))]
 (if match
   match
   (recur (inc i  )

One other version I considered makes due with a single 'loop', but  
this is pretty convoluted:
(defn word-insertion [s]
   (let [s1 (make-array Character/TYPE (inc (count s)))]
 (System/arraycopy (.toCharArray s) 0 s1 1 (count s))
 (loop [i 0
j 0]
   (when (and (not (zero? i))
  (zero? j))
 (aset s1 (dec i) (nth s (dec i
   (cond (= i (count s1)) nil
 (= j (inc (- (int \z) (int \a (recur (inc i) 0)
 :else (do
 (aset s1 i (char (+ j (int \a
 (let [match (binary-search (String. s1))]
   (if match
 match
 (recur i (inc j  )

The one nice thing about this is I can terminate the entire loop and  
return a value in one step. Otherwise the logic is a mess.

Any suggestions out there?

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Nested loops

2009-04-04 Thread David Sletten


On Apr 4, 2009, at 6:18 PM, Mark Triggs wrote:


 Hi David,

 Quite a few times when I've felt the need for this sort of thing I've
 found that laziness comes to the rescue.  Would something like this
 sort of approach work for you?

 (defn possibilities [word pos]
   All variations of `word' with letters from 'a' to 'z' inserted at
 `pos'
   (let [[beg end] (split-at pos word)
   letters (map char (range (int \a) (inc (int \z]
 (map #(apply str (concat beg [%] end)) letters)))

 (defn all-possibilities [word]
   (for [n (range (inc (count word)))
   pos (possibilities word n)]
 pos))

 ;; Since all-possibilities produces a lazy seq we don't need short
 circuiting anyway...
 (some #(binary-search word) (all-possibilities hello))



Mark and Jim,

Thanks for your responses. You both make an excellent point about  
functional code not often needing explicit loops (and even being a  
sign of design problems). My example is decidedly non-functional (I  
don't really like that term...My code works--it does function! :-) ).  
It was kind of a first cut in a more imperative style because I  
thought it might be more efficient destructively modifying a char  
array rather than copying lots of substrings. I intended to attempt a  
more functional version next.

I was more curious about the general case, but you guys may be right  
that nested loops just aren't needed.

Your example looks useful, Mark. In fact, for the real program I do  
want to collect all possible suggestions rather than terminating with  
the first one. So I'll be dealing with sequences anyway.

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Advanced Practical Recursion in Lisp 1.0

2009-04-01 Thread David Sletten
 [future]
(m (fn [arg]
 ((future future) arg
  (fn [future]
(m (fn [arg]
 ((future future) arg ))
   (fn [rec]
 (fn [l]
   (if (empty? l)
 0
 (inc (rec (rest l )))
  '(a b c d e))
= 5

And 'reverse':
(((fn [m]
 ((fn [future]
(m (fn [arg]
 ((future future) arg
  (fn [future]
(m (fn [arg]
 ((future future) arg ))
   (fn [rec]
 (fn [l]
   (cond (empty? l) '()
 (empty? (rest l)) (list (first l))
 :else (cons (first (rec (rest l)))
 (rec (cons (first l)
(rec (rest (rec (rest l  )))
  '(a b c d e))
= (e d c b a)

Breathtaking in its elegance!

I'm going to move forward with the negotiations, but I need to know  
if you, the Clojure community, are on board here. Ultimately the  
decision is going to come down to whether or not you find the APRiL  
1.0 technology useful. Try it out and let me know your opinions.

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Trying to get a list of random numbers using repeat

2009-03-24 Thread David Sletten


On Mar 23, 2009, at 10:36 PM, Paul Drummond wrote:


 2009/3/24 Joshua Fox joshuat...@gmail.com:
 Why presumably with side effects?
 Otherwise you would use repeat. A pure  function returns the same  
 value
 every time, so there is no reason to call it repeatedly.

 Yup, that makes sense.

 Random numbers are side-effecting (is that the right term?) and I was
 trying to think about the (simple) problem in a pure functional way
 which was getting my simple brain all confused!


It's not obvious what side effect is occurring by calling rand-int,  
but in fact the state of the pseudorandom generator is affected by  
each call. This is from java.util.Random. Everybody calls next()  
sooner or later, and it calls the compareAndSet() method:

* This is a linear congruential pseudorandom number generator, as
  * defined by D. H. Lehmer and described by Donald E. Knuth in  
iThe
  * Art of Computer Programming,/i Volume 2: iSeminumerical
  * Algorithms/i, section 3.2.1.
protected int next(int bits) {
 long oldseed, nextseed;
 AtomicLong seed = this.seed;
 do {
 oldseed = seed.get();
 nextseed = (oldseed * multiplier + addend)  mask;
 } while (!seed.compareAndSet(oldseed, nextseed));
 return (int)(nextseed  (48 - bits));
 }

As Joshua pointed out, whenever a function returns different values  
given the same args that's a good sign that a side effect has  
occurred--some state has obviously changed.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Information Hiding

2009-03-23 Thread David Sletten


On Mar 22, 2009, at 10:27 PM, Mark Engelberg wrote:


 I've been thinking quite a bit about the OO side of Clojure the past
 couple of days, and trying to figure out how common OO design patterns
 would look when ported over to Clojure's way of doing things.

 The most obvious thing that others have noted is that you can
 effectively simulate a mutable object by having a ref that holds a
 hash map.  You can then write getters and setters, and other kinds of
 supporting functions that use and manipulate the ref, and the hash map
 contained therein.  But as far as I can tell, there's no way to stop a
 client from simply dereferencing the ref and extracting or
 manipulating the private information in the hash map and shoving it
 back into the ref.  Even if you trust a client to do the right thing,
 if the object is complex, it might be hard for other programmers to
 figure out which properties are meant to be manipulated, and which are
 off-limits.

 I suspect that if you use double-colon keywords for the keys, you get
 a bit more privacy in the sense that these keys are slightly harder to
 accidentally manipulate from other namespaces, so perhaps that could
 at least be an informal convention for this is private.  Or perhaps
 it's better to keep as much private data in the metadata as possible
 (although I would think that in many cases, the private data would
 still be essential to the notion of equality).  Any other tricks or
 techniques for helping to hide or separate out the portions of a data
 structure that are meant to be accessed or altered from the portions
 that should only be accessed and changed by the existing support
 functions?


One simple (simplistic?) way to guarantee privacy is through closures:
(defn make-person [first-name last-name age sex]
   (let [age (ref age)]
 {:first-name (fn [] first-name)
  :last-name (fn [] last-name)
  :sex (fn [] sex)
  :age (fn [] @age)
  :set-age (fn [new-age] (dosync (ref-set age new-age)))}))

person= (def me (make-person David Sletten 39 male))
#'person/me
person= ((me :first-name))
David
person= ((me :last-name))
Sletten
person= ((me :age))
39
person= ((me :set-age) 40)
40
person= ((me :age))
40

There's no way to manipulate the age ref except through the :set-age  
function.

This may not scale though if every 'object' carries around its own  
set of all the methods.

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Month/Day names

2009-03-23 Thread David Sletten

Is there a simpler way to do this?

(defn get-months []
   (drop-last (.getMonths (java.text.DateFormatSymbols.

(defn get-weekdays []
   (drop 1 (.getWeekdays (java.text.DateFormatSymbols.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread David Sletten


On Mar 23, 2009, at 5:24 AM, Jeff Valk wrote:


 On Mon, 23 Mar 2009 at 03:29, Mark Engelberg wrote:

 But it traverses m twice, which is likely to be less efficient.

 I wondered about this too, and actually no.

I think Mark was referring to the call to 'keys'. But apparently  
Clojure doesn't need to traverse the map to generate the keys?

 Zipmap is efficient. It constructs its return map in a single loop  
 from two lazy seqs.

Not sure what you mean here. It will produce a map from any 2 seqs.  
And it does not generate it lazily--it uses loop. Don't try this at  
home:
(zipmap (map str (iterate inc 1)) (iterate inc 1))


Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Calling `str' on a LazySeq

2009-03-22 Thread David Sletten


On Mar 21, 2009, at 1:44 PM, Mark Triggs wrote:

   user= (str (filter even? (range 1 10)))
   clojure.lang.lazy...@f1005

 Previously this would readably print the contents of the seq and some
 of my code was relying on this.  Obviously it's not difficult to call
 `prn-str' myself, but I just wondered if this change was made
 consciously.


According to the documentation for 'str':
With one arg x, returns x.toString().

So it looks like toString() on a sequence used to return its contents  
and now doesn't. However, rather than relying on this behavior what  
you probably should be doing is using 'apply':
(apply str (filter even? (range 1 10))) = 2468

If you want commas between those elements, use 'interpose':
(apply str (interpose ,  (filter even? (range 1 10 = 2, 4, 6, 8

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Calling `str' on a LazySeq

2009-03-22 Thread David Sletten

On Mar 21, 2009, at 11:30 PM, Mark Triggs wrote:


 Yep, that's fine.  In my case I was actually relying on the fact that
 `str' was effectively doing a `prn-str' because I would later read it
 back using `read-string' elsewhere.  Calling `prn-str' explicitly
 isn't a problem--I just thought I'd mention that the semantics have
 now changed a little.


Sorry Mark. I guess I misunderstood what 'prn-str' does. I thought it  
was for I/O. I missed the print TO string part.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: 08 and 09 are invalid numbers, but 01 through 07 are fine?

2009-03-15 Thread David Sletten


On Mar 15, 2009, at 4:53 PM, Aaron Brooks wrote:


 Rather than going to the horrible effort /irony of looking up to see
 if Clojure had support for binary notation, I had a Clojure prompt so
 I just tried it and got semi-surprising results:

 user= #b010001
 java.lang.Exception: No dispatch macro for: b
 4097

 I'm not surprised that Clojure complains of not knowing what manner of
 macro #b is but I was impressed (?) that it still yielded the correct
 value. Somewhere, deep in Clojure's little heart, it wants to do other
 bases.


Umm, that's not really the correct value. Clojure gave you octal  
010001 - 4097 not binary 010001 - 17

Sorry,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: 08 and 09 are invalid numbers, but 01 through 07 are fine?

2009-03-13 Thread David Sletten


On Mar 13, 2009, at 3:07 AM, Michael Wood wrote:

 This is pretty standard behaviour.

 On the other hand, it's not universal.

 sbcl:

 * 07

 7
 * 08

 8


Common Lisp uses a separate syntax for binary/octal/hex literals. Legal:
#b1011, #o377, #xDEADBEEF, #36rZZZ (Base 36 anyone?)
Illegal:
#b2, #o8, #xQUICKSAND

(Of course, #36rCLOJURE = 27432414842 :-) )

Aloha,
David Sletten



--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Two quick questions on functions...

2009-03-10 Thread David Sletten


On Mar 9, 2009, at 11:11 PM, Rich wrote:
 1) You must define a method before you call it from another function.
 Stylistically, I prefer to define helper functions after the main
 function, but that seems to cause errors. If I move them in front of
 the main function, the errors go away. I don't know if there's some
 way to declare the methods before you define them (like C header
 files).


Don't know about this one. It's been bugging me too.

 2) To have two or more functions with the same name and a different
 arity, you must define them in a single (defn...).


Correct.

 For example, the following code:

 (defn good
   ([a] (println (str argument:  a)))
   ([a, b] (println (str arguments:  a ,  b

 (defn bad [a] (str argument:  a))
 (defn bad [a b] (str arguments: a ,  b))


 (good foo)
 (good foo bar)
 (bad foo)
 (bad foo bar)

 Generates the following output:

 argument: foo
 arguments: foo, bar
 Exception in thread main java.lang.IllegalArgumentException: Wrong
 number of args passed to: core$bad (SandBox.clj:0)

 This crops up when I have a function that was created using a  
 function-
 building macro, and I wanted to define a wrapper with the same name
 that allowed me to enter the arguments in a simpler manner.

 Also, it just feels odd. You don't get an error when defining the  
 same-
 named function--but suddenly neither version works. That's a pretty
 serious side-effect. So maybe this is just a bug?


What happens if you flip you 2 tests of bad. (I'll bet it's exactly  
what you expect to happen.)

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: letfn - mutually recursive local functions

2009-03-10 Thread David Sletten


On Feb 28, 2009, at 2:38 PM, Rich Hickey wrote:


 I've added letfn, which lets you define mutually recursive local
 functions a la CL's labels.

 (defn ring [n]
   (letfn [(a [n] (if (zero? n) n (b (dec n
   (b [n] (if (zero? n) n (c (dec n
   (c [n] (if (zero? n) n (a (dec n]
  (c n)))

 (ring 1000)

 Note this is still subject to stack limits, i.e. no TCO, so please
 don't report your StackOverflowErrors. Useful for bounded data only.


Do you advocate usage of 'letfn' and 'let' similar to the distinction  
between LABELS and FLET in CL? In other words, FLET implies non- 
recursive local function definition whereas LABELS suggests  
(mutually) recursive function(s).

So,
(letfn [(f [x] (+ x 2))] (f 8)) ; LABELS
should ideally be:
(let [f (fn [x] (+ x 2))] (f 8)) ; FLET

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



List comprehension examples for Wikibook

2009-03-10 Thread David Sletten

I translated some examples from the book The Haskell Road (http:// 
homepages.cwi.nl/~jve/HR/):
(defn naturals [] (iterate inc 0))
(def evens1 (for [n (naturals) :when (even? n)] n))
(def odds1 (for [n (naturals) :when (odd? n)] n))
(def evens2 (for [n (naturals)] (* 2 n)))
(def small-squares1 (for [n (range 0 1000)] (* n n)))
(def small-squares2 (for [n (naturals) :when ( n 1000)] (* n n))) ;  
Maybe should use :while instead?

Are these appropriate for inclusion on the Wikibook API page (http:// 
en.wikibooks.org/wiki/Clojure_Programming/Examples/API_Examples)  
since they are derived from a copyrighted book?

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Problems with read-line

2009-03-09 Thread David Sletten

While using the code distributed with Stu Halloway's Programming  
Clojure book I get the following exception from (read-line):
java.lang.ClassCastException:  
clojure.lang.LineNumberingPushbackReader (NO_SOURCE_FILE:0)

So I downloaded the latest trunk from SVN, and (read-line) works  
fine. However, as I tried to run Stu's translation of Peter Seibel's  
PCL ch. 3 (http://blog.thinkrelevance.com/2008/9/16/pcl-clojure- 
chapter-3), I got this exception:
java.lang.Exception: Unable to resolve symbol: lazy-seq in this  
context (duck_streams.clj:175)

At first I thought this was a problem with my clojure-contrib. But I  
realized I needed the lazy branch of Clojure from SVN. I downloaded  
that, and the problem with lazy-seq goes away. But now (read-line) is  
broken again...

Here's read-line from trunk:
(defn read-line
   Reads the next line from stream that is the current value of *in* .
   [] (. *in* (readLine)))

And the lazy branch:
(defn read-line
   Reads the next line from stream that is the current value of *in* .
   [] (. #^java.io.BufferedReader *in* (readLine)))

Apparently *in* is a LineNumberingPushbackReader:
public class LineNumberingPushbackReader extends PushbackReader{

Can't be cast to BufferedReader...

What's the policy for fixing something like this?

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Help please: or function

2009-03-09 Thread David Sletten

On Mar 9, 2009, at 5:48 AM, timc wrote:

  (re-seq #([a-zA-Z_0-9]+)=([^ ]+) arg))]


Two small suggestions--it's easier, and more legible to use \S to  
match non-whitespace characters:
(re-seq #([a-zA-Z_0-9]+)=(\S+) arg)

And you've basically defined the word character class \w verbatim  
in your example:
(re-seq #(\w+)=(\S+)

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Problems with read-line

2009-03-09 Thread David Sletten


On Mar 9, 2009, at 8:41 AM, Jason Wolfe wrote:


 I think this was discussed here:

 http://groups.google.com/group/clojure/browse_frm/thread/ 
 48f1fb08b3052083/85f858df39daca2a? 
 hl=enlnk=gstq=linenumberingpushbackreader#85f858df39daca2a

 I'm not sure what the resolution was, if any.

 -Jason


Sorry. I missed that.

Thanks for the link.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Clojure Cookbook

2009-03-09 Thread David Sletten

Has anyone done any work towards assembling a cookbook of Clojure  
recipes along the lines of the Perl/Ruby Cookbooks? Even something  
less formal such as the Common Lisp Cookbook would be useful (http:// 
cl-cookbook.sourceforge.net/index.html).

It would be good to have something like this in place to support the  
increased interest in Clojure that Stu Halloway's book will generate.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Capitalize string

2009-03-08 Thread David Sletten

Is there a function to capitalize the first letter of a string or a  
better way than this idiotic code?
(apply str (map #(if (zero? %2) (Character/toUpperCase %1) %1)  
clojuriffic (iterate inc 0)))

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Capitalize string

2009-03-08 Thread David Sletten


On Mar 8, 2009, at 2:45 AM, Joshua Fox wrote:


 How about this?
 user= (defn upper-first [s] (apply str (Character/toUpperCase (first
 s)) (rest s)))
 #'user/upper-first
 user= (upper-first a)
 A


That certainly qualifies as less idiotic. :)

Mahalo,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



filter-split

2009-03-07 Thread David Sletten

I'm reading the Sequences chapter of Programming Clojure, and Stu  
points out that split-with combines the semantics of take-while and  
drop-while. But is there a function that does something similar with  
filter? Namely, rather than simply filtering the elements of a  
collection that satisfy a predicate I also want to capture those that  
don't. Something like this:
(defn filter-split [pred coll]
   (loop [trues '() falses '() coll coll]
 (cond (empty? coll)
   (vector (reverse trues) (reverse falses))
   (pred (first coll))
   (recur (cons (first coll) trues) falses (rest coll))
   :else
   (recur trues (cons (first coll) falses) (rest coll)

(filter-split #{\a\e\i\o\u} is this not pung?) = [(\i \i \o \u)  
(\s \space \t \h \s \space \n \t \space \p \n \g \?)]
(filter-split even? (range 10)) = [(0 2 4 6 8) (1 3 5 7 9)]

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: filter-split

2009-03-07 Thread David Sletten


On Mar 7, 2009, at 7:17 PM, Adrian Cuthbertson wrote:


 That's the beauty of this language - there are many ways to skin  
 the cat!

Hmmm...I'm not sure what I'll do with a skinless cat. :)

 Here's a version using reduce...

 (defn filt-split [pred col]
  (reduce (fn [[a b] x] (if (pred x) [(conj a x) b] [a (conj b x)]))
 [[] []] col))

 (filt-split even? [1 2 3 4 5 6 7 8])
 [[2 4 6 8] [1 3 5 7]]


I like that a lot. As long as the repeated creation of the ephemeral  
vectors isn't too expensive.

 But when you look at separate in clojure.contrib.seq-utils its simple
 and elegant;
 (defn separate [f s]
  [(filter f s) (filter (complement f) s)])


This is exactly what I'm trying to avoid. I don't want to traverse  
the collection twice.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: filter-split

2009-03-07 Thread David Sletten


On Mar 7, 2009, at 6:44 PM, e wrote:

 check the discussion with the subject, time lies, even with  
 doall.  We came up with something like the following, but some  
 name change change tweaks were suggested.  This thing takes a pred  
 and a collection and returns a list of two collections -- one that  
 passes the pred, and one that fails.

 (defn filt-rem [pred coll]
(loop [l1 () l2 () [f  r] coll]
  (if f
(if (pred f)
  (recur (conj l1 f) l2 r)
  (recur l1 (conj l2 f) r))
(list l1 l2



This is almost identical to what I posted. However, is this the  
intended behavior?
(filt-rem identity '(true nil false 8)) = ((true) ())
(filt-split identity '(true nil false 8)) = [[true 8] [nil false]]

(filt-rem even? (range 10)) = ((8 6 4 2 0) (9 7 5 3 1))
(filter-split even? (range 10)) = [(0 2 4 6 8) (1 3 5 7 9)]

 (defn filter-split [pred coll]
   (loop [trues '() falses '() coll coll]
 (cond (empty? coll)
   (vector (reverse trues) (reverse falses))
   (pred (first coll))
   (recur (cons (first coll) trues) falses (rest coll))
   :else
   (recur trues (cons (first coll) falses) (rest coll)

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: float vs fraction (just playing around)

2009-03-06 Thread David Sletten
 is different from 6 * 0.1:
(rationalize 0.6) = 3/5
(rationalize (* 6 0.1)) = 6001/1
(rationalize (+ 0.1 0.1 0.1 0.1 0.1 0.1)) = 3/5

Even worse is the potential for infinite loops:
(defn trap [x]
   (prn x)
   (cond (= x 1) How nice. 10 * 0.1 = 1
 ( x 1) Whoops. Good thing I had an escape hatch.
 :else (trap (+ x 0.1

(trap 0.1)
0.1
0.2
0.30004
0.4
0.5
0.6
0.7
0.7999
0.8999
0.
1.0999
Whoops. Good thing I had an escape hatch.

If you've read this far you'll want to take a look at the links Mark  
provided earlier.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



let vs. let*

2009-03-06 Thread David Sletten

I see a lot of let* in macro expansions, but Clojure's let already  
behaves like Common Lisp's LET*. Is let* archaic? It seems to behave  
the same as let in terms of sequential binding.
(let [x 8 y (inc x)] (list x y)) = (8 9)
(let* [x 8 y (inc x)] (list x y)) = (8 9)

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Roman Numerals

2009-03-05 Thread David Sletten


On Mar 4, 2009, at 8:29 PM, Tom Faulhaber wrote:


 BTW, cl-format (my Common Lisp format function for Clojure), supports
 the ~...@r directive for converting Arabic to Roman (but nothing to go
 the other way around. I didn't spend too much time thinking about
 stylistic issues when I wrote it, but if you're interested you can
 compare. It's at http://github.com/tomfaulhaber/cl-format.)


Thanks for the link Tom. I'd read mention of your work somewhere but  
hadn't had a chance to look at it yet. That's extremely cool that  
you've implemented FORMAT!

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Roman Numerals

2009-03-04 Thread David Sletten
)
  num- 
 list))
 (arabic-to-roman n tail ))

 You might consider using 'reduce' instead of recursion here.
 Alternatively, it's interesting to note that because of the ease with
 which you're destructuring arabic-values, it would be no more
 difficult if you had a single list (or vector) of alternating numbers
 and strings rather than nesting them.


I don't think reduce would actually work here. As you see, the test  
(= n arabic) determines whether we continue working with the  
original num-list or proceed to the tail. I'm not sure of how to get  
that behavior with reduce.

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



When in Rome

2009-03-04 Thread David Sletten


On Mar 4, 2009, at 3:56 AM, Rich Hickey wrote:


 Conversely, when says side effect. This is clear for 2 reasons.
 First, there is no else clause, so when doesn't really work as an
 expression. Furthermore, the forms in the when body are evaluated
 in an implicit do. Since only the final value is returned, any of
 the earlier expressions in the when body are useful only for their
 side effects.


 This is not the convention in Clojure for a couple of reasons.

 First, there are far fewer side effects. 'when' does not say side
 effects, although as you point out, it does support them. But then, so
 do function bodies and they don't inherently say side-effects.


Rich,

You're obviously the wrong guy to argue with regarding what the  
right way to do stuff in Clojure is, so I'll take your comment to  
heart.

At the same time though, I still don't quite get why when by  
definition evaluates its subexpressions in an implicit do (as CL's  
WHEN provides an implicit PROGN). There is no point in evaluating  
multiple expressions unless they produce side effects: printing to  
the screen, writing to disk, etc... Since this is the defined  
semantics of when it seems this should be a flag that governs how  
when is used. I understand that there is far less mutability in  
Clojure, but that's not to say there aren't side effects.

 I agree 'if' should always have 3 subexpressions, all the more reason
 to use 'when' when the second is going to be nil. Idiomatic Clojure
 code is full of expressions like:

 (when there-is-stuff (expr stuff))

 Which I read as when there is stuff, some function of it, else
 nothing. There's nothing inherently side-effecting about it.


Again here I'm not sure what you mean by else nothing. If you're  
using when as an expression, it has to produce a value even when  
the test fails. Why not just use if and make that value explicit?

 It would certainly be a waste of 'when' in Clojure to reserve it for
 side effects, since so much code contains none.


It was 50 years ago today that John McCarthy's description of Lisp   
was published in an AI Memo (AIM-8). Here's to McCarthy and Lisp. And  
here's to you, RIch, for carrying on the flame.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Roman Numerals

2009-03-03 Thread David Sletten

Here's a little toy to practice my basic Clojure skills. I didn't see  
any similar topic in the archives, so here we go...

This code performs conversions between Roman and Arabic numerals.  
Roman numerals are represented as strings and Arabic numerals are  
just integers. Arabic numerals in the range of 1 and 3999 inclusive  
are allowed. Conventionally, 3999 is the upper limit since the Roman  
numeral for 5000 (a V with a bar over it) cannot be represented in  
ASCII (although it exists in Unicode).

The function roman-to-arabic-aux correctly converts any valid Roman  
numeral. This can be exhaustively tested by comparing the Roman  
numeral output of Common Lisp's FORMAT function for example (e.g.,  
(format nil ~...@r n)). The trick, however, is weeding out bogus  
strings representing invalid Roman numerals such as IVI, IXV, etc...  
For this purpose the function roman? uses a regular expression I  
cribbed from Perl's CPAN module Roman.pm (http://search.cpan.org/ 
~chorny/Roman-1.23/lib/Roman.pm).

arabic-to-roman performs the obvious conversion in the other direction.

Incidentally, the cond form in roman-to-arabic-aux seems to me  
harder to read in Clojure than it would be in CL with its additional  
set of grouping parentheses. When you can't fit both the predicate  
and the consequent expression on the same line it gets confusing.

I'd appreciate any feedback regarding my Clojure style. Any more  
natural ways to do things?

Aloha,
David Sletten

(def roman-values-map {\I 1 \V 5 \X 10 \L 50 \C 100 \D 500 \M 1000})

(defn value [roman]
   (get roman-values-map (Character/toUpperCase roman)))

(defn roman? [roman-string]
   (and (not (empty? roman-string))
(re-matches
 #(?:M{0,3})(?:D?C{0,3}|C[DM])(?:L?X{0,3}|X[LC])(?:V?I{0,3}|I 
[VX])$
 roman-string)))

(defn roman-to-arabic-aux [roman-string]
   (cond (empty? roman-string) 0
 (empty? (rest roman-string)) (value (first roman-string))
 ( (value (first roman-string)) (value (second roman-string)))
 (- (roman-to-arabic-aux (rest roman-string))
(value (first roman-string)))
 :else
 (+ (value (first roman-string))
(roman-to-arabic-aux (rest roman-string)

(defn roman-to-arabic [roman-string]
   (if (roman? roman-string)
 (roman-to-arabic-aux roman-string)
 (format '%s' is not a valid Roman numeral. roman-string)))

(def arabic-values '((1000 M) (900 CM) (500 D) (400 CD)
  (100 C) (90 XC) (50 L) (40 XL)
  (10 X) (9 IX) (5 V) (4 IV) (1 I)))

(defn arabic-to-roman
   ([n] (if (= 1 n 3999)
  (apply str (arabic-to-roman n arabic-values))
  (format %d cannot be converted. n)))
   ([n num-list] (cond (empty? num-list) '()
   (zero? n) '()
   :else (let [[[arabic roman]  tail] num-list]
   (if (= n arabic)
 (cons roman (arabic-to-roman (- n  
arabic)
  num-list))
 (arabic-to-roman n tail ))


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



member function

2009-03-02 Thread David Sletten

Does Clojure have an analog of Lisp's MEMBER function?
(member 'a '(c a f e b a b e)) = (A F E B A B E)

(I'm more interested in it's use as a predicate rather than the fact  
that it returns a sublist when true.)

find and contains? are listed under the Maps section of the data  
structures page (http://clojure.org/data_structures#toc17) so no good  
with lists. I can't think of any other synonyms.

The documentation for some suggests this:
(some (fn [elt] (= elt 'a)) '(a b c)) = true
That's pretty verbose, and even the shortcut is kinda long:
(some #(= % 'a) '(a b c)) = true

Although this alternative is alright:
(some #{'a} '(a b c)) = a

Is that the Clojure version of MEMBER?

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: member function

2009-03-02 Thread David Sletten


On Mar 2, 2009, at 3:39 AM, Meikel Brandmeyer wrote:

 Does Clojure have an analog of Lisp's MEMBER function?
 (member 'a '(c a f e b a b e)) = (A F E B A B E)

 I don't know the member function of CL, but I interpret
 your example, that it cuts away the head of the list until
 the first occurence of the given thing.


MEMBER is a fancy predicate that tests whether or not an item is an  
element of a given list. I say fancy because rather than simply  
returning true when the item is present it returns the tail of the  
list starting with the item. It returns nil otherwise. I don't care  
about this fancy value. I just want to know whether or not the item  
is in the list without too much verbosity.

I think (some #{ITEM} LIST) is probably the way to do it.

 You can do that in Clojure with drop-while:

   (drop-while #(not= % :a) (list :c :a :f :e :b :a :b :e))
   = (:a :f :e :b :a :b :e)


Thanks for your example anyway.

Mahalo nui loa (vielen dank),
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: member function

2009-03-02 Thread David Sletten


On Mar 2, 2009, at 4:01 AM, Mark Volkmann wrote:


 It's verbose in order to discourage its use since its a linear search.
 See the discussion about the contains? function at
 http://www.ociweb.com/mark/clojure/article.html#Lists
 and http://www.ociweb.com/mark/clojure/article.html#Sets.

Ahh. Nice explanation. Thanks again Mark for the article.

sheepish
As you can see I haven't finished reading the whole thing yet.
/sheepish

Aloha,
David Sletten



--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Clojure documentation problems

2009-02-25 Thread David Sletten


On Feb 19, 2009, at 2:52 AM, David Sletten wrote:


 The macros page at clojure.org (http://clojure.org/macros) has links
 to several points in the API page. The link to the if-not macro
 appears to be broken (http://clojure.org/api#if-not). There is no
 such entry in the API. The same holds true for the condp macro
 (http://clojure.org/api#condp). Their documentation is available via
 doc at the REPL though.

 In addition, the rationalize function was missing last week, but it
 has an entry now. So never mind that...


Whoops...it's rational? that was missing from the API page and  
still is.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Flatten a list

2009-02-24 Thread David Sletten


On Feb 24, 2009, at 5:42 PM, Timothy Pratley wrote:


 user= (remove nil? '(:a nil nil :b :a))
 (:a :b :a)



C'mon! Doesn't anybody do things the old-fashioned way anymore?

(defn kill-nil
   ([l] (kill-nil l '()))
   ([l result] (cond (nil? l) (reverse result)
 (nil? (first l)) (recur (rest l) result)
 true (recur (rest l) (cons (first l) result )

You young whipper snappers!

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Flatten a list

2009-02-24 Thread David Sletten


On Feb 24, 2009, at 6:07 PM, David Sletten wrote:


 (defn kill-nil
([l] (kill-nil l '()))
([l result] (cond (nil? l) (reverse result)
  (nil? (first l)) (recur (rest l) result)
  true (recur (rest l) (cons (first l) result )



I forgot to ask...

In Lisp, rather than repeatedly testing for an optional argument like  
this:
(defun kill-nil (l optional (result '()))
   (cond ((endp l) (nreverse result))
 ((null (first l)) (kill-nil (rest l) result))
 (t (kill-nil (rest l) (cons (first l) result )

I would preserve the interface to the user (i.e., single arg) but  
eliminate the decisions regarding the optional arg from the recursive  
calls:
(defun kill-nil (l)
   (labels ((kill-nil-aux (l result)
  (cond ((endp l) (nreverse result))
((null (first l)) (kill-nil-aux (rest l) result))
(t (kill-nil-aux (rest l) (cons (first l)  
result ))
 (kill-nil-aux l '(

In the Clojure version above there doesn't seem to be any penalty  
since the recur only occurs after the correct arity has been selected.

Is this correct? How about a more traditional recursion?
(defn kill-nil
   ([l] (kill-nil l '()))
   ([l result] (cond (nil? l) (reverse result)
 (nil? (first l)) (recur (rest l) result)
 true (kill-nil (rest l) (cons (first l)  
result )

Is there a penalty deciding which arity to use on each call?

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Clojure documentation problems

2009-02-19 Thread David Sletten

The macros page at clojure.org (http://clojure.org/macros) has links  
to several points in the API page. The link to the if-not macro  
appears to be broken (http://clojure.org/api#if-not). There is no  
such entry in the API. The same holds true for the condp macro  
(http://clojure.org/api#condp). Their documentation is available via  
doc at the REPL though.

In addition, the rationalize function was missing last week, but it  
has an entry now. So never mind that...

Aloha,
David Sletten

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: terminology question re: binding

2009-02-17 Thread David Sletten

On Feb 16, 2009, at 10:34 AM, Stuart Halloway wrote:


 David Sletten sent me this erratum:

 
 At the beginning of section 2.4 we have The symbol user/foo refers to
 a var which is bound to the value 10. Under the next subsection
 Bindings we have Vars are bound to names, but there are other kinds
 of bindings as well. The Common Lisp standard defines a binding as
 an association between a name and that which the name denotes. This
 is the second sense used in the book. The first sense of a binding
 between a var and its value is inconsistent.


 Should I be using two different terms, or is the notion of binding
 overloaded?



Stuart,

I'm sorry but my comments appear to have raised more of a fuss than I  
intended. I think I need to clarify two issues:

1. I was probably not sufficiently clear in my intent. I did not mean  
so much to point out that you were wrong as to simply highlight the  
inconsistent use of the words binding and bound. Your term  
overloaded is more neutral, and therefore a better choice than mine.

In a language such as Common Lisp where every variable is  
(effectively) a reference variable, we have three concepts: names,  
variables (references), and values (referents). These three things  
have two connections. In an orthodox (perhaps pedantic) sense a name  
is bound to a variable, and the variable has a value. Names can  
be bound to different variables and variables can be assigned new  
values:

(defvar *x* 8) ; Bind *x* to special variable and assign value.
(setf *x* 9) ; Assign new value to variable. Binding hasn't changed.

(let ((x 12)) ; Bind x to variable, assign value.
   (let ((x pung)) ; Bind x to different variable - different  
binding.
 (setf x foo) ; Same (2nd) variable, new value.
   ...) ; 1st binding visible again outside of inner LET
...) ; No more binding for x out here

On a side note, when we talk of scope we shouldn't talk about an  
identifier's scope or a variable's scope. Scope is an issue  
involving both names and variables: bindings have scope.

The definitions in the CLHS glossary all reflect this interpretation.  
However, as I was looking through my notes it became clear that your  
overloaded use is hardly idiosyncratic. For example, the CLHS entry  
for LET states: let and let* create new variable bindings and  
execute a series of forms that use these bindings. Yet it explicitly  
states later that: ...Then all of the variables varj are bound to  
the corresponding values. This seems to me inconsistent with the  
glossary definitions, but such usage occurs throughout the Standard.

I think that the strict usage is consistent with Clojure's binding  
macro, which binds a name to a new variable. The let special form  
does a similar thing, but the situation is a little different than in  
CL since you can't assign a new value to a variable established by  
a Clojure let binding. Consequently, it seems that we can more safely  
blur the distinctions among name/variable/value here. A name is  
associated with a given value for the lifetime of the binding.

As another example, the language Oz has the notion of identifiers,  
which may be either bound or free, and variables, which may either be  
bound or unbound. Oz variables are like Clojure lexicals--once  
assigned their values cannot change. So an unbound variable is simply  
a variable that has not been assigned a value yet. Assignment binds  
a value to a variable. Likewise, a free identifier is a name that  
doesn't refer to anything yet. Once bound, an identifier names a  
variable.

So to wrap this all up, if you are satisfied with your discussion in  
the book--and you seem justified in that--then I'll just shut up  
about binding.

2. My erratum report and comments above should not be viewed as  
though I advocate Clojure being evaluated through the lens of Common  
Lisp. I have a few years experience studying CL, so naturally that  
affects my perception of Clojure. However, in fairness the language  
should be judged on its own merits, and I am far too new to Clojure  
to make any such judgment yet.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: terminology question re: binding

2009-02-17 Thread David Sletten


On Feb 17, 2009, at 5:10 AM, Chouser wrote:


 I think that the strict usage is consistent with Clojure's  
 binding macro,
 which binds a name to a new variable.

 Are you sure?  It seems to me the most natural mapping from the CL
 concepts to Clojure is:
   CL name - Clojure symbol, name, or perhaps namespace entry
   CL variable - Clojure Var (or perhaps ref, atom, etc.)
   CL value or referent - Clojure value.

 Clojure's 'binding' macro does not change the connection from name to
 Var, but the one from Var to (effective, thread-local) value.


I see that you are correct. Observe the following behavior:
; Common Lisp. We have no way to get ahold of the variable  
(reference) to which a
; name is bound. Dereferencing is automatic. However, with a dynamic
; variable we can access the symbol data structure associated with  
the name *PUNG*.
(defvar *pung* 8)
(defvar *foo* *pung*) ; Referent of *PUNG* assigned
(defvar *bar* '*pung*) ; Note the quote here--assigning symbol *PUNG*

; Establish a new binding for *PUNG*. *BAR* changed as well.
(let ((*pung* 9)) (list *pung* *foo* (symbol-value *bar*))) = (9 8 9)

; Clojure. We can access the reference itself via var.
(def pung 8)
(def foo pung) ; i.e., (deref (var pung)) or @#'pung
(def bar (var pung))

; binding changes value of pung--apparently not the variable  
itself, thus
; bar also reflects changed value.
(binding [pung 9] (list pung foo @bar)) = (9 8 9)

; By contrast let binds pung to a new variable, which shadows the  
global.
; bar still refers to global pung
(let [pung 9] (list pung foo @bar)) = (9 8 8)

Do I have it right now?

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: is mod correct?

2009-02-12 Thread David Sletten


On Feb 10, 2009, at 6:37 PM, Timothy Pratley wrote:


 I would have expected the mult to be a performance hit, but my overly
 simple tests show it performing better:
 user= (time (dotimes [i 100] (zero? (* 5 11
 Elapsed time: 183.358706 msecs
 user= (time (dotimes [i 100] (or ( 5 0 11) ( 11 0 5
 Elapsed time: 682.586025 msecs

 In practice it doesn't seem to make much difference overall:
 user= (time (dotimes [i 100] (map #(mod2 % 3) (range -9 9)) ))
 Elapsed time: 966.868765 msecs
 user= (time (dotimes [i 100] (map #(mod42 % 3) (range -9 9)) ))
 Elapsed time: 938.675334 msecs

 But the multiply seems to have the edge in both expression and speed.



The real hit would come with bignums, no? But as far as the routine  
use of MOD goes we're probably talking about fixnums  99% of the time.

Aloha,
David Sletten


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---