Ways of making a Clojure program?

2009-01-29 Thread timc

I'm struggling to understand exactly what form(s) a Clojure program
can take. In particular, the empty section "The REPL and main entry
points" on the clojure.org web site doesn't help.

Obviously, interacting manually with the REPL is nice for learning the
language, but this becomes tedious as the size of the source
increases. So the question is: what are the different ways that one
can run or package up a Clojure/Java program, so that it is invoked by
running a shell (or DOS cmd) script?

I have got the book by Stuart Holloway, but that does not address this
issue (in its present revision).

Are there any tools to perform this "packaging up"?

I have been trying to use the clojure-dev Eclipse plugin but that does
not seem to be working yet. I work on Windows (using Eclipse) and want
to avoid using Emacs, which I find pretty vile (largely because there
does not seem to be an explanation of it that works).

I apologize if I'm being really dense! I really like the "smell" of
this language and want to use it for real applications.

Regards, Tim

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



How to build tree with nodes that 'point' to each other?

2009-02-12 Thread timc

I'm new to Clojure so this may be a stupid question.

I want to make a tree out of these things:

(defstruct treeNode :parent :children :data)

so that every node knows which node is its parent and which nodes are
its children.

But, given that these things are immutable, I am baffled as to how the
tree may be constructed - in particular how it's possible to make
immutable things that 'point at' each other.

Any guidance on this would be greatly 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
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
-~--~~~~--~~--~--~---



Example of use of Atom: Fibonacci generator

2009-02-15 Thread timc

I'm new to Clojure, just thought I would share this.
I was playing around, trying to understand Atoms and I devised a
function that generates the next value in the Fibonacci sequence each
time it is called.

(def fib-gen-val (atom [1 1]))

(defn fib-gen []
  (let [[a b] @fib-gen-val]
   (swap! fib-gen-val #(let [[x y] %] (vector y (+ x y
a))

Repeated calls to fib-gen return 1 1 2 3 5 ...etc

I could not figure out how to make a proper generator which somehow
initializes its own secret internal state (atom). In particular, I
couldn't find a function (exists? x) which would return true if the
thing x already exists, so that it would be created just once. Then,
how would the particular generator know which such secret atom
belonged to it?

[This is the sort of thing that Icon does (much more generally) with
its generators.
I think it's an interesting exercise to try to implement some sort of
general-purpose Icon-like generator control structure.
Also interesting would be something like the string-scanning control
structure that Icon has.]


--~--~-~--~~~---~--~~
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: Example of use of Atom: Fibonacci generator

2009-02-16 Thread timc

Thanks for these interesting replies - I have some way to go in my
understanding of the power of functional programming.
I look forward to seeing Stuart's chapter 5!

On Feb 16, 11:25 am, Timothy Pratley  wrote:
> Also consider (fromhttp://en.wikibooks.org/wiki/Clojure_Programming/Examples):
>
> (defn fib-seq []
>   ((fn rfib [a b]
>        (lazy-cons a (rfib b (+ a b
>     0 1))
>
> user> (take 20 (fib-seq))
> (0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)
>
> Regards,
> Tim.
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



Please explain

2009-02-27 Thread timc

On the page describing Vars, I cannot get the meaning of this sentence
(a typo has made it incomprehensible I think):

"Bindings created with binding can be assigned to, which provides a
means for nested contexts to communicate with code before it the call
stack."

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



Please take mercy on us newbies

2009-02-27 Thread timc

Can I make a small plea for people who submit source code to PLEASE
insert some sort of explanation of what the code is about.

I know it's usual in programming circles to think that if someone
can't understand something it's because they are dumb - but really -
this is a terribly inefficient way of communicating and also rather
arrogant.

Please don't take this as the start of a war!

Best regards
--~--~-~--~~~---~--~~
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: Please take mercy on us newbies

2009-02-27 Thread timc

OK - choosing files at random:

Is it at all obvious what these do?

app.clj
application-context-patter.clj
binary-structure.clj
bookmark-tut.clj
bsptree.clj
chlam-clean-clj

and so on...

On Feb 27, 9:20 am, Laurent PETIT  wrote:
> What are you talking about ? It's really vague.
>
> It seems to me that people in this list have always been kind to help people
> discovering the language.
> And if you turn it the other way around, maybe people are not always
> explaining each line of code because they don't presuppose that readers will
> mainly be "dumb" or whatever term you want to use?
>
> And also people are taking time to give hints to the person asking, but each
> one's time is precious (most -if not all- people in this list are not paid
> for answering questions).
>
> If there's something you don't understand, have no complex and ask for
> further explanation !
>
> Regards,
> --
> Laurent
>
> 2009/2/27 timc 
>
>
>
> > Can I make a small plea for people who submit source code to PLEASE
> > insert some sort of explanation of what the code is about.
>
> > I know it's usual in programming circles to think that if someone
> > can't understand something it's because they are dumb - but really -
> > this is a terribly inefficient way of communicating and also rather
> > arrogant.
>
> > Please don't take this as the start of a war!
>
> > Best regards
--~--~-~--~~~---~--~~
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: Please take mercy on us newbies

2009-02-27 Thread timc

Thanks for the responses - very helpful.

On Feb 27, 3:24 pm, Chouser  wrote:
> On Fri, Feb 27, 2009 at 10:14 AM, James Reeves
>
>  wrote:
>
> > Just to expand on Meikel's answer: when people upload files, it's
> > usually as an attachment to an existing thread. Reading though the
> > file list isn't a very good way of learning Clojure, as it's just a
> > flat list of every file anyone has ever uploaded to the group. Without
> > the context of the original thread, the files are naturally not going
> > to make a lot of sense when studied in isolation.
>
> It may also be worth noting that the code in the files section of this
> group isn't vetted in any way.  Some may be meant for real world use
> while other files may be examples of a problem or be in error.  Just
> about anyone can upload a file for just about any purpose.
>
> If you're looking for example code to help you learn clojure, there
> are many better options.
>
> The first that comes to mind is the several wikis -- the official
> wikibook link from clojure.org, a tutorial wiki, a wiki attempting to
> show an example of every function in clojure.core, and the clojure
> projecteuler wiki.  All of these contain working examples with
> specific goals, and several of them have lots of English text
> describing what's going on.
>
> Another good place to look is in clojure-contrib.  Code submitted
> there goes through a minimal vetting process and is actively
> maintained by people who take the time to stay current on Clojure's
> growing feature set.
>
> Hope that helps,
> --Chouser
--~--~-~--~~~---~--~~
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-contrib build fails

2009-03-04 Thread timc

After checking out the trunk of clojure-contrib (revision 565) and
doing "ant jar", I get this:

compile_clojure:
 [java] Compiling clojure.contrib.accumulators to C:
\eclipseWS1\clojure-cont
rib\classes
 [java] java.lang.IllegalArgumentException: fn params must be
Symbols (accum
ulators.clj:224)
.etc

Any ideas?

--~--~-~--~~~---~--~~
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-contrib build fails

2009-03-04 Thread timc

Thanks Konrad - that did the trick!

On Mar 4, 5:43 pm, Konrad Hinsen  wrote:
> On Mar 4, 2009, at 18:21, timc wrote:
>
> > After checking out the trunk of clojure-contrib (revision 565) and
> > doing "ant jar", I get this:
>
> > compile_clojure:
> >      [java] Compiling clojure.contrib.accumulators to C:
> > \eclipseWS1\clojure-cont
> > rib\classes
> >      [java] java.lang.IllegalArgumentException: fn params must be
> > Symbols (accum
> > ulators.clj:224)
> > .etc
>
> > Any ideas?
>
> I suspect that your Clojure is a few days old. There was a bug in  
> letfn that Rich fixed quickly, and that bug causes the failure you  
> report. Your copy of Clojure is thus probably the one just before the  
> fix. I suggest updating Clojure and trying again.
>
> Konrad.
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



Confused about vars, symbols, names,...

2009-03-06 Thread timc

I would like to have a function which tells me about the values of a
var, where the parameter to the function is a string equal to the
'name' of the var.

For example:

(defn checkNil [name]
 "If the var with the given (String) name is nil, display a
message; result = value of var".
 (when (nil? (value of the var called name))
(display (str name " is nil")))
 (value of the var called name))

so that

(def x nil)
(checkNil "x")

should display: "x is nil" -- (display s) being a function that shows
the string s somewhere.

The question is, how do I express (value of the var called name)?

I tried this: (var (symbol name))
but that caused the exception: clojure.lang.PersistentList cannot be
cast to clojure.lang.Symbol

Is this possible?


Another way to do it would be as follows.

(defn checkNil [x]
 "If the variable x is nil, display a message; result = value of
x."
 (when (nil? x)
(display (str (name of the var x) ) " is nil")))
   x)

so that

(def x nil)
(checkNil x)

should display: "x is nil".

In this case - how to do: (name of the var x)?
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



Help please: or function

2009-03-09 Thread timc

Can someone please see what's wrong with this.

(defn getArg [arg]
"Return a [keyword value] depending on the form of the string arg:
1. arg is of the form +x ==> [:x true].
2. arg is of the form -x ==> [:x false].
3. arg is of the form x=v ==> [:x v].
4. else ==> [:files arg]."
(let [x (or
   (re-seq #"([+])([a-zA-Z_0-9]+)" arg)
   (re-seq #"([-])([a-zA-Z_0-9]+)" arg)
   (re-seq #"([a-zA-Z_0-9]+)=([^ ]+)" arg))]
(if (nil? x) [:files arg]
(let [x (first x)
y (nth x 1)
z (nth x 2)]
(cond
(= y "+")   [(keyword z) true]
(= y "-")   [(keyword z) false]
:else   [(keyword y) z])

This is part of a command-line-arg processing function. I want to end
up with a map containing things like this:

{:verbose true :fast false :configFile "/tom/dick" :files ["foo" "bar"
"zot"]}

as a result of processing the command line args:

+verbose -fast configFile=/tom/dick foo bar zot

Now...

(getArg "+foo") correctly returns [:foo true]

however

(getArg "-foo") throws a NullPointerException.

Am I wrong in my understanding of the or function? That is, that (or a
b c) should return the first of a,b,c that returns true (i.e. non-nil)
or nil if they are all nil?

Or is something happening to the function 'arg' inside the let?


Thanks in advance.

---
In case it's interesting to anyone, the other part of this (that calls
getArg) is the following.

(defn getArgs [args & xs]
"This processes args (a seq of strings) and returns a map.
The parameter xs is a seq of two-element vectors: [keyword value].
The returned map contains (keyword,value) pairs produced by
processing the args, as follows.
1. An arg of the form +x creates the pair (:x true).
2. An arg of the form -x creates the pair (:x false).
3. An arg of the form x=v creates the pair (:x v), where v is a
string.
4. Any other args will be placed in the pair (:files
vectorOfStrings).
5. Any [x v] in xs, not found in the args, will create the pair (:x
v)."
(let [res {:files []}]
; First process the args (if any).
(when args (doall (for [arg args]
(let [ga (getArg arg) [key val] ga]
(cond
(= key :files) (conj (:files res) val)
:else  (conj res ga))
; Now process the xs (if any).
(when xs (doall (for [x xs]
(let [key (first x)]
(when (not (key res)) (conj res x))
res))

so that (for example)

(def cmdArgs (getArgs *command-line-args* [[:verbose false] [:fast
true] [:configFile "/tom/harry"] [:something "someValue"]]))

both gets command line params into the map cmdArgs and/or creates
entries with default values. What is does NOT do is validate the
parameters.
--~--~-~--~~~---~--~~
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 timc

Thanks David.

On Mar 9, 4:22 pm, David Nolen  wrote:
> The first regex is returning an empty list not nil.
> David
>
> On Mon, Mar 9, 2009 at 11:48 AM, timc  wrote:
>
> > Can someone please see what's wrong with this.
>
> > (defn getArg [arg]
> >        "Return a [keyword value] depending on the form of the string arg:
> >        1. arg is of the form +x ==> [:x true].
> >        2. arg is of the form -x ==> [:x false].
> >        3. arg is of the form x=v ==> [:x v].
> >        4. else ==> [:files arg]."
> >        (let [x (or
> >                   (re-seq #"([+])([a-zA-Z_0-9]+)" arg)
> >                   (re-seq #"([-])([a-zA-Z_0-9]+)" arg)
> >                   (re-seq #"([a-zA-Z_0-9]+)=([^ ]+)" arg))]
> >                (if (nil? x) [:files arg]
> >                        (let [x (first x)
> >                                y (nth x 1)
> >                                z (nth x 2)]
> >                                (cond
> >                                        (= y "+")       [(keyword z) true]
> >                                        (= y "-")       [(keyword z) false]
> >                                        :else           [(keyword y) z])
>
> > This is part of a command-line-arg processing function. I want to end
> > up with a map containing things like this:
>
> > {:verbose true :fast false :configFile "/tom/dick" :files ["foo" "bar"
> > "zot"]}
>
> > as a result of processing the command line args:
>
> > +verbose -fast configFile=/tom/dick foo bar zot
>
> > Now...
>
> > (getArg "+foo") correctly returns [:foo true]
>
> > however
>
> > (getArg "-foo") throws a NullPointerException.
>
> > Am I wrong in my understanding of the or function? That is, that (or a
> > b c) should return the first of a,b,c that returns true (i.e. non-nil)
> > or nil if they are all nil?
>
> > Or is something happening to the function 'arg' inside the let?
>
> > Thanks in advance.
>
> > ---
> > In case it's interesting to anyone, the other part of this (that calls
> > getArg) is the following.
>
> > (defn getArgs [args & xs]
> >        "This processes args (a seq of strings) and returns a map.
> >        The parameter xs is a seq of two-element vectors: [keyword value].
> >        The returned map contains (keyword,value) pairs produced by
> > processing the args, as follows.
> >        1. An arg of the form +x creates the pair (:x true).
> >        2. An arg of the form -x creates the pair (:x false).
> >        3. An arg of the form x=v creates the pair (:x v), where v is a
> > string.
> >        4. Any other args will be placed in the pair (:files
> > vectorOfStrings).
> >        5. Any [x v] in xs, not found in the args, will create the pair (:x
> > v)."
> >        (let [res {:files []}]
> >                ; First process the args (if any).
> >                (when args (doall (for [arg args]
> >                        (let [ga (getArg arg) [key val] ga]
> >                                (cond
> >                                        (= key :files) (conj (:files res)
> > val)
> >                                        :else          (conj res ga))
> >                ; Now process the xs (if any).
> >                (when xs (doall (for [x xs]
> >                        (let [key (first x)]
> >                                (when (not (key res)) (conj res x))
> >                res))
>
> > so that (for example)
>
> > (def cmdArgs (getArgs *command-line-args* [[:verbose false] [:fast
> > true] [:configFile "/tom/harry"] [:something "someValue"]]))
>
> > both gets command line params into the map cmdArgs and/or creates
> > entries with default values. What is does NOT do is validate the
> > parameters.
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



Problem with SwingWorker and proxy-super

2009-03-19 Thread timc

I am trying to understand how to use SwingWorker to do time-consuming
work that needs to update a Swing GUI. The following makes a frame
with a button (which starts a SwingWorker on the first click).

Thereafter, clicking the button increments an integer n that is
displayed in the first JTextField (Event Dispatch thread).

Meanwhile the worker thread running the method doInBackground()
increments an integer m and sleeps for 2s. On each increment it calls
publish(m) which is supposed to run in the Event Dispatch thread and
show the current value of m in the second JTextField. When it has done
this ten times, the exit from doInBackground() causes the done()
method to be called (in the Event Displatch thread), which sets the
checkbox.

However the code (proxy-super publish m) throws this exception:

#


Can anyone tell me what I am doing wrong?


(import
'(javax.swing JFrame JPanel JButton JTextField JCheckBox SwingWorker)
'(java.awt FlowLayout)
'(java.awt.event ActionListener)
)

(def startIt (atom true))
(def n (atom 0))
(def tf1 (doto (JTextField. 5) (. setEditable false)))
(def tf2 (doto (JTextField. 5) (. setEditable false)))
(def cb (JCheckBox.))

(def worker
(proxy [SwingWorker] []
(doInBackground []
(try
(loop [m 0]
(prn (str "doInBackground1: m=" m))
(proxy-super publish m)
(Thread/sleep 2000)
(if (< m 10)
(recur (inc m))
(prn (str "doInBackground2: m=" m
(catch Exception e (prn e
(process [val]
(prn (str "process: val=" val))
(. tf2 (setText (str val
(done []
(prn (str "done"))
(. cb (setSelected true)

(def buttonAction
(proxy [ActionListener] []
(actionPerformed [e]
(when @startIt (. worker execute) (swap! startIt not))
(dosync (swap! n inc))
(. tf1 (setText (str @n))

(def button
(doto (JButton. "Press me") (. addActionListener buttonAction)))

(def frame
(doto   (JFrame. "SwingWorker test")
(.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE)
(. add
(doto (JPanel. (FlowLayout.))
(. add button)
(. add tf1)
(. add tf2)
(. add cb)))
(. pack)
(. setVisible true)))

--~--~-~--~~~---~--~~
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: Problem with SwingWorker and proxy-super

2009-03-19 Thread timc

It would be a great pity if there was no way to do this, as
SwingWorker is the 'proper' way for long-running code to interact with
Swing objects.
Any ideas for how to achieve this would be appreciated.


On Mar 19, 7:35 pm, MikeM  wrote:
> > However the code (proxy-superpublish m) throws this exception:
>
> > # > matching method found: publish for class
> > clojure.proxy.javax.swing.SwingWorker>
>
> publish is a protected method, and I don't think proxy (even withproxy-super) 
> lets you access it. Also, even if it was public, it is a
> var-arg method, so you would need to supply an array.
--~--~-~--~~~---~--~~
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: Problem with SwingWorker and proxy-super

2009-03-23 Thread timc

Thanks for that Tim - perfect.

On Mar 19, 11:49 pm, Timothy Pratley  wrote:
> http://clojure.org/java_interop
> "Note that while method fns can be provided to override protected
> methods, they have no other access to protected members, nor to super,
> as these capabilities cannot be proxied."
>
> However this solution might be adequate:
>
>         (proxy [SwingWorker] []
>                 (doInBackground []
>                         (try
>                         (loop [m 0]
>                                 (prn (str "doInBackground1: m=" m))
>                                 (javax.swing.SwingUtilities/invokeLater
>                                   (fn []
>                                     (prn (str "process: val=" m))
>                                     (. tf2 (setText (str m)
>                                 (Thread/sleep 2000)
>                                 (if (< m 10)
>                                         (recur (inc m))
>                                         (prn (str "doInBackground2:
> m=" m
>                                 (catch Exception e (prn e
>                 (done []
>                         (prn (str "done"))
>                         (. cb (setSelected true)))))
>
> ie: don't use the publish/process part but instead put updates on the
> Event Thread explicitly.
>
> On Mar 20, 5:56 am, timc  wrote:
>
> > I am trying to understand how to use SwingWorker to do time-consuming
> > work that needs to update a Swing GUI. The following makes a frame
> > with a button (which starts a SwingWorker on the first click).
>
> > Thereafter, clicking the button increments an integer n that is
> > displayed in the first JTextField (Event Dispatch thread).
>
> > Meanwhile the worker thread running the method doInBackground()
> > increments an integer m and sleeps for 2s. On each increment it calls
> > publish(m) which is supposed to run in the Event Dispatch thread and
> > show the current value of m in the second JTextField. When it has done
> > this ten times, the exit from doInBackground() causes the done()
> > method to be called (in the Event Displatch thread), which sets the
> > checkbox.
>
> > However the code (proxy-super publish m) throws this exception:
>
> > # > matching method found: publish for class
> > clojure.proxy.javax.swing.SwingWorker>
>
> > Can anyone tell me what I am doing wrong?
>
> > (import
> >         '(javax.swing JFrame JPanel JButton JTextField JCheckBox 
> > SwingWorker)
> >         '(java.awt FlowLayout)
> >         '(java.awt.event ActionListener)
> > )
>
> > (def startIt (atom true))
> > (def n (atom 0))
> > (def tf1 (doto (JTextField. 5) (. setEditable false)))
> > (def tf2 (doto (JTextField. 5) (. setEditable false)))
> > (def cb (JCheckBox.))
>
> > (def worker
> >         (proxy [SwingWorker] []
> >                 (doInBackground []
> >                         (try
> >                         (loop [m 0]
> >                                 (prn (str "doInBackground1: m=" m))
> >                                 (proxy-super publish m)
> >                                 (Thread/sleep 2000)
> >                                 (if (< m 10)
> >                                         (recur (inc m))
> >                                         (prn (str "doInBackground2: m=" 
> > m
> >                                 (catch Exception e (prn e
> >                 (process [val]
> >                         (prn (str "process: val=" val))
> >                         (. tf2 (setText (str val
> >                 (done []
> >                         (prn (str "done"))
> >                         (. cb (setSelected true)
>
> > (def buttonAction
> >         (proxy [ActionListener] []
> >                 (actionPerformed [e]
> >                         (when @startIt (. worker execute) (swap! startIt 
> > not))
> >                         (dosync (swap! n inc))
> >                         (. tf1 (setText (str @n))
>
> > (def button
> >         (doto (JButton. "Press me") (. addActionListener buttonAction)))
>
> > (def frame
> >         (doto   (JFrame. "SwingWorker test")
> >                 (.setDefaultCloseOperation JFrame/DISPOSE_ON_CLOSE)
> >                 (. add
> >                         (doto (JPanel. (FlowLayout.))
> >                                 (. add button)
> >                                 (. add tf1)
> >                                 (. add tf2)
> >                                 (. add cb)))
> >                 (. pack)
> >                 (. setVisible true)))
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



How to call function (or Java method) using string name?

2009-04-26 Thread timc

Is there a way of invoking functions, or java methods "by name" in
Clojure?
Or, put another way, why does this work:

(+ 1 2)

but this does not:

((symbol "+") 1 2)

Similarly, this works

(. javaObj (methodName param))

but this does not:

(. javaObj ((symbol "methodName") param))


I suppose this really comes down to the question: what is a symbol?
And, is the thing at the head of the list (+ 1 2 3) a symbol?

[In Icon, for example, there is no difference between

"funcName"(1,2,3) and funcName(1,2,3), or indeed:

x := "funcName"
x(1,2,3)

which is VERY useful.]

--~--~-~--~~~---~--~~
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: How to call function (or Java method) using string name?

2009-04-26 Thread timc

Thanks Stuart.

I have figured out another way, which is much more general (and uses
the lowest level of how Clojure works).

(defn evalStr [s] (clojure.lang.Compiler/eval (clojure.lang.RT/
readString s)))

will (attempt to) execute any valid form (i.e. the string that is the
source of the form).

Thus: (evalStr "(+ 1 2)") --> 3

On Apr 26, 5:21 pm, Stuart Sierra  wrote:
> This will work:
> ((resolve (symbol "+")) 1 2 3)
>
> To answer your question, a symbol is just a symbol, it doesn't have a
> value.  (In Common Lisp, symbols have values, but in Clojure they do
> not.)  In Clojure, values belong to Vars.  "resolve" will find the Var
> that is named by the symbol.  When you write (+ 1 2 3), the compiler
> automatically resolves the "+" to get the Var #'clojure.core/+
>
> To invoke Java methods by name, use the Java Reflection 
> API:http://java.sun.com/docs/books/tutorial/reflect/index.html
>
> -Stuart Sierra
>
> On Apr 26, 10:46 am, timc  wrote:
>
> > Is there a way of invoking functions, or java methods "by name" in
> > Clojure?
> > Or, put another way, why does this work:
>
> > (+ 1 2)
>
> > but this does not:
>
> > ((symbol "+") 1 2)
>
> > Similarly, this works
>
> > (. javaObj (methodName param))
>
> > but this does not:
>
> > (. javaObj ((symbol "methodName") param))
>
> > I suppose this really comes down to the question: what is a symbol?
> > And, is the thing at the head of the list (+ 1 2 3) a symbol?
>
> > [In Icon, for example, there is no difference between
>
> > "funcName"(1,2,3) and funcName(1,2,3), or indeed:
>
> > x := "funcName"
> > x(1,2,3)
>
> > which is VERY useful.]
--~--~-~--~~~---~--~~
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: How to call function (or Java method) using string name?

2009-04-27 Thread timc

Thanks again!

On Apr 27, 6:41 pm, Richard Lyman  wrote:
> There's a section on the wiki with almost the exact same title:
>
> http://en.wikibooks.org/wiki/Clojure_Programming/Examples#Invoking_Ja...
>
> If I'm understanding the question correctly that should do what you're
> wanting to do.
>
> -Rich
>
> On Sun, Apr 26, 2009 at 11:50 AM, timc  wrote:
>
> > Thanks Stuart.
>
> > I have figured out another way, which is much more general (and uses
> > the lowest level of how Clojure works).
>
> > (defn evalStr [s] (clojure.lang.Compiler/eval (clojure.lang.RT/
> > readString s)))
>
> > will (attempt to) execute any valid form (i.e. the string that is the
> > source of the form).
>
> > Thus: (evalStr "(+ 1 2)") --> 3
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



Syntax for proxy methods?

2009-10-01 Thread timc

Can someone please advise me if this is possible:


//  --- IX.java ---
interface IX
{
  void doit();
  void doit(int n);
}

; --- x.clj ---

(def prx (proxy [IX][]
  (doit
([] (doseq [x someSeq] (doit x))
([y] (print y

When I tried something of this form, it looks like the call of the 1-
arg function from the 0-arg function can't be resolved.

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



Re: Syntax for proxy methods?

2009-10-01 Thread timc

No, its a proxy for an interface.

On Oct 1, 7:22 pm, Jarkko Oranen  wrote:
> On Oct 1, 9:18 pm, timc  wrote:
> 
>
> > (def prx (proxy [IX][]
> >   (doit
> >     ([] (doseq [x someSeq] (doit x))
> >     ([y] (print y
>
> > When I tried something of this form, it looks like the call of the 1-
> > arg function from the 0-arg function can't be resolved.
>
> > Thanks in advance
>
> I'm not certain, but since it's a java method, shouldn't you call it
> like (.doit this x)?
--~--~-~--~~~---~--~~
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: Syntax for proxy methods?

2009-10-01 Thread timc

Oops, I spoke too hastily -- thank you Jarkko.

On Oct 1, 8:38 pm, timc  wrote:
> No, its a proxy for an interface.
>
> On Oct 1, 7:22 pm, Jarkko Oranen  wrote:
>
> > On Oct 1, 9:18 pm, timc  wrote:
> > 
>
> > > (def prx (proxy [IX][]
> > >   (doit
> > >     ([] (doseq [x someSeq] (doit x))
> > >     ([y] (print y
>
> > > When I tried something of this form, it looks like the call of the 1-
> > > arg function from the 0-arg function can't be resolved.
>
> > > Thanks in advance
>
> > I'm not certain, but since it's a java method, shouldn't you call it
> > like (.doit this x)?
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



How to make lazy seq from socket input?

2009-10-30 Thread timc

Can someone suggest how to make the packets received on a socket into
a lazy sequence?
The application I'm making is a log file parser. A (Java) program is
producing log output using log4j, the output can go to file(s) or be
sent to a socket. So, the program has this outline:

(defn fileLines [fileNameSeq]
"Return a lazy sequence of lines from the given lazy sequence of file
names.
Return nil at end of file." ...)

(defn socketLines [ipAddr portN]
"Return a lazy sequence of lines from a server socket at the given
place.
Return nil if socket error." ...)

(defn parseLine [line] ... )

(defn parseLines [lineSeq]
"Parse the lines from lineSeq."
(loop [line (first lineSeq) tail (rest lineSeq)]
(when line
(parseLine line)
(recur (first tail) (rest tail)

I think I know how to do fileLines, but not socketLines. (Each
received packet should contain one line as it would have been written
to a file, I think). My problem is not how to manage a server socket,
but how to make an ISeq -- i.e. what exactly is the contract that ISeq
defines (the source code has no comments).

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



Re: How to make lazy seq from socket input?

2009-10-30 Thread timc

Thanks for the help.

On Oct 30, 1:23 pm, Meikel Brandmeyer  wrote:
> Hi,
>
> if you have a stream, you can basically do:
>
> (defn stream-seq
>   [stream]
>   (take-while #(<= 0 %) (repeatedly #(.read stream
>
> This will give a character at a time. From there you can build the
> lines and turn it into a seq of lines. Or can you can to the lower
> level and use lazy-seq directly.
>
> (defn stream-line-seq
>   [stream]
>   (lazy-seq
>     (loop [line []]
>       (let [ch (.read stream)]
>         (cond
>           (= \newline ch) (cons (apply str line) (stream-line-seq
> stream))
>           (<= 0 ch) (recur (conj line ch))
>           :else (when (< 0 (count line)) (cons (apply str line)
> nil)))
>
> Probably not the best implementation, but well... Of course lines is
> only an example. This can be used for any type of record.
>
> Beware of laziness in combination with resources like streams!
> (premature close etc.)
>
> Hope this helps.
>
> 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
-~--~~~~--~~--~--~---



Hints on how to 'nest' lazy sequences

2010-01-28 Thread timc
Can anyone please advise on how to structure a sort of 'nested lazy
sequence' in this sense:

Given a collection (say*command-line-args*) of file names, how to make
a lazy function that in effect does what clojure.contrib.duck-streams/
read-lines does, but of all the files in sequence.

Thanks

-- 
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: Hints on how to 'nest' lazy sequences

2010-01-28 Thread timc
Thanks Michal -- however, (multi-read-lines *command-line-args*)
produces this exception:

 java.lang.IllegalArgumentException: Mismatched argument count to
recur, expected: 0 args, got: 1


On Jan 28, 12:54 pm, Michał Marczyk  wrote:
> On 28 January 2010 13:41, timc  wrote:
>
> > Given a collection (say*command-line-args*) of file names, how to make
> > a lazy function that in effect does what clojure.contrib.duck-streams/
> > read-lines does, but of all the files in sequence.
>
> How about this:
>
> (defn multi-read-lines [sources]
>   (when-let [source (first sources)]
>     (lazy-cat (read-lines source) (recur (rest sources)
>
> It would be easy enough to have it accept a variable number of sources
> as arguments rather than a single list, if you prefer.
>
> Sincerely,
> Michal

-- 
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: Hints on how to 'nest' lazy sequences

2010-01-28 Thread timc
Michal

The last, elegant one works -- marvellous!

Thanks a lot.
Tim

On Jan 28, 1:05 pm, Michał Marczyk  wrote:
> Ouch, sorry, this won't work with recur... Use an explicit call instead:
>
> (defn multi-read-lines [sources]
>   (when-let [source (first sources)]
>    (lazy-cat (read-lines source) (multi-read-lines (rest sources)
>
> I guess this would overflow the stack with a huge number of sources, though.
>
> A second solution which should hopefully be fully lazy (and seems more
> elegant anyway):
>
> (defn multi-read-lines [sources]
>   (reduce (fn [acc s]
>                   (lazy-cat acc (read-lines s)))
>                 nil
>                 sources))
>
> Sincerely,
> Michal

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


What is EvalReader?

2010-02-19 Thread timc
The API documentation refers to EvalReader:

Quote
*read-eval* - var - When set to logical false, the EvalReader
(#=(...)) is disabled in the
read/load in the thread-local binding.
Unquote

Is #= an undocumented reader macro character?

And what is the EvalReader anyway? It doesn't appeared to be defined
anywhere.


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


Compile works with 1.1, fails with 1.2.0-RC3

2010-08-19 Thread timc
I'm trying to compile a program, with source files as follows.

com/minibar/PmsSimulator.clj -- containing these lines:

(ns com.minibar.PmsSimulator
  (:require  [com.minibar :as mb] ...etc)
  (:load  "pmssim/util"  ...etc)
  (:gen-class))
...etc

where the file com/minibar/pmssim/util.clj contains these lines:

(ns com.minibar.PmsSimulator
  (:require  [com.minibar :as mb]))
...
  (mb/getProgArg ":foobar")
...etc

The com.minibar namespace is a separately compiled library (getProgArg
gets program args by keyword). This library compiles fine with 1.2.0-
RC3.

I am using Ant to do this, with a task like this:





...etc





The above compiles fine with Clojure 1.1, but fails to compile with
1.2.0-RC3, with this exception:

 [java] Compiling com.minibar.PmsSimulator to classes
 [java] java.lang.Exception: No such var: mb/getProgArg (util.clj:
85)

I happen to be doing all this with Eclipse CCW, but that's irrelevant
I think.

Has anyone else seen anything like this?

Regards, Tim

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


Help: how to construct lazy sequences

2011-05-19 Thread timc
Hello
I wonder if I could ask for advice on how to construct a lazy sequence. My 
application might be of interest to some of you.

The context for this is that I have an embedded system with very limited 
facilities for proper debugging.
I have inserted a 'trace' facility in the embedded code that is able to emit 
binary bytes that I can capture over a serial comm channel.
So, what I get is a stream of bytes that is a sort of mini-language.

For example, I might get the values as in this seq:

  (def bSeq [1 20 30 4 1 7 8 5 60 5 70])

where the 'sentences' of this language are as follows:

1 a b (that is, a 1 is followed by two values),
4 (that is, a 4 is on its own)
5 x (that is, a 5 is followed by one value),  and so on.

Now, examining this stream of values is tedious to say the least, so I want 
to parse it and print meaningful versions of the sentences (after all, I 
know what they really mean :).
So, I construct a set of specifications for the sentences, like this:

(defstruct Spec :nArgs :fmt)

(def specs {
1 (struct Spec 2 "[1] a=%d b=%d\n")
4 (struct Spec 0 "[4]\n")
5 (struct Spec 1 "[5] z=%d\n")
})

The map of Specs is keyed by the value that starts the sentence.
The Spec itself comprises :nArgs (how many values follow)
and :fmt (a string for the format function, expecting :nArgs values, which 
will render the sentence in a useful way).

I want to do the parsing of the byte sequence as follows, using the magic of 
reduce:

(reduce parser {} bSeq)

where the parser function is this:

  (defn parser [m a]
(if (empty? m)
  (if-let [spec (specs a)]
(if (zero? (spec :nArgs))
  (do
(print (format (spec :fmt)))
{})
  {:spec spec :args []})
(throw (Error. (format "Input %d has no format spec" a
  (let [newArgs (conj (m :args) a)]
(if (= ((m :spec) :nArgs) (count newArgs))
  (do
(print (apply format ((m :spec) :fmt) newArgs))
{})
  (assoc m :args newArgs)

To explain a bit: the args to parser are m, a map with keys:
  :spec -- the spec of the sentence that is currently being parsed
  :args -- a vector of the args to this sentence
or the empty map if the next thing expected is the start value of a 
sentence;
and a the next value in the sequence.

Lo and behold, this produces formatted output like this:

[1] a=20 b=30
[4]
[1] a=7 b=8
[5] z=60
[5] z=70

So far so good, but here comes the real question of this post.
The data arrives from the serial port in variable sized byte arrays at 
unpredictable moments in time; these are placed in a queue, like this:

(def inputQ (java.util.concurrent.LinkedBlockingQueue.))
(defn inputArrives [byteArray] (.put inputQ byteArray))

It is of course very easy to read the things out of the queue by means of 
(.take inputQ), and then read the bytes one-by-one; of course this may block 
waiting for more inputs.

So - how do I make a function that returns a lazy sequence that internally 
is getting the byte arrays off this queue and feeding the bytes contained 
therein to the caller of the lazy sequence - one byte at a time?

And - a similar question (easier to answer I imagine) how do I construct a 
lazy sequence from the bytes read from a file (possibly with some 
translation between reading the raw bytes from the file and handing them 
over to the caller of the lazy sequence)?

Of course, I could (and have) implemented all the above in a much more 
procedural kind of way, but it is so much more elegant (and easier to 
understand) with a lazy sequence :)

Looking forward to some remarkable, simple solutions :)

Regards, Tim

PS Thinking about this makes me wonder about the existence, or non-existence 
of a 'super-reduce' function that could do context-free grammar parsing.
Is such a thing possible? Is there-such a thing as a lazy back-trackable 
sequence? Now that I've asked - I'm not even sure what that means :))

-- 
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: Help: how to construct lazy sequences

2011-05-19 Thread timc
That was very helpful - thanks Meikel and Jonathon.

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

Macros to help writing closures?

2012-04-21 Thread timc
Hello

I am a beginner when it comes to writing macros, so there may be an easy 
way to do this.
I have a number of 'state machines' which have this sort of appearance:

(defn startFSM [eventQ]
  (let [state (atom :1)
 going (atom true)
 timerId (atom -1)
 startTimer (fn [] )
 stopTimer (fn [] ...)]
   (inThread
 (while @going
   (let [ev (.take eventQ)]
   (condp = @state
 :1 ()
 :2 (...)
 etc...))

where inThread runs its body in a thread, and the timer functions deal with 
timers. So, when (startFSM aQ) is called, the thread runs and processes 
events arriving on aQ.

My question is, how to write a macro, fsmWithTimers, that could be used 
like this:

(fsmWithTimers
   (condp = @state
 :1 ()
 :2 (...)
 etc...))

which would resolve into the form shown above, so that the items mentioned 
in the outer let are usable (via the names specified) within the body (in 
the example a condp form)?


-- 
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: Macros to help writing closures?

2012-04-22 Thread timc
Thanks Cedric - that's very nice.
I'm beginning to understand the power of macros. I have to say they are not 
very well explained in the clojure docs.
In particular, how many distinct 'macro operators' are there, and what are 
their precise definitions?
For instance, is ~' a single operator, or is it two ' and ~; in either case 
exactly what is/are it/they doing?
Most of the explanations of this stuff do it by example, which is all very 
well but... "it works in practice but not in theory" as some wag once said 
about elementary particle physics. 

-- 
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: Macros to help writing closures?

2012-04-22 Thread timc
I often write functions like this:

(defn foobar []
  (let [log (makeLogger "foobar")]
 blah blah ))

where makeLogger returns a logging function that prefixes all messages with 
the name provided.

It looks as though macros don't have a "stringize" ability (like the C 
preprocessor) so that this would work:

(defmacro foo [fname & body]
  `(defn ~fname []
 (let [~'log (~'makeLogger "~fname")]
   ~@body)))

When this is expanded, the string comes out as-is: "~fname".
Is there some way to do this?

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

How to emulate Java sub-classing using closure with a macro?

2012-11-18 Thread timc
Hello - I would appreciate some advice on how to implement something 
equivalent to sub-classing.

The context for this is a finite state machine (FSM), by which I mean a 
thread that waits on a queue of events, then deals with each event (one at 
a time) according to the state it is in, possibly changing state in the 
process.

In Java, an (abstract) super class might be defined for all FSMs, which 
contains common fields such as the current state, timer ID, event queue, 
etc, together with methods for getting and setting the state, starting and 
stopping timers, handling timeouts (this inserts a timeout event into the 
event queue), putting an event into the queue and waiting on the next event 
in the queue. The method to insert an event is generally public so that 
other objects may insert events.

Then, a particular FSM is written as a sub-class; this comprises code to 
execute before the first event is waited for, a loop which waits for then 
processes each event, then code that is executed when the FSM is exited for 
the last time.
The code that implements all the above naturally makes use of the 
super-class methods and fields, since they are within the scope of the 
sub-class.

It is easy enough to implement all the above as closure of the form

  (defn fsm []
"Start a thread that is a finite state machine.
 Return [putEventF stopF] where putEventF[ev] is a function that adds 
an event to the event queue,
 and stopF[] is a function that stops the state machine.
 Events are vectors of the form [kind & data]." 
(let [eventQ (java.util.concurrent.LinkedBlockingQueue.)
  putEventF (fn [ev] (.put eventQ ev))
  stopF (fn [] (putEventF [:stop]))
  state (atom nil)
  going (atom true)
  timerID (atom nil)
  timerExpired (fn [id data]
 (when (and @timerID (= id timerID))
   (.put eventQ [:timeout data]))) 
  stopTimer (fn []
  (when @timerID
(extStopTimer @timerID)
(reset! timerID nil))) 
  startTimer (fn [period data]
   (stopTimer)
   (reset! timerID (extStartTimer period timerExpired 
data)))
  nextState #(reset! state %)]
  (inThread
(do
  (nextState :init)
  ; Starting stuff ...
  (print "started"))
(while @going
  (let [[kind & data :as ev] (.get eventQ)]
(cond = @state
  :init (do
  ; Initialization stuff ...
  ) 
  :state1 (do
; state 1 stuff ...
)
  :state2 (do
; state 2 stuff ...
)
  ; etc...
  :stop (do
  ; Stopping stuff ...
  (reset! going false)) 
  (error "bad state"
(do
  ; Exit stuff ...
  (print "terminated")))
  [putEventF stopF]))

where extFunction... are externally defined functions (implementing timers 
etc) and inThread is a macro that executes a form in a newly created thread.
Within the body of the FSM, the code can of course directly refer to all 
the things defined in the let by name.

The problem is that I have numerous FSMs and it's really tedious to repeat 
all the stuff in the initial let of the closure.

One solution is to define a *context* that contains the values defined in 
the closure (as a map with keys instead of the explicit names shown above), 
created by a context factory function.
Then the code has to refer to all the things via a lookup in the context 
map - quite ugly and also tedious.

Another option is that the context factory creates a closure, then returns 
a vector of all the functions defined in the let binding, which can then be 
used directly by the FSM code - that's even more ugly and error prone.

So - the question is - what about an anaphoric macro that creates the 
closure, so that the FSM code can still refer to all that stuff by name?
If this is the way to go, please an example of the syntax (say the 
timerExpired function). The macro syntax really is confusing to me :(

Or, I imagine a macro called myFsmMacro that takes a map as parameter and 
has the same effect as the fsm function above, something like this:

(def myFsmDefinition  {
   :preamble (do
   (nextState :init)
   (print "started"))
   :states {:init (do
(initData 1 2 3) 
(putEvent :dummy)
(nextState :state1)) 
:state1 (do
  (startTimer 10)
  (nextState :state2))
:state2 (condp = kind
  :timeout ;
  )
 all the other states
:stop (d

Help with zetta-parser please

2012-12-09 Thread timc
Hi

Can someone give example of parsing using zetta-parser for the case that 
the input stream is intermittent (i.e. possibly incomplete at a particular 
moment).
The author of zetta-parser refers to this very possibility in his readme 
(for example parsing messages arriving at a socket or such).

My particular application is interacting with several command line programs 
in MS Windows.
So I need to parse the characters coming from the program's output streams 
(stdout and stderr).
The interaction really is interactive, so for example, when I start the CL 
program, I might get a lot of lines of output followed by a prompt 
"TypeNow>" kind of thing.
So I want the parser to skip the lines and return when it sees the prompt.
Now I might send a character or string to the CL program's stdin and then 
get more (differently structured) output to parse.
And so on.
I cannot change these CL programs because they are provided by third 
parties; they were written with a view to interacting with a human, not a 
program.

It seems to me that this kind of parser is perfect for this job - but I'm a 
newbie at monads etc so I don't know how to express it in zetta-parser 
syntax. (I'm also not familiar with Haskell).

BTW The Win32 treatment of the streams associated with a command line 
program is completely broken, in the sense that the stdout stream is 
*buffered*, so as it stands it is not possible to interact like this with a 
console program. You don't get to see the buffered output until either the 
buffer fills up, or the program terminates. Either way, it's not 
interaction.
This of course also carries over the Java version using 
java.lang.RunTime.exec. If one tries to run an interactive program by this 
means, it just hangs up. In order to achieve interactivity I have had to 
create a truly horrible CL program runner written in C (which I start and 
interact with via a JNI interface) that infers the output from stdout and 
stderr by continually examining the console output buffer (i.e. the screen).

Best regards, Tim

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

Handling of unsigned bytes

2011-02-11 Thread timc
How on earth is one supposed to do communication programming (not to
mention handling binary files etc) without an unsigned byte type?

I see that this issue has been talked about vaguely - is there a
solution?

Thanks

-- 
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: Handling of unsigned bytes

2011-02-12 Thread timc
Sorry I did not make myself clear - I thought it was obvious given the
previous postings on this subject.
This java program:

public class TestByte {
public static void main(String[] args)
{
int i = 0x123456ab;
byte[] b = new byte[1];
b[0] = (byte) i;
showInt("i",i);
showByte("b[0]",b[0]);
}

private static void showInt(String s, int x)
{
System.out.println(String.format("%s=%d(0x%08x 0x%02x)", s, x, 
x,
x));
}

private static void showByte(String s, byte x)
{
System.out.println(String.format("%s=%d(0x%08x 0x%02x)", s, x, 
x,
x));
}
}

compiles and runs, producing this output:

i=305419947(0x123456ab 0x123456ab)
b[0]=-85(0x00ab 0xab)

But, this bit of clojure:

(defn show [s x] (println (format "%s=%d(0x%08x 0x%02x)" s, x, x, x)))
(def i 0x123456ab)
(def b (byte-array 1))
(aset-byte b 0 (byte i))
(show "i" i)
(show "b[0]" (aget b 0))

throws this exception:
java.lang.IllegalArgumentException: Value out of range for byte:
305419947

Shouldn't these two programs be equivalent?
Presumably they are not because the effect of

int i = (byte) b;

is NOT the same as

(def i (byte b))

-- but surely it should be the same?


On Feb 11, 5:24 pm, Andy Fingerhut  wrote:
> What can you not do with the signed byte type and arrays of bytes  
> (Java byte[] and Clojure (byte-array ...))?
>
> I believe these are frequently used for Java I/O, and can be used for  
> Clojure I/O as well.
>
> Andy
>
> On Feb 11, 2011, at 9:22 AM, timc wrote:
>
> > How on earth is one supposed to do communication programming (not to
> > mention handling binary files etc) without an unsigned byte type?
>
> > I see that this issue has been talked about vaguely - is there a
> > solution?
>
> > Thanks
>
> > --
> > 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: Handling of unsigned bytes

2011-02-12 Thread timc
Further investigation reveals that

(def b (byte i))

is doing something equivalent to this internally:

byte b = Byte.parseByte(String.format("%d",i));

which does indeed throw a NumberFormatException if the decimal integer
representation given to it produces an out-of-range value (as it
should).

So - what I'm pleading for, is that (byte b) and (int i), (short s),
etc. should simply perform a masking operation (on the appropriate
number of least significant bits) in the way that java clearly does.


On Feb 12, 1:08 pm, timc  wrote:
> Sorry I did not make myself clear - I thought it was obvious given the
> previous postings on this subject.
> This java program:
>
> public class TestByte {
>         public static void main(String[] args)
>         {
>                 int i = 0x123456ab;
>                 byte[] b = new byte[1];
>                 b[0] = (byte) i;
>                 showInt("i",i);
>                 showByte("b[0]",b[0]);
>         }
>
>         private static void showInt(String s, int x)
>         {
>                 System.out.println(String.format("%s=%d(0x%08x 0x%02x)", s, 
> x, x,
> x));
>         }
>
>         private static void showByte(String s, byte x)
>         {
>                 System.out.println(String.format("%s=%d(0x%08x 0x%02x)", s, 
> x, x,
> x));
>         }
>
> }
>
> compiles and runs, producing this output:
>
> i=305419947(0x123456ab 0x123456ab)
> b[0]=-85(0x00ab 0xab)
>
> But, this bit of clojure:
>
> (defn show [s x] (println (format "%s=%d(0x%08x 0x%02x)" s, x, x, x)))
> (def i 0x123456ab)
> (def b (byte-array 1))
> (aset-byte b 0 (byte i))
> (show "i" i)
> (show "b[0]" (aget b 0))
>
> throws this exception:
> java.lang.IllegalArgumentException: Value out of range for byte:
> 305419947
>
> Shouldn't these two programs be equivalent?
> Presumably they are not because the effect of
>
> int i = (byte) b;
>
> is NOT the same as
>
> (def i (byte b))
>
> -- but surely it should be the same?
>
> On Feb 11, 5:24 pm, Andy Fingerhut  wrote:
>
> > What can you not do with the signed byte type and arrays of bytes  
> > (Java byte[] and Clojure (byte-array ...))?
>
> > I believe these are frequently used for Java I/O, and can be used for  
> > Clojure I/O as well.
>
> > Andy
>
> > On Feb 11, 2011, at 9:22 AM, timc wrote:
>
> > > How on earth is one supposed to do communication programming (not to
> > > mention handling binary files etc) without an unsigned byte type?
>
> > > I see that this issue has been talked about vaguely - is there a
> > > solution?
>
> > > Thanks
>
> > > --
> > > 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: Handling of unsigned bytes

2011-02-12 Thread timc
Thanks for the help. Sorry I got agitated about this - it was just
that my code (that was doing lots of byte handling) worked with a
previous version of clojure and then stopped working.
Thanks Ken, I shall use your little workaround.

On Feb 12, 10:04 pm, Ken Wesson  wrote:
> On Sat, Feb 12, 2011 at 4:54 PM, Aaron Cohen  wrote:
> > On Sat, Feb 12, 2011 at 4:42 PM, Ken Wesson  wrote:
> >> On Sat, Feb 12, 2011 at 8:28 AM, timc  wrote:
> >>> (def b (byte i))
>
> >>> is doing something equivalent to this internally:
>
> >>> byte b = Byte.parseByte(String.format("%d",i));
>
> >> What the HELL?
>
> >> That's incredibly icky and inefficient. :)
>
> > Don't worry, it's not actually doing that:
> >https://github.com/clojure/clojure/blob/f128af9d36dfcb268b6e9ea63676c...
>
> Oh, good. That's basically what I said it should do.

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