Re: (take-by f coll), (drop-by f coll): Problem Comparing Adjacent Items Of A Collection

2011-04-03 Thread Stefan Rohlfing
Hi Andreas,

You are right, the helpful Clojure community is a real asset to be proud of!

I like your solution using* loop ... recur* as it makes the intention of the 
code a bit more clear.

The pattern 
 (lazy-seq
(when-let [s (seq coll)]
  ...
is used in the implementation of* take-while * in Clojure 
Core . *loop 
... recur* cannot be used because the function call is not the tail 
position.

By the way, my code for *drop-by2* in my last post was not correct. So here 
is the corrected version:

(defn drop-by2 [f coll]
  (lazy-seq
(when-let [s (seq coll)]
  (let [x (first s)
y (second s)]
(if (and x y (= (f x) (f y)))
  (drop-by2 f (rest s))
  (rest s))

Best regards,

Stefan





-- 
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: (take-by f coll), (drop-by f coll): Problem Comparing Adjacent Items Of A Collection

2011-04-03 Thread Stefan Rohlfing
@ Ken, Andreas

Thank you for your nice implementations!

As far as I can see, there are two main methods of comparing adjacent items 
of a list:

1) Take the first item of a coll. Compare the remaining items with an offset 
of 1:
(map f coll (rest coll))
;; apply some sort of filter

2) Take the first and the second item of a coll. Test if both items exists 
and then compare: 
(let [x (first coll), y (second coll)]
   (and x y (= (f x) (f y 

The first method works for *take-by*, but not for *drop-while* (or so I 
think).

Using the second method *take-by* can be changed into *drop-by* by only 
changing the last two lines:

(defn drop-by2 [f coll]
  (lazy-seq
(when-let [s (seq coll)]
  (let [x (first s)
y (second s)]
(if (and x y (= (f x) (f y)))
  (drop 2 s)
  (drop 1 s))


I am curious to know if one of these methods is the preferred way of doing a 
comparison in Clojure (aka Python's one way of doing things). The sheer 
number of possible solutions to the same problem sometimes overwhelms me a 
bit, so that I'm looking for some orientation ;-) 

Best regards,

Stefan

-- 
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

(take-by f coll), (drop-by f coll): Problem Comparing Adjacent Items Of A Collection

2011-04-02 Thread Stefan Rohlfing
Dear Clojure Group,

In the style of *take-while* and *drop-while* I wrote two functions* take-by
* and *drop-by* that take an arbitrary function f instead of a predicate and 
return a lazy sequence based on comparing the result of (f item) of 
successive items in the collection.

  However, whenever I need to compare adjacent items of a collection, I 
quickly get lost and the result always looks like a hack. Here, this is 
especially true for the implementation of *drop-by*:

(defn take-by [f coll]
  "Starting from the first item in coll, 
  returns a lazy sequence of items for which (f item) 
  returns the same result."
  (lazy-seq
(when-let [s (seq coll)]
  (let [x (first s)]
(cons x (take-by f (when-let [y (second s)]
 (if (= (f x) (f y))
   (rest s)
   nil


;; (take-by (partial + 2) [])
;; ()
;; (take-by (partial + 2) [2 2 2 3 3 4 4])
;; (2 2 2)



(defn drop-by [f coll]
  "Returns a lazy sequence of the items in coll starting 
  from the first item for which (f item) returns the same result."
  (lazy-seq
(let [s (seq coll), x (first s), y (second s)]
  (if (and s y)
(if (= (f x) (f y))
  (drop-by f (rest (rest s)))
  (rest s))
s


;; (drop-by (partial + 2) [])
;; ()
;; (drop-by (partial + 2) [2 2 2 3 3 4])
;; (3 3 4)


I am sure there is a standard *functional* way of comparing adjacent items 
in a coll and would be glad if someone could point me to it.
Also, any suggestions of making my code a little bit more idiomatic are 
highly welcome!

Best regards,

Stefan

-- 
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: Tranforming an ACL file: Comparing Clojure with Ruby

2011-03-03 Thread Stefan Rohlfing
Thanks for your suggestion. 
Using the 'for' macro here makes the main part of the parse function much 
clearer.

-- 
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: Tranforming an ACL file: Comparing Clojure with Ruby

2011-03-03 Thread Stefan Rohlfing
You are perfectly right. Organizing the code so that -> or ->> an be applied 
is key here. 
Unfortunately, only if all functions to be composed follow the same pattern 
of either 'insert first' or 'insert last' can these macros be used.

-- 
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: Tranforming an ACL file: Comparing Clojure with Ruby

2011-03-03 Thread Stefan Rohlfing
Thank you all so much for helping me improve my code!

I personally find Stuart's suggestion to be the most readable. The use of 
the ->> macro makes the workflow quite easy to follow. 

I hope that with some more experience I will be able to see these patterns 
myself and adapt my code accordingly.

Best regards,

Stefan  

-- 
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

Tranforming an ACL file: Comparing Clojure with Ruby

2011-03-03 Thread Stefan Rohlfing
Dear Clojure Group,

I am currently reading the online book Pro Git . In 
chapter 7.4  (section “Enforcing a 
User-Based ACL System”) there is a task of reading in an access control list 
(ACL) file, such as the following

# avail/unavail | users | path
avail|nickh,pjhyett,defunkt,tpw
avail|usinclair,cdickens,ebronte|doc
avail|schacon|lib
avail|schacon|tests

and printing out a map of the form { "user1" [path 1, path 2], "user2" 
[path2, path3] ...}.

The author of the book provides a solution in Ruby, which I find relatively 
easy to follow, despite not having written any Ruby code before:

def get_acl_access_data(acl_file)
 # read in ACL data
 acl_file = File.read(acl_file).split("\n").reject { |line| line == '' }
 access = {}
 acl_file.each do |line|
   avail, users, path = line.split('|')
   next unless avail == 'avail'
   users.split(',').each do |user|
 access[user] ||= []
 access[user] << path
   end
 end
 access
end

I then tried the same in Clojure, but found my solution to be much less 
readable compared to the Ruby code:

(use '[clojure.string :only (split)])

(defn get-acl-access-data [file]
 (let [acl (split (slurp file) #"\n")]
   (apply merge-with #(into %1 %2)
 (map (fn [[avail users path]]
 (let [users (split users #",")]
(reduce (fn [acc user]
(when (= avail "avail")
  (assoc acc user [path])))
   {} users)))
   (map #(split % #"\|") acl)

;; Output:
;; {"schacon" ["lib" "tests"], 
;;  "usinclair" ["doc"], 
;;  "cdickens" ["doc"], 
;;  "ebronte" ["doc"], 
;;  "tpw" [nil], 
;;  "defunkt" [nil], 
;;  "pjhyett" [nil], 
;; "nickh" [nil]}

Maybe it is just because I am an ambitious beginner at best, but I am afraid 
I won’t be able to figure out immediately what this code is doing in a few 
weeks.

However, there probably is a better way of translating the Ruby version into 
Clojure. With "better" I mean easier to follow. My main goal is on clarity, 
as I often struggle organizing my code in a way I would consider readable.

I therefore would be glad for any ideas of improvement. Any suggestions are 
highly welcome!

Best regards,

Stefan

-- 
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

Tranforming an ACL file: Comparing Clojure with Ruby

2011-03-03 Thread Stefan Rohlfing
Dear Clojure Group,

I am currently reading the online book Pro 
Git.
 
In chapter 7.4  (section “Enforcing a 
User-Based ACL System”) there is a task of reading in an access control list 
(ACL) file, such as the following

# avail/unavail | users | path
avail|nickh,pjhyett,defunkt,tpw
avail|usinclair,cdickens,ebronte|doc
avail|schacon|lib
avail|schacon|tests

and printing out a map of the form { "user1" [path 1, path 2], "user2" 
[path2, path3] ...}.

The author of the book provides a solution in Ruby, which I find relatively 
easy to follow, despite not having written any Ruby code before:

def get_acl_access_data(acl_file)
 # read in ACL data
 acl_file = File.read(acl_file).split("\n").reject { |line| line == '' }
 access = {}
 acl_file.each do |line|
   avail, users, path = line.split('|')
   next unless avail == 'avail'
   users.split(',').each do |user|
 access[user] ||= []
 access[user] << path
   end
 end
 access
end

I then tried the same in Clojure, but found my solution to be much less 
readable compared to the Ruby code:

(use '[clojure.string :only (split)])

(defn get-acl-access-data [file]
 (let [acl (split (slurp file) #"\n")]
   (apply merge-with #(into %1 %2)
 (map (fn [[avail users path]]
 (let [users (split users #",")]
(reduce (fn [acc user]
(when (= avail "avail")
  (assoc acc user [path])))
   {} users)))
   (map #(split % #"\|") acl)

;; Output:
;; {"schacon" ["lib" "tests"], 
;;  "usinclair" ["doc"], 
;;  "cdickens" ["doc"], 
;;  "ebronte" ["doc"], 
;;  "tpw" [nil], 
;;  "defunkt" [nil], 
;;  "pjhyett" [nil], 
;; "nickh" [nil]}

Maybe it is just because I am still a beginner, but I am afraid I won’t be 
able to figure out immediately what this code is doing a few weeks from now.

However, I am sure there must be a better way of translating the Ruby 
version into Clojure. My main goal is on clarity, as I often struggle 
organizing my code in a way I would consider readable.

I therefore would be glad for any ideas of improvement. Any suggestions are 
highly welcome!

Best regards,

Stefan

-- 
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: Problem Installing VimClojure + lein-vimclojure

2011-01-27 Thread Stefan Rohlfing
Hi Meikel,

Thanks for pointing me to the installation instructions. I somehow must have 
missed that part.

I have already joined the VimClojure Group and will probably have some more 
questions while learning how to use this plugin.

Best regards,

Stefan

-- 
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: Problem Installing VimClojure + lein-vimclojure

2011-01-27 Thread Stefan Rohlfing
Hi Miki,

Thanks for your help. Now the Nailgun client is running.

Best regards,

Stefan

-- 
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: Problem Installing VimClojure + lein-vimclojure

2011-01-27 Thread Stefan Rohlfing
As it seems the Nailgun client has to be installed manually. 

This is what I did so far:

1) 
Downloaded
 the 
Nailgun Client and extracted it.
2) Added the following commands to my ~/.vimrc file:

let vimclojure#WantNailgun = 1
let vimclojure#NailgunClient = 
"/home/sovonex/Clojure/Add-ins/vimclojure-nailgun-client/ng.exe"
let clj_want_gorilla = 1

Opened a Clojure file from my Leiningen project in Vim but received the 
following error message:

*Could not determine the Namespace of the file.*
*[...]*
*Reason:*
*Error executing Nail! (126)*
*/bin/bash: /home/sovonex/Clojure/Add-ins/vimclojure-nailgun-client/ng.exe: 
Permission 
denied*

Pointing to ng.exe in my ~/.vimrc file is definitely not correct as I am not 
using Windows but Kubuntu 10.10.
The missing piece to a successful installation therefore is probably the 
building of the Nailgun client. Does anybody know how to build the Nailgun 
client on Linux when using VimClojure + lein-vimclojure?

Best regards,

Stefan



-- 
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

Problem Installing VimClojure + lein-vimclojure

2011-01-27 Thread Stefan Rohlfing
Hi all, 

I have been trying to install the Vim pluing VimClojure togheter with the 
lein plugin lein-vimclojure but always get an error message telling me ng 
(the Nailgun client) cannot be found.

This is how my installation went so far:

1) Downloaded  Vimclojure from 
Github and copied it into /.vim/bundle (I am using the Pathogen plugin)

Opened a Clojure file in Vim to verify that features that don’t require the 
Nailgun server, such as syntax highlighting, work as expected.


2) Downloaded  lein-vimclojure 
from Github and added the following dev dependency to Leiningen’s 
project.clj:

:dev-dependencies [[swank-clojure "1.2.1"]
  *[org.clojars.autre/lein-vimclojure "1.0.0"]*]) 


3) Added the following line to .vimrc:

let vimclojure#WantNailgun = 1


4) Started the nailgun server:

*Command*:
$ *lein vimclojure &*
*Output*:
[1] 10509
$ NGServer started on 127.0.0.1, port 2113.

4) Opened a Clojure file from the above Leiningen project in Vim  but 
 received the following error message:

*Error message:
Could not determine the Namespace of the file.
This might have different reasons. Please check, that the ng server
is running with the correct classpath and that the file does not contain
syntax errors. The interactive features will not be enabled, ie. the
keybindings will not be mapped.
Reason:
Error executing Nail! (127)
/bin/bash: ng: command not found*

Apparently, the Nailgun client could not be found.
Does lein-vimclojure also install the Nailgun client or does this plugin 
only set the correct classpath to the Leiningen project?

I already 
downloadedthe
 Nailgun client from kotka.de but have to admit 
that I am not sure how to do a manual install and what to put into .vimrc 
when using VimClojure + lein-vimclojure.
Therefore I hope that someone with a successfull install using 
lein-vimclojure could give me some hints. Any suggestions are highly 
welcome!

Best regards,

Stefan

-- 
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: Regarding The Implementation of 'merge-with'

2011-01-20 Thread Stefan Rohlfing
Hi John, 

Thanks for your detailed explanation of the inner workings of my code! I 
have been confused by the behavior of Clojure's mutable data structures 
quite often, but after reading your explanation it finally starts to make 
sense. 

I also tried to explain why your code works:

Everything starts with an empty map of *acc* that is bound to *acc2* (the 
accumulator of the inner reduce):

;; Inner reduce
(assoc {} :a 1);; --> {:a 1}
(assoc {:a 1} :b 2) ;; --> {:a 1 :b 2}

;; This map is then returned to the outer reduce and bound again to *acc2*
;; In the next step *acc* will again be the start map for the inner reduce:

;; Inner reduce
(assoc {:a 1 :b 2} :a (+ 1 9))   ;; --> {:a 10, :b 2}
(assoc {:a 10, :b 2} :b (+ 2 98)) ;; --> {:a 10, :b 100}
(assoc {:a 10, :b 100} :c 0);; --> {:c 0, :a 10, :b 100}

Best regards,

Stefan

-- 
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: Regarding The Implementation of 'merge-with'

2011-01-20 Thread Stefan Rohlfing
Hi John,

Thank you very much for your correction of my code! *my-merge-with* is 
working perfectly now.

There is just one thing: I always want to understand my errors so that I can 
learn from them. However, I still don't understand why my implementation did 
not work. Looking at my code I am thinking everything should be fine as all 
key/val pairs are added to the map *acc* of the outer *reduce* (or so is my 
assumption). 

Any ideas are highly appreciated!

Best regards,

Stefan

-- 
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: Regarding The Implementation of 'merge-with'

2011-01-19 Thread Stefan Rohlfing
Hi all,

I tried another implementation of 'merge-with' using nested calls to
'reduce'. However,
I just cannot get it to work correctly:

(defn my-merge-with [f & maps]
  (when (some identity
maps)
(reduce
 (fn [acc m]
   (reduce
(fn [_ [key val]]
  (assoc acc key (if-let [old-val (get acc key)]
 (f old-val val)
  val)))
{} m))
 {} maps)))

(my-merge-with +  {:a 1  :b 2} {:a 9  :b 98 :c 0})
;; --> {:c 0, :b 2}

The problem most probably has to to with 'assoc' but I don't now how
to test this code.

I hope someone can me point to my error.

Best regards,

Stefan





On Nov 26 2010, 8:42 pm, Stefan Rohlfing 
wrote:
> Dear Clojure Group,
>
> Today I took a closer look at the 'merge-with' function of Clojure
> Core and changed some parts to better understand its implementation.
>
> Now I still have two questions regarding the following code:
>
> (defn my-merge-with [f & maps]
>   (when (some identity
> maps)                                                ;; question 1
>     (reduce (fn [acc m]
>                      (let [key (key (first  m)) val (val (first
> m))]          ;; question 2
>                        (assoc acc key (if-let [old-val (get acc key)]
>                                                      (f old-val val)
>                                                       val
>      {} maps)))
>
>  (my-merge-with + {"t" 1} {"a" 1} {"c" 1} {"g" 1} {"g" 1} {"g" 1} {"a"
> 1} {"c" 1} )
> ;; {"g" 3, "c" 2, "a" 2, "t" 1}
>
> Question 1:
> (when (some identity maps)
>
> This expression from the original implementation checks if the
> provided coll is empty.
> However, why not just use (when (empty? maps) or (when (seq maps)
> instead?
>
> Question 2:
> In order to return the key of a map consisting of one key/value pair I
> have to use the 'first' function, otherwise an exception will be
> thrown:
>
> (key {:a "a"})
> ;; clojure.lang.PersistentArrayMap cannot be cast to java.util.Map
> $Entry
> ;;  [Thrown class java.lang.ClassCastException]
>
> (key (first {:a "a"}))
> ;; :a
>
> I understand that 'key' expects a java.util.Map$Entry object, but how
> exactly does using 'first' accomplish this?
>
> (first {:a "a"})
> ;; [:a "a"]
>
> [:a "a"] is not a vector because the 'key' function does not work on a
> vector:
>
> (key [:a "a"])
> ;; clojure.lang.PersistentVector cannot be cast to java.util.Map$Entry
> ;;   [Thrown class java.lang.ClassCastException]
>
> Any suggestions are very welcome!
>
> Stefan

-- 
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: I don't understand this exception

2011-01-17 Thread Stefan Rohlfing
Dear Meikel and Ken,

Thank you very much for your corrections and suggestions! I admit it
took a while for me to understand the more sophisticated parts of your
code, but on the way I learned quite a lot about the correct usage of
conj, assoc, update-in, and fnil!

Best regards,

Stefan

On Jan 17, 3:21 pm, Ken Wesson  wrote:
> On Mon, Jan 17, 2011 at 1:47 AM, Stefan Rohlfing
>
>
>
>
>
>
>
>
>
>  wrote:
> > Hi all,
>
> > I am trying to implement the function 'group-by' from Clojure.Core
> > using my current knowledge of Clojure but cannot get pass a
> > java.lang.Exception.
>
> > This is the code so far:
>
> > (defn key? [key coll]
> >  (some #{key} (keys coll)))
>
> > (defn my-group-by [f coll]
> >  (let [test (fn [m x]
> >               (let [res (f x)]
> >                 (if (key? res m)
> >                   (conj (m res) x)
> >                   (assoc m res (vec x)]
> >    (reduce test {} coll)))
>
> First of all, your key? is only ever (supposed to be) called on maps,
> so you can dispense with it:
>
> (defn my-group-by [f coll]
>  (let [test (fn [m x]
>               (let [res (f x)]
>                 (if (contains? res m)
>                   (conj (m res) x)
>                   (assoc m res (vec x)]
>    (reduce test {} coll)))
>
> Second, your already-in-the-map case returns a vector. It doesn't
> modify the vector in place; it makes a new one with one more item and
> returns that. Not the map it should return.
>
> The next iteration of your reduce, the vector gets passed to key? with
> some value. Your key? function calls keys on it, which results in an
> exception. I get:
>
> user=> (keys ['x 'y 'z])
> java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to
> java.util.Map$Entry
>
> You got:
>
> > ;; java.lang.Exception: Unable to convert: class java.lang.Integer to
> > Object[] (repl-1:2)
>
> I'm not sure why the difference -- different Clojure versions? -- but
> no matter, the fix is the same:
>
> (defn my-group-by [f coll]
>  (let [test (fn [m x]
>               (let [res (f x)]
>                 (if (contains? res m)
>                   (assoc m res (conj (m res) x))
>                   (assoc m res (vec x)]
>    (reduce test {} coll)))
>
> This actually returns an updated map and not just an updated vector.
> But it can be made nicer in a couple of ways. One uses the optional
> not-found option to get to dispense with the contains?:
>
> (defn my-group-by [f coll]
>  (let [test (fn [m x]
>               (let [res (f x)]
>                 (assoc m res (conj (m res []) x]
>    (reduce test {} coll)))
>
> And the other uses update-in. Update-in means the key only needs to be
> specified once, which lets you dispense with the inner let:
>
> (defn my-group-by [f coll]
>  (let [test (fn [m x]
>                 (update-in m [(f x)] #(if % (conj % x) [x])))]
>    (reduce test {} coll)))
>
> This can be formatted a bit more nicely:
>
> (defn my-group-by [f coll]
>   (reduce
>     (fn [m x]
>       (update-in m [(f x)]
>         #(if % (conj % x) [x])))
>     {} coll))
>
> This gets rid of the outer let as well.
>
> The latter two versions can't distinguish the map having a key with an
> associated value of nil and the map lacking that key; however, the map
> never associates a key with anything other than a vector, so this ends
> up not mattering.
>
> For reference (and I only peeked at this *after* writing all of the
> above), the implementation of group-by in clojure.core is:
>
> (defn group-by
>   "Returns a map of the elements of coll keyed by the result of
>   f on each element. The value at each key will be a vector of the
>   corresponding elements, in the order they appeared in coll."
>   {:added "1.2"
>    :static true}
>   [f coll]
>   (persistent!
>    (reduce
>     (fn [ret x]
>       (let [k (f x)]
>         (assoc! ret k (conj (get ret k []) x
>     (transient {}) coll)))
>
> This is basically the same as the version I got adding the optional
> not-found argument to get instead of using update-in, except that it
> uses transients for the performance benefits (and has docstrings and
> metadata) and gets rid of the outer let in the same manner as the
> final update-in using version I wrote.

-- 
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 don't understand this exception

2011-01-16 Thread Stefan Rohlfing
Hi all,

I am trying to implement the function 'group-by' from Clojure.Core
using my current knowledge of Clojure but cannot get pass a
java.lang.Exception.

This is the code so far:

(defn key? [key coll]
  (some #{key} (keys coll)))

(defn my-group-by [f coll]
  (let [test (fn [m x]
   (let [res (f x)]
 (if (key? res m)
   (conj (m res) x)
   (assoc m res (vec x)]
(reduce test {} coll)))


Calling 'my-group-by' throws an exception:

(my-group-by (fn [x] (mod x 3)) [0 1 2 3 4 5 6 7 8 9 10])

;; java.lang.Exception: Unable to convert: class java.lang.Integer to
Object[] (repl-1:2)

This is the result that should have been returned if everything was
correct:

{2 (2 5 8), 1 (1 4 7 10), 0 (0 3 6 9)}

So, far I have been unable to find the place in my code where an
Integer  is passed incorrectly. Any suggestions are highly
appreciated!

Best regards,

Stefan

-- 
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: Regarding The Implementation of 'merge-with'

2010-11-26 Thread Stefan Rohlfing
Hi Chris,

Thanks a lot for your clear explanations! Now all the pieces suddenly
make sense to me.

Stefan

On Nov 26, 9:30 pm, Chris Perkins  wrote:
> On Nov 26, 7:42 am, Stefan Rohlfing  wrote:
>
>
>
>
>
>
>
>
>
> > Dear Clojure Group,
>
> > Today I took a closer look at the 'merge-with' function of Clojure
> > Core and changed some parts to better understand its implementation.
>
> > Now I still have two questions regarding the following code:
>
> > (defn my-merge-with [f & maps]
> >   (when (some identity
> > maps)                                                ;; question 1
> >     (reduce (fn [acc m]
> >                      (let [key (key (first  m)) val (val (first
> > m))]          ;; question 2
> >                        (assoc acc key (if-let [old-val (get acc key)]
> >                                                      (f old-val val)
> >                                                       val
> >      {} maps)))
>
> >  (my-merge-with + {"t" 1} {"a" 1} {"c" 1} {"g" 1} {"g" 1} {"g" 1} {"a"
> > 1} {"c" 1} )
> > ;; {"g" 3, "c" 2, "a" 2, "t" 1}
>
> > Question 1:
> > (when (some identity maps)
>
> > This expression from the original implementation checks if the
> > provided coll is empty.
> > However, why not just use (when (empty? maps) or (when (seq maps)
> > instead?
>
> It has the effect that calling (merge-with f nil), or (merge-with f
> nil nil nil), returns nil rather than an empty map. I guess that's the
> reason for it.
>
>
>
>
>
>
>
>
>
> > Question 2:
> > In order to return the key of a map consisting of one key/value pair I
> > have to use the 'first' function, otherwise an exception will be
> > thrown:
>
> > (key {:a "a"})
> > ;; clojure.lang.PersistentArrayMap cannot be cast to java.util.Map
> > $Entry
> > ;;  [Thrown class java.lang.ClassCastException]
>
> > (key (first {:a "a"}))
> > ;; :a
>
> > I understand that 'key' expects a java.util.Map$Entry object, but how
> > exactly does using 'first' accomplish this?
>
> Calling seq on a map returns a sequence of Map$Entry objects (which
> look a lot like two-element vectors, but are not quite the same).
> first calls seq.
>
> - Chris

-- 
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


Regarding The Implementation of 'merge-with'

2010-11-26 Thread Stefan Rohlfing
Dear Clojure Group,

Today I took a closer look at the 'merge-with' function of Clojure
Core and changed some parts to better understand its implementation.

Now I still have two questions regarding the following code:


(defn my-merge-with [f & maps]
  (when (some identity
maps);; question 1
(reduce (fn [acc m]
 (let [key (key (first  m)) val (val (first
m))]  ;; question 2
   (assoc acc key (if-let [old-val (get acc key)]
 (f old-val val)
  val
 {} maps)))



 (my-merge-with + {"t" 1} {"a" 1} {"c" 1} {"g" 1} {"g" 1} {"g" 1} {"a"
1} {"c" 1} )
;; {"g" 3, "c" 2, "a" 2, "t" 1}

Question 1:
(when (some identity maps)

This expression from the original implementation checks if the
provided coll is empty.
However, why not just use (when (empty? maps) or (when (seq maps)
instead?

Question 2:
In order to return the key of a map consisting of one key/value pair I
have to use the 'first' function, otherwise an exception will be
thrown:

(key {:a "a"})
;; clojure.lang.PersistentArrayMap cannot be cast to java.util.Map
$Entry
;;  [Thrown class java.lang.ClassCastException]

(key (first {:a "a"}))
;; :a

I understand that 'key' expects a java.util.Map$Entry object, but how
exactly does using 'first' accomplish this?

(first {:a "a"})
;; [:a "a"]

[:a "a"] is not a vector because the 'key' function does not work on a
vector:

(key [:a "a"])
;; clojure.lang.PersistentVector cannot be cast to java.util.Map$Entry
;;   [Thrown class java.lang.ClassCastException]

Any suggestions are very welcome!

Stefan

-- 
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: Problem adjusting the implementation of 'partition'

2010-11-22 Thread Stefan Rohlfing
Fantastic! Thanks again!

On Nov 23, 3:50 pm, Benny Tsai  wrote:
> Indeed there is :)
>
> http://clojuredocs.org/clojure_core/clojure.core/cycle
>
> On Nov 23, 12:37 am, Stefan Rohlfing 
> wrote:
>
>
>
>
>
>
>
> > Hi Benny,
>
> > Your solution is much more elegant and flexible as my hacking of the
> > core function!
>
> > How would you implement 'pad-padding' (I like this name) if every item
> > of the padding should be repeated in order, not only the last one?
>
> > (defn pad-padding [padding]
> >   (concat padding (repeat padding)))
>
> > does not work because of the additional parentheses around 'padding'.
>
> > Is there a function that circles through the elements of a coll such
> > as:
>
> > (take 10 (circle [1 2 3]))
> > ;; (1 2 3 1 2 3 1 2 3 1)
>
> > Stefan
>
> > On Nov 23, 3:17 pm, Benny Tsai  wrote:
>
> > > Since (repeat) returns a lazy sequence, and partition will only take
> > > as many as is needed, I think you don't even have to specify how many
> > > times to repeat:
>
> > > user=> (partition 3 3 (repeat "a") [1 2 3 4 5 6 7])
> > > ((1 2 3) (4 5 6) (7 "a" "a"))
>
> > > And if the desired behavior is to repeat the last element of provided
> > > padding as many times as necessary, you could do it with a little
> > > helper function:
>
> > > (defn pad-padding [padding]
> > >   (concat padding (repeat (last padding
>
> > > user=> (partition 4 4 (pad-padding ["a" "b"]) [1 2 3 4 5 6 7 8 9])
> > > ((1 2 3 4) (5 6 7 8) (9 "a" "b" "b"))
>
> > > On Nov 23, 12:05 am, Meikel Brandmeyer  wrote:
>
> > > > Hi,
>
> > > > while not having looked at your code, partition does what you want:
>
> > > > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7])
> > > > ((1 2 3) (4 5 6) (7 "a" "a"))
> > > > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8])
> > > > ((1 2 3) (4 5 6) (7 8 "a"))
> > > > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8 9])
> > > > ((1 2 3) (4 5 6) (7 8 9))
> > > > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8 9 10])
> > > > ((1 2 3) (4 5 6) (7 8 9) (10 "a" "a"))
>
> > > > (Note: the 3 in repeat is not strictily necessary. 2 would be
> > > > sufficient)
>
> > > > Sincerely
> > > > Meikel

-- 
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: Problem adjusting the implementation of 'partition'

2010-11-22 Thread Stefan Rohlfing
Hi Benny,

This implementation looks great!

If I could only find out what went wrong with my (not so elegant)
solution...

Stefan

On Nov 23, 3:30 pm, Benny Tsai  wrote:
> Or, to put it all together into a modified partition:
>
> (defn my-partition
>   ([n coll]
>      (partition n n coll))
>   ([n step coll]
>      (partition n step coll))
>   ([n step pad coll]
>      (let [expanded-pad (concat pad (repeat (last pad)))]
>        (partition n step expanded-pad coll
>
> user=> (my-partition 4 4 ["a" "b"] [1 2 3 4 5 6 7 8 9])
> ((1 2 3 4) (5 6 7 8) (9 "a" "b" "b"))
>
> On Nov 23, 12:25 am, Benny Tsai  wrote:
>
>
>
>
>
>
>
> > Sorry, pad-padding is a terrible name choice on my part :)  Maybe
> > something like "repeat-last" would be at least a little bit better.
>
> > On Nov 23, 12:17 am, Benny Tsai  wrote:
>
> > > Since (repeat) returns a lazy sequence, and partition will only take
> > > as many as is needed, I think you don't even have to specify how many
> > > times to repeat:
>
> > > user=> (partition 3 3 (repeat "a") [1 2 3 4 5 6 7])
> > > ((1 2 3) (4 5 6) (7 "a" "a"))
>
> > > And if the desired behavior is to repeat the last element of provided
> > > padding as many times as necessary, you could do it with a little
> > > helper function:
>
> > > (defn pad-padding [padding]
> > >   (concat padding (repeat (last padding
>
> > > user=> (partition 4 4 (pad-padding ["a" "b"]) [1 2 3 4 5 6 7 8 9])
> > > ((1 2 3 4) (5 6 7 8) (9 "a" "b" "b"))
>
> > > On Nov 23, 12:05 am, Meikel Brandmeyer  wrote:
>
> > > > Hi,
>
> > > > while not having looked at your code, partition does what you want:
>
> > > > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7])
> > > > ((1 2 3) (4 5 6) (7 "a" "a"))
> > > > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8])
> > > > ((1 2 3) (4 5 6) (7 8 "a"))
> > > > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8 9])
> > > > ((1 2 3) (4 5 6) (7 8 9))
> > > > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8 9 10])
> > > > ((1 2 3) (4 5 6) (7 8 9) (10 "a" "a"))
>
> > > > (Note: the 3 in repeat is not strictily necessary. 2 would be
> > > > sufficient)
>
> > > > Sincerely
> > > > Meikel

-- 
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: Problem adjusting the implementation of 'partition'

2010-11-22 Thread Stefan Rohlfing
Hi Benny,

Your solution is much more elegant and flexible as my hacking of the
core function!

How would you implement 'pad-padding' (I like this name) if every item
of the padding should be repeated in order, not only the last one?

(defn pad-padding [padding]
  (concat padding (repeat padding)))

does not work because of the additional parentheses around 'padding'.

Is there a function that circles through the elements of a coll such
as:

(take 10 (circle [1 2 3]))
;; (1 2 3 1 2 3 1 2 3 1)

Stefan

On Nov 23, 3:17 pm, Benny Tsai  wrote:
> Since (repeat) returns a lazy sequence, and partition will only take
> as many as is needed, I think you don't even have to specify how many
> times to repeat:
>
> user=> (partition 3 3 (repeat "a") [1 2 3 4 5 6 7])
> ((1 2 3) (4 5 6) (7 "a" "a"))
>
> And if the desired behavior is to repeat the last element of provided
> padding as many times as necessary, you could do it with a little
> helper function:
>
> (defn pad-padding [padding]
>   (concat padding (repeat (last padding
>
> user=> (partition 4 4 (pad-padding ["a" "b"]) [1 2 3 4 5 6 7 8 9])
> ((1 2 3 4) (5 6 7 8) (9 "a" "b" "b"))
>
> On Nov 23, 12:05 am, Meikel Brandmeyer  wrote:
>
>
>
>
>
>
>
> > Hi,
>
> > while not having looked at your code, partition does what you want:
>
> > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7])
> > ((1 2 3) (4 5 6) (7 "a" "a"))
> > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8])
> > ((1 2 3) (4 5 6) (7 8 "a"))
> > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8 9])
> > ((1 2 3) (4 5 6) (7 8 9))
> > user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8 9 10])
> > ((1 2 3) (4 5 6) (7 8 9) (10 "a" "a"))
>
> > (Note: the 3 in repeat is not strictily necessary. 2 would be
> > sufficient)
>
> > Sincerely
> > Meikel

-- 
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: Problem adjusting the implementation of 'partition'

2010-11-22 Thread Stefan Rohlfing
Hi Meikel,

What I want to accomplish is to have the function 'fill the gap' if
not enough padding is supplied.

With the standard 'partition' function this does not work, as it only
adds as much padding as provided:

(partition 3 3 ["a"] [1 2 3 4 5 6 7 8 9 10])
;; ((1 2 3) (4 5 6) (7 8 9) (10 "a"))

I thought my implementation would solve this problem, but
unfortunately there is some bug in the code I haven't been able to
find.

Stefan


On Nov 23, 3:05 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> while not having looked at your code, partition does what you want:
>
> user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7])
> ((1 2 3) (4 5 6) (7 "a" "a"))
> user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8])
> ((1 2 3) (4 5 6) (7 8 "a"))
> user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8 9])
> ((1 2 3) (4 5 6) (7 8 9))
> user=> (partition 3 3 (repeat 3 "a") [1 2 3 4 5 6 7 8 9 10])
> ((1 2 3) (4 5 6) (7 8 9) (10 "a" "a"))
>
> (Note: the 3 in repeat is not strictily necessary. 2 would be
> sufficient)
>
> Sincerely
> Meikel

-- 
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


Problem adjusting the implementation of 'partition'

2010-11-22 Thread Stefan Rohlfing
Dear Clojure Group,

I am trying to adjust the implementation of the 'partition' function
so that the last element of a provided padding such as ["a" "b"] will
be repeated if necessary to ensure the length of the last list
returned by 'padding' is the same as the other lists.

This is the original implementation of 'padding':

(defn partition [n coll]
 (partition n n coll))
  ([n step coll]
 (lazy-seq
   (when-let [s (seq coll)]
 (let [p (take n s)]
   (when (= n (count p))
 (cons p (partition n step (drop step s
  ([n step pad coll]
 (lazy-seq
   (when-let [s (seq coll)]
 (let [p (take n s)]
   (if (= n (count p))
 (cons p (partition n step pad (drop step s)))
 (list (take n (concat p pad)

And here is my implementation of 'my-partition':

(defn my-partition
  ([n coll]
 (partition n n coll))
  ([n step coll]
 (lazy-seq
   (when-let [s (seq coll)]
 (let [p (take n s)]
   (when (= n (count p)) ;; 1)
 (cons p (partition n step (drop step s
  ([n step pad coll]
 (lazy-seq
  (when-let [s (seq coll)]
 (let [p (take n s)]
   (if (= n (count p))
 (cons p (partition n step pad (drop step s)))
 ;; Changed from here on:
 (let [padding (take n (concat p pad))]
   (if (= n (count padding))
 (list padding)
 (list (take n (concat padding (repeat (last 
padding)


Unfortunately this doesn't work as 'partition' and 'my-partition' both
return the same result when 'my-partition' should add additional
padding instead:

(partition 3 3 ["a"] [1 2 3 4 5 6 7])
;; ((1 2 3) (4 5 6) (7 "a"))

(my-partition 3 3 ["a"] [1 2 3 4 5 6 7])
;; ((1 2 3) (4 5 6) (7 "a"))
;; Should be: ((1 2 3) (4 5 6) (7 "a" "a" "a"))

I believe that the last step is OK as it returns the expected result:

(def pad ["a" "b"])

(take 10 (concat [1 2 "a"] (repeat (last pad
;; (1 2 "a" "b" "b" "b" "b" "b" "b" "b")

Does anybody know where I made a mistake? Any suggestions are highly
appreciated!

Stefan

-- 
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: Trying to Load An Alias from Another Namespace into The Current Namespace

2010-10-24 Thread Stefan Rohlfing
Thanks for pointing this out.

Adding the namespace declaration was exactly the reason why loading
the file did not work in the first place.

Now everything is working like a charm, and thanks to you I learnt yet
another piece of the Clojure puzzle!

Best regards,

Stefan

On Oct 24, 10:54 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> On 24 Okt., 04:00, Stefan Rohlfing  wrote:
>
> > This is what I did:
> > -
> > src/active-record/tns.clj
>
> > (ns active-record.tns)
>
> > (require '[active-record.user :as user])
> > (require '[active-record.charge :as charge])
>
> You should not add a ns clause in this file. It acts like a C header
> would work. If you add a ns clause the namespace is changed again and
> the aliases are not done in the namespace which loads the file.
>
> Sincerely
> Meikel

-- 
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: Trying to Load An Alias from Another Namespace into The Current Namespace

2010-10-23 Thread Stefan Rohlfing
I started Emacs again and now your solution is working! I have no idea
why it did not work on the first restart but I am happy that I now can
import aliases from another namespace.

Thanks again for your help!

Stefan

On Oct 24, 10:00 am, Stefan Rohlfing 
wrote:
> Hi Mikel,
>
> I tried your solution but am still not able to import the aliases from
> another namespace:
>
> This is what I did:
> -
> src/active-record/tns.clj
>
> (ns active-record.tns)
>
> (require '[active-record.user :as user])
> (require '[active-record.charge :as charge])
>
> -
>
> Clojure core file: src/active-record/program/core.clj
>
> (ns active-record.program.core)
>
> (load "/active_record/tns")
> ;; Returns nil
> ;; I had to change 'active-record' to 'active_record'
>
> (user/create
>  {:login "my-login"
>    :first_name "Jonas"
>    :last_name "Rohl"
>    :password "secret"
>    :email_address "jo...@example.com"})
>
> ;; Evaluation throws an exception:
> ;; No such var: user/create
> ;;  [Thrown class java.lang.Exception]
> ;; Same error message as before.
>
> (charge/create
>  {:user_id 10,
>   :amount_dollars 244
>   :amount_cents 91
>   :category "meals"
>   :vendor_name "Metro"
>   :date "2010-01-15"})
>
> ;; Evaluation throws an exception:
> ;; No such namespace: charge
> ;;  [Thrown class java.lang.Exception]
> ;; Same error message as before.
>
> -
>
> I restarted Emacs after making the above changes to my code.
>
> Maybe it is just not possible to import aliases from another
> namespace?
>
> Stefan
>
> On Oct 21, 7:47 pm, Meikel Brandmeyer  wrote:
>
>
>
>
>
>
>
> > Hi,
>
> > you can't transfer aliases from one namespace to another. But as a
> > workaround, you can create a file which contains the necessary
> > commands:
>
> > active-record/tables.clj:
> > (require '[active-record.user :as user])
> > (require '[active-record.charge :as charge])
>
> > And then just load the file in the namespaces you want to use the
> > tables.
>
> > (ns active-record.program.core
> >   (:load "tables"))
> > ...
> > ---
> > (ns active-record.program.different-namespace
> >   (:load "tables"))
> > ...
>
> > (You might have to use "active-record/tables". Haven't used load in a
> > while. But without .clj extension!)
>
> > Sincerely
> > Meikel

-- 
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: Trying to Load An Alias from Another Namespace into The Current Namespace

2010-10-23 Thread Stefan Rohlfing
Hi Mikel,

I tried your solution but am still not able to import the aliases from
another namespace:

This is what I did:
-
src/active-record/tns.clj

(ns active-record.tns)

(require '[active-record.user :as user])
(require '[active-record.charge :as charge])

-

Clojure core file: src/active-record/program/core.clj

(ns active-record.program.core)

(load "/active_record/tns")
;; Returns nil
;; I had to change 'active-record' to 'active_record'


(user/create
 {:login "my-login"
   :first_name "Jonas"
   :last_name "Rohl"
   :password "secret"
   :email_address "jo...@example.com"})

;; Evaluation throws an exception:
;; No such var: user/create
;;  [Thrown class java.lang.Exception]
;; Same error message as before.


(charge/create
 {:user_id 10,
  :amount_dollars 244
  :amount_cents 91
  :category "meals"
  :vendor_name "Metro"
  :date "2010-01-15"})

;; Evaluation throws an exception:
;; No such namespace: charge
;;  [Thrown class java.lang.Exception]
;; Same error message as before.

-

I restarted Emacs after making the above changes to my code.

Maybe it is just not possible to import aliases from another
namespace?


Stefan


On Oct 21, 7:47 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> you can't transfer aliases from one namespace to another. But as a
> workaround, you can create a file which contains the necessary
> commands:
>
> active-record/tables.clj:
> (require '[active-record.user :as user])
> (require '[active-record.charge :as charge])
>
> And then just load the file in the namespaces you want to use the
> tables.
>
> (ns active-record.program.core
>   (:load "tables"))
> ...
> ---
> (ns active-record.program.different-namespace
>   (:load "tables"))
> ...
>
> (You might have to use "active-record/tables". Haven't used load in a
> while. But without .clj extension!)
>
> Sincerely
> Meikel

-- 
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: Trying to Load An Alias from Another Namespace into The Current Namespace

2010-10-23 Thread Stefan Rohlfing
Thanks for the great explanation. This really makes using the clj-
record library much more comfortable!

Stefan


PS. Sorry for replying late. I could not get my VPN to work which
meant Google Groups was blocked for me.


On Oct 21, 7:47 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> you can't transfer aliases from one namespace to another. But as a
> workaround, you can create a file which contains the necessary
> commands:
>
> active-record/tables.clj:
> (require '[active-record.user :as user])
> (require '[active-record.charge :as charge])
>
> And then just load the file in the namespaces you want to use the
> tables.
>
> (ns active-record.program.core
>   (:load "tables"))
> ...
> ---
> (ns active-record.program.different-namespace
>   (:load "tables"))
> ...
>
> (You might have to use "active-record/tables". Haven't used load in a
> while. But without .clj extension!)
>
> Sincerely
> Meikel

-- 
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


Trying to Load An Alias from Another Namespace into The Current Namespace

2010-10-21 Thread Stefan Rohlfing
Dear Clojure group,

The library clj-record requires to add a source file for every table
in a given database.

This can lead to a lot of files whose namespaces have to be imported
wherever you want to work on the tables.

In order to avoid having to write the whole namespace declaration
every time, I decided put it into a file on its own and load this
namespace via (ns :use...).

The problem is I also have to be able to use an alias with each of the
table files like this:

Table file 1: src/active-record/user.clj

---

Table file 2: src/active-record/charge.clj

---

File to hold load and alias the namespaces of the table files:
src/active-record/tns.clj

 (ns active-record.tns
   (:require [active-record.user :as user])
   (:require [active-record.charge :as charge]))

---

Clojure core file: src/active-record/program/core.clj

(ns active-record.program.core
  (:use active-record.tns))

;; Evaluation returns nil


(user/create
 {:login "my-login"
   :first_name "Jonas"
   :last_name "Rohl"
   :password "secret"
   :email_address "jo...@example.com"})

;; Evaluation throws an exception:
;; No such var: user/create
;;  [Thrown class java.lang.Exception]


(charge/create
 {:user_id 10,
  :amount_dollars 244
  :amount_cents 91
  :category "meals"
  :vendor_name "Metro"
  :date "2010-01-15"})

;; Evaluation throws an exception:
;; No such namespace: charge
;;  [Thrown class java.lang.Exception]

---


I restarted Emacs and tried again but got the same error messages.

Maybe I messed up the namespace declarations again but it could also
be that referring to an alias that was created in another namespace
might not be possible.

Does anybody know which one is the case?

Stefan

-- 
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: clj-record Library: Handling Namespaces

2010-10-20 Thread Stefan Rohlfing
I apologize for presenting you with a moving target. That was
definitely not my attention.

I should have realized I messed up the content of the files but
unfortunately had no clue what all these exceptions meant.

Therefore I really appreciate your detailed description of the
conclusion you draw from the different error messages.

Thanks again for your great help!

Stefan





On Oct 20, 8:34 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> On 20 Okt., 14:04, Stefan Rohlfing  wrote:
>
> > I really learned at lot about dealing with namespaces today.
>
> I hope you also learned a bit about error messages. ;)
>
> "No such var: user/create": That means you get past the namespace
> declaration. Hence they load fine. But in the user namespace the model-
> init call was obviously not done. => Possible questions: maybe the
> file was not saved? maybe there is a spurious .class file around
> messing up things from a previous AOT compilation run?
>
> "EOF while reading": Now something changed. Either in one of
> the :required namespaces was a syntax error introduced, or the init-
> model now happens and the syntax error is in a-r.program.core after
> the user/create call.
>
> I remembered darkly that I had once trouble with Vars which had the
> same name as an alias. Hence my questions: "Did you try the same with
> charge instead of user?" => Different alias. Does it work? Then the
> problem could be the alias.
>
> "No such namespace: charge": So the alias is not done. That means that
> the error is either in user, during its alias creation or charge
> itself. Just to be sure my question: "Does it work with a different
> alias instead of user?"
>
> "Unable to resolve symbol: user=> in this context": again something
> changed in the files between our conversation. So we are targeting a
> moving target. Hence my request to really check the files and - if in
> doubt - use a fresh repl to get a clear foundattion.
>
> There were several occasions in the above description, where I'm
> expected an exception, but you didn't report one, and where I'm not
> sure whether this was due to the repl interaction or other side
> effects (eg. unsaved files, etc.). Also your positive report in the
> end leaves the question why it actually works now. From the code you
> pasted it should have worked from the beginning.
>
> Anyway, it works. :)
>
> Sincerely
> Meikel

-- 
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: clj-record Library: Handling Namespaces

2010-10-20 Thread Stefan Rohlfing
You were right again. I left a code snippet from the book in
charge.clj and forgot to remove it later.

Now everything seems to work fine, even when importing the active-
record.user namespace as 'user':


(ns active-record.program.core
   (:require [active-record.user :as user])
   (:require [active-record.charge :as charge]))

(user/create
 {:login "my-login"
  :first_name "Stefan"
  :last_name "Rohl"
  :password "secret"
  :email_address "ste...@example.com"})

;; {:email_address "ste...@example.com", :password "secret",
;;  :last_name "Rohl", :first_name "Stefan", :login "my-login",
;;  :id 8}

(charge/create
 {:user_id 8,
  :amount_dollars 27
  :amount_cents 91
  :category "meals"
  :vendor_name "Metro"
  :date "2010-01-15"})

;; {:date "2010-01-15", :vendor_name "Metro", :category "meals",
;;  :amount_cents 91, :amount_dollars 27, :id 7,
;;  :user_id 8}



Thank you so much for your help! I really learned at lot about dealing
with namespaces today.

Stefan


On Oct 20, 5:45 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> On 20 Okt., 11:35, Stefan Rohlfing  wrote:
>
> > Evaluating your suggested declaration:
>
> >  (ns active-record.program.core
> >    (:require [active-record.user :as u])
> >    (:require [active-record.charge :as charge]))
>
> > I get the following error message:
>
> > ;; Unable to resolve symbol: user=> in this context
> > ;;   [Thrown class java.lang.Exception]
>
> You copy'n'pasted a clojure prompt somewhere or your repl is messed
> up. Please check your files thoroughly and (if necessary) start with a
> fresh repl.
>
> Sincerely
> Meikel

-- 
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: clj-record Library: Handling Namespaces

2010-10-20 Thread Stefan Rohlfing
Evaluating your suggested declaration:

 (ns active-record.program.core
   (:require [active-record.user :as u])
   (:require [active-record.charge :as charge]))

I get the following error message:

;; Unable to resolve symbol: user=> in this context
;;   [Thrown class java.lang.Exception]

The same happens if I do not include the active-record.user namespace:

(ns active-record.program.core
   (:require [active-record.charge :as charge]))


;; Unable to resolve symbol: user=> in this context
;;   [Thrown class java.lang.Exception]


On Oct 20, 5:23 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> On 20 Okt., 11:09, Stefan Rohlfing  wrote:
>
> > Yes, I also tried charge/create. The error message is different, but
> > it still does not work:
>
> More evidence for a problem with the user alias. Try a different one
> like (:require [active-record.user :as u]).
>
> Sincerely
> Meikel

-- 
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: clj-record Library: Handling Namespaces

2010-10-20 Thread Stefan Rohlfing
Yes, I also tried charge/create. The error message is different, but
it still does not work:

;; No such namespace: charge
;;  [Thrown class java.lang.Exception]


On Oct 20, 5:03 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> On 20 Okt., 10:46, Stefan Rohlfing  wrote:
>
> > You are right, there was a syntax error in charge.clj. However, after
> > correcting the error I get the same error message as with the other
> > namespace declaration:
>
> Did you try the same with charge/create? Examples in books are not
> necessarily correct.
>
> Sincerely
> Meikel

-- 
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: clj-record Library: Handling Namespaces

2010-10-20 Thread Stefan Rohlfing
You are right, there was a syntax error in charge.clj. However, after
correcting the error I get the same error message as with the other
namespace declaration:

;; No such var: user/create
;;   [Thrown class java.lang.Exception]

On Oct 20, 4:37 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> On 20 Okt., 10:09, Stefan Rohlfing  wrote:
>
> > ;; EOF while reading
> > ;;  [Thrown class java.lang.Exception]
>
> Are you sure, that you don't have some syntax error somewhere?
>
> Sincerely
> Meikel

-- 
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: clj-record Library: Handling Namespaces

2010-10-20 Thread Stefan Rohlfing
The name 'user' is taken from an example in the book. The author
executes the code at the REPL like this:

(require '(active-record [user :as user]))

user=> (user/create {:login "rob"
 :first_name "Robert"
 :last_name "Berger"
 :password "secret"
 :email_address "r...@runa.com"})

And then there is the clj-record macro 'init-model' that creates a
model out of a Clojure namespace. However, I don't quite understand
how this affects bringing in the namespaces.
Here is the code:
http://github.com/duelinmarkers/clj-record/blob/master/src/clj_record/core.clj
(at the bottom)



On Oct 20, 4:20 pm, Michael Wood  wrote:
> On 20 October 2010 10:09, Stefan Rohlfing  wrote:
>
>
>
>
>
>
>
>
>
> > Dear Clojure group,
>
> > I am currently reading chapter 9.1 MySQL & clj-record of 'Clojure in
> > Action'.
>
> > clj-record seems pretty awesome, but I once again got lost in
> > namespace jungle.
>
> > Here is a concrete example:
>
> > --- 
> > -
>
> > File 1: src/active-record/credentials.clj
> > [Database credentials]
>
> > (ns active-record.credentials)
>
> > (def db
> >     {:classname "com.mysql.jdbc.Driver"
> >      :subprotocol "mysql"
> >      :user ""
> >      :password ""
> >      :subname "//localhost:3306/damages_dev"
> >      })
>
> > --- 
> > -
>
> > File 2: src/active-record/user.clj
> > [Belongs to the database name with the name 'users']
>
> > (ns active-record.user
> >  (:use [active-record.credentials :only [db]])
> >  (:require clj-record.boot))
>
> >  (clj-record.core/init-model
> >   (:associations
> >    (has-many charges)))
>
> > --- 
> > -
>
> > File 3: src/active-record/charge.clj
> > [Belongs to the database name with the name 'charges']
>
> > (ns active-record.user
> >  (:use [active-record.credentials :only [db]])
> >  (:require clj-record.boot))
>
> >  (clj-record.core/init-model
> >   (:associations
> >    (has-many charges)))
>
> > --- 
> > -
>
> > I want to add/remove/alter table entries in a different file:
>
> > File 4: src/active-record/program/core.clj
>
> > All my efforts to import the user.clj and charge.clj namespaces have
> > failed so far. For example, I have tried the following namespace
> > declaration:
>
> >  (ns active-record.program.core
> >   (:require [active-record.user :as user])
>
> Just a guess, but try something other than "user".  The user namespace
> is the default namespace when using the repl and maybe there's some
> sort of conflict there.
>
> I'm not sure how likely that is, but it's worth a try, I think :)
>
>
>
>
>
>
>
>
>
> >   (:require [active-record.charge :as charge])
> >     (:require clj-record.boot))
>
> > (user/create
> >  {:login "rob"
> > :first_name "Robert"
> > :last_name "Berger"
> > :password "secret"
> > :email_address "r...@runa.com"})
>
> > ;; No such var: user/create
> > ;;  [Thrown class java.lang.Exception]
>
> > This one doesn't work either:
>
> >  (ns active-record.program.core
> >   (:require [active-record.user :as user])
> >   (:require [active-record.charge :as charge]))
>
> > ;; EOF while reading
> > ;;  [Thrown class java.lang.Exception]
>
> > Can anybody tell me what went wrong in the example above?
>
> --
> Michael Wood 

-- 
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


clj-record Library: Handling Namespaces

2010-10-20 Thread Stefan Rohlfing
Dear Clojure group,

I am currently reading chapter 9.1 MySQL & clj-record of 'Clojure in
Action'.

clj-record seems pretty awesome, but I once again got lost in
namespace jungle.

Here is a concrete example:



File 1: src/active-record/credentials.clj
[Database credentials]

(ns active-record.credentials)

(def db
 {:classname "com.mysql.jdbc.Driver"
  :subprotocol "mysql"
  :user ""
  :password ""
  :subname "//localhost:3306/damages_dev"
  })




File 2: src/active-record/user.clj
[Belongs to the database name with the name 'users']


(ns active-record.user
  (:use [active-record.credentials :only [db]])
  (:require clj-record.boot))


  (clj-record.core/init-model
   (:associations
(has-many charges)))





File 3: src/active-record/charge.clj
[Belongs to the database name with the name 'charges']


(ns active-record.user
  (:use [active-record.credentials :only [db]])
  (:require clj-record.boot))


  (clj-record.core/init-model
   (:associations
(has-many charges)))




I want to add/remove/alter table entries in a different file:

File 4: src/active-record/program/core.clj

All my efforts to import the user.clj and charge.clj namespaces have
failed so far. For example, I have tried the following namespace
declaration:

 (ns active-record.program.core
   (:require [active-record.user :as user])
   (:require [active-record.charge :as charge])
 (:require clj-record.boot))


(user/create
 {:login "rob"
:first_name "Robert"
:last_name "Berger"
:password "secret"
:email_address "r...@runa.com"})

;; No such var: user/create
;;  [Thrown class java.lang.Exception]



This one doesn't work either:

 (ns active-record.program.core
   (:require [active-record.user :as user])
   (:require [active-record.charge :as charge]))

;; EOF while reading
;;  [Thrown class java.lang.Exception]



Can anybody tell me what went wrong in the example above?


Stefan

-- 
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 Stefan Rohlfing
Thanks again for these beautiful code examples!

I haven't come across (apply map ... before so this is idiom a big
step forward for me.

The same is true for the extended use of 'reduce'. I know that this
function is really powerful but I am only just beginning to understand
its potential.

Sometimes I feel a bit overwhelmed by the flexibility of Clojure.
Therefore, reading idiomatic code like your examples really helps me a
lot.

Stefan

-- 
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 Stefan Rohlfing
Thank you all for your great code examples!

The goal of the function 'd-map' is to return a collection of maps
that looks like this:

 ({:headline "this", :points 1, :comments 10}
  {:headline "is", :points 2, :comments 20}
  {:headline "me", :points 3, :comments 30})


Based on Per's example using 'for' I came up with the following
implementation:

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

(defn d-map [& args]
  (let [kv-list (for [ [head items] args, item items] [head item])
 len  (count args)]
 (map #(into {} %)
 (partition len (apply interleave (partition len kv-
list))


This is quite a few functions for turning 'kv-list':

([:headline "this"] [:headline "is"] [:headline "me"] [:points 1]
[:points 2] ...)

into:
({:headline "this", :points 1, :comments 10} {:headline "is", :points
2, ...} ...)


Therefore, I would like to ask again if there is a more elegant way to
get to this result.

Stefan

-- 
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


Is This Function Idiomatic Clojure?

2010-10-06 Thread Stefan Rohlfing
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

I am relatively new to Clojure and want to learn how to write
idiomatic code. I therefore appreciate any alternative implementation
that might help me learn some new things.

Stefan

-- 
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: Macro Implementation: I Don't Understand This Error Message

2010-10-01 Thread Stefan Rohlfing
@Jürgen and Chris

Thank you very much for helping me enlarge my understanding of macros!

I realize that learning the subtleties of a macro implementation is
not easy but well worth the effort.

It is also quite interesting that a macro as it seems takes two
implicit extra arguments. I am curious what these arguments might be
and hope someone can tell us.

Stefan

> Actually, it's not. That's becuase the compiler inserts a couple of
> extra implicit arguments to all calls to macros. So in fact, my-infix,
> at runtime, expects 3 arguments. Check this out:
>
> user=> (defmacro foo [x] x)
> #'user/foo
> user=> (foo 23)
> 23
> user=> (def foo2 (var-get #'foo))
> #'user/foo2
> user=> (foo2 23)
> java.lang.IllegalArgumentException: Wrong number of args (1) passed
> to: user$foo (NO_SOURCE_FILE:0)
> user=> (foo2 23 34 45)
> 45
>
> I hope that makes it clearer. I certainly feel like I understand
> macros a little better after figuring this out.
>
> As for what exactly the two implicit args to macros are - I don't
> know. Someone else will have to explain that.
>
> - Chris

-- 
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


Macro Implementation: I Don't Understand This Error Message

2010-10-01 Thread Stefan Rohlfing
Dear Clojure Group,

I wanted to expand the 'infix' macro presented in chapter 7.3.1 of
'Clojure in Action' to handle nested s-expressions:

My first version did not work:

(defmacro my-infix [expr]
  (if (coll? expr)
(let [ [left op right] expr]
  (list op (my-infix left) (my-infix right)))
expr))

;; Test:
(my-infix ((3 * 5) - (1 + 1)))

;; Wrong number of args (1) passed to: user$my-infix
;;  [Thrown class java.lang.IllegalArgumentException]


However, the following version does work:

(defmacro new-infix [expr]
  (if (coll? expr)
(let [ [left op right] expr]
  `(~op (new-infix ~left) (new-infix ~right)))
expr))

(new-infix ((3 * 5) - (1 + 1)))
;; --> 13

(macroexpand '(new-infix ((3 * 5) - (1 + 1

;; (- (user/new-infix (3 * 5)) (user/new-infix (1 + 1)))


I would love to know why the first version 'my-infix' throws an
exception. Can anybody give me a hint? I hope the answer could give me
a better understanding of how macros work.

-- 
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: Some Problem with Recursion

2010-09-10 Thread Stefan Rohlfing
Hi Laurent,

Thanks for your detailed explanation! It greatly helped me understand
the usage of quoting.

Stefan

On Sep 10, 5:27 pm, Laurent PETIT  wrote:
> 2010/9/10 Stefan Rohlfing :
>
>
>
>
>
>
>
>
>
> > @ Nicolas and ajuc
>
> > Thank you very much for showing me where I went wrong! With so many
> > parentheses it sometimes happens that I misplace one
>
> > Now the output of the function is as expected:
>
> > (defn prefix->postfix [expr]
> >  (if (coll? expr)
> >    (let [ [op arg1 arg2] expr]
> >      [ (prefix->postfix arg1) (prefix->postfix arg2) op])  ;; <--
> > removed on parenthesis here
> >  expr))
>
> > (prefix->postfix '(+ 2 (* 3 2)))
> > ;; --> [2 [3 2 *] +]
>
> > There is just one point I still don't quite understand. That is,
> > during one of the recursive calls, the expression (* 3 2) is passed as
> > an argument to prefix->postfix:
>
> > (prefix->postfix (* 3 2))
>
> > As prefix->postfix is a normal function and not a macro, (* 3 2)
> > should get evaluated BEFORE being passed to the function. However,
> > this is not the case here.
>
> > Could it be that because (* 3 2) is quoted, because the initial
> > argument to the function, '(+ 2 (* 3 2)), was quoted?
>
> > Could it be that because the initial argument to prefix->postfix, '(+
> > 2 (* 3 2)), is quoted, (* 3 2) is also quoted and therefore does not
> > get evaluated?
>
> Yes. '(+ 2 (* 3 2)) being quoted means that the function receives a
> datastructure : a list composed of the symbol +, the number 2, and
> finally a list composed of the symbol *, the number 3 and the number
> 2.
> ' is a syntactic sugar for the special form named quote , whose
> purpose is to not evaluate everything which is quoted, and just keep
> as a datastructure what the reader has read.
>
> And now, food for thought :-) :
>
> user=> (quote (defn x))
> (defn x)
>
> ;; => See, no macroexpansion, just what the reader read
>
> user=> (read-string "(defn x)")
> (defn x)
>
> ;; => I prove the point of above: just what the reader read
>
> user=> (quote (defn ^{:foo :bar} x))
> (defn x)
>
> ;; => but in the above ^^^, where's :foo :bar ?
>
> user=> (meta (second (quote (defn ^{:foo :bar} x
> {:foo :bar}
>
> ;; => it's there, but the reader has already interpreted the ^
> (because it is a reader macro) and placed {:foo :bar} as the metadata
> map for the symbol x
>
> HTH,
>
> --
> Laurent

-- 
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: Some Problem with Recursion

2010-09-10 Thread Stefan Rohlfing
@ Nicolas and ajuc

Thank you very much for showing me where I went wrong! With so many
parentheses it sometimes happens that I misplace one

Now the output of the function is as expected:

(defn prefix->postfix [expr]
  (if (coll? expr)
(let [ [op arg1 arg2] expr]
  [ (prefix->postfix arg1) (prefix->postfix arg2) op])  ;; <--
removed on parenthesis here
  expr))

(prefix->postfix '(+ 2 (* 3 2)))
;; --> [2 [3 2 *] +]

There is just one point I still don't quite understand. That is,
during one of the recursive calls, the expression (* 3 2) is passed as
an argument to prefix->postfix:

(prefix->postfix (* 3 2))

As prefix->postfix is a normal function and not a macro, (* 3 2)
should get evaluated BEFORE being passed to the function. However,
this is not the case here.

Could it be that because (* 3 2) is quoted, because the initial
argument to the function, '(+ 2 (* 3 2)), was quoted?

Could it be that because the initial argument to prefix->postfix, '(+
2 (* 3 2)), is quoted, (* 3 2) is also quoted and therefore does not
get evaluated?

Stefan

-- 
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: Some Problem with Recursion

2010-09-09 Thread Stefan Rohlfing
The indentation was correct by got messed up when I copying the code.

This is how I interpret the function:
'expr' is only returned if (coll? expr) returns 'false', with is not
the case with an argument such as '(+ 2 4).
Next, this expression is destructured in the 'let' and 'prefix-
>postfix called again:

[ (prefix->postfix 2) (prefix->postfix 4) +]

As 2 and 4 are both not a collection, their values are just returned.
This should lead to this final result:

[2 4 +]

However, no vector is returned, just the initial argument to the
function.

I really want to understand what I did wrong here :-)

Stefan



On Sep 9, 9:08 pm, Nicolas Oury  wrote:
> Yes.
>
> Have someone (for example your editor), do your indentation for you.
> By typing on tab on a good editor, you would have has:
> (defn prefix->postfix [expr]
>    (if (coll? expr)
>      (let [ [op arg1 arg2] expr]
>        [ (prefix->postfix arg1) (prefix->postfix arg2) op]))
>    expr)
>
> which is easier to diagnose. (At least for me)
>
> Have fun with recursion,
>
> Nicolas.

-- 
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


Some Problem with Recursion

2010-09-09 Thread Stefan Rohlfing
In order to get some more insight into recursion I wrote the following
function but ended up in confusion:

(defn prefix->postfix [expr]
  (if (coll? expr)
(let [ [op arg1 arg2] expr]
  [ (prefix->postfix arg1) (prefix->postfix arg2) op]))
expr)

I expected the result to be a vector, such as
(prefix->postfix '(+ 1 2))
;; [1 2 +]

However, the expression passed as an argument is just returned, at
least this is what is looks like:

(prefix->postfix '(* 2 3))
;; --> (* 2 3)

(prefix->postfix '(+ 1 (* 2 3)))
;; --> (+ 1 (* 2 3))


I seems there is still some way to go until I can really 'think in
recursion'.

Therefore I would appreciate if someone could tell me why the above
function is not returning the expected result.

Stefan

-- 
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


Is Advanced Destructuring Considered Idiomatic?

2010-05-21 Thread Stefan Rohlfing
This site http://paste.lisp.org/display/97057 shows various examples
of destructuring in Clojure ranging from basic to advanced. I managed
to follow the more basic examples, but then got quickly lost when I
looked at this one:

(let [ [{a :a b :b c :c :as m :or {a 100 b 200}} [p q r & s] ]
[{:a 5 :c 6} [1 2 3 4 5]] ] [a b c m p q r s])

; Result: [5 200 6 {:a 5, :c 6} 1 2 3 (4 5)]

For example, I don't understand what [p q r & s] is doing here and how
{:a 5, :c 6} ends up in the result.

Other examples such as the following are even more complicated and I
don't even know where to start:

(let [ [ {:keys [a b c]} & [[d & e] {:keys [x y] :or {z 1 y
555}}]]
[ {:a 1 :b 2} "quux" {:x 1000 :y 999}]]
[a b c d e x y])

;; Result: [1 2 nil \q (\u \u \x) 1000 999]

This kind of advanced destructuring makes the code much less readable
for me. But this might just be because I am still new to Clojure.

Therefore I would like to ask the following question:
-- Are the above examples used in 'real' code or do they mainly serve
as examples of what you can do with destructuring? In other words: Is
this idiomatic Clojure coding style?

Thanks in advance!

Stefan

-- 
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: Problem with Destructuring in A Function Call

2010-04-16 Thread Stefan Rohlfing
Your explanations from different angles of the problem were really
helpful. I now have a much better picture of what is going on during
destruturing. Thank you very much!

Stefan

-- 
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