Re: [ANN] Envvar 1.1.0 — a library for handling environment variables

2014-08-14 Thread Constantine Vetoshev
On Thursday, August 14, 2014 6:46:56 AM UTC-7, James Reeves wrote:

 You can do this with Environ. Leiningen checks for a profiles.clj in your 
 project directory, as well as then one in $HOME/.lein. If you add 
 profiles.clj to your .gitignore file, you can use it for local overrides 
 during development and testing.


Please update the Environ README to include this suggestion. The current 
text explicitly suggests setting variables in ~/.lein/profiles.clj, and I 
did not notice the reference to project-specific profiles.clj files buried 
deeply in Leiningen documentation.

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


Re: [ANN] Envvar 1.1.0 — a library for handling environment variables

2014-08-14 Thread Constantine Vetoshev
On Thursday, August 14, 2014 2:53:30 AM UTC-7, Tony Tam wrote:

 It wasn't really clear to me from the README why use this instead of 
 environ. Care to explain a little more in detail? I.e. give a concrete use 
 case.
 Any particular reason for not supporting .lein-env files?
 Also, if a .env is just a java .properties file, then why use .env files?


The main distinctions from Environ are:

1. Property file .env syntax is the compatible with the one used by shells, 
as well as with the one used by dotenv libraries from Node and Ruby.

2. Loading env files in the REPL, and modifying the environment at runtime 
in general. Environ only handles loading variables when it loads itself, 
and has no provision for modifying them except by restarting the Clojure 
process.

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


[ANN] Envvar 1.1.0 — a library for handling environment variables

2014-08-13 Thread Constantine Vetoshev
The JVM does not make using environment variables easy or convenient. The 
environ https://github.com/weavejester/environ library took a step in the 
right direction by abstracting away the distinction between environment 
variables and Java properties into a Clojure map data structure. However, I 
still found it awkward to use in multi-person projects where each 
programmer wants to set up different environment variable values at 
runtime. I also wanted an easy way to modify the environment in a dynamic 
scope. Hence:

https://github.com/gcv/envvar

Feedback welcome.

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


[ANN] appengine-magic 0.4.6 released

2011-11-07 Thread Constantine Vetoshev
I just released appengine-magic version 0.4.6. appengine-magic is a
library which makes it easy to write Clojure web applications intended
for deployment on Google App Engine.

https://github.com/gcv/appengine-magic/

This version of appengine-magic adds support for Clojure 1.3.0, while
retaining compatibility with 1.2.x.

Other changes: I made an effort to improve support for non-Emacs
interactive environments. So with luck, Clojure modes in popular Java
IDEs might now work. Since I don't use these IDEs, I did not really
test this, but the change I made removed an important reason why they
tended to break.

The datastore now has :before-save and :after-load callback support.

This version of appengine-magic supports App Engine SDK 1.5.5.

Please note that this release does NOT support App Engine SDK 1.6.0,
released earlier today. I tried to use 1.6.0 with appengine-magic, and
it introduced breaking changes to the /_ah/admin console (Google's
servlets started throwing NPEs and fail to load). Unfortunately, I
will not have time over the next few weeks to track down this problem.
If someone sends me a working patch for this, I'll merge it in and
release an update.

Best,
Constantine Vetoshev

-- 
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: Exception handling changes in Clojure 1.3.0

2011-10-09 Thread Constantine Vetoshev
I finally came up with a simple example which shows the broken
exception handling behavior I described in my earlier post on this
thread.

(defn broken-catch [filename]
  (try (java.io.FileReader. filename)
   (catch java.io.FileNotFoundException fnfe
 FileNotFoundException caught)
   (catch RuntimeException ioe
 (str RuntimeException caught; cause: 
  (.getCause ioe)

user= (broken-catch /etc/passwdXYZ)
RuntimeException caught; cause: java.io.FileNotFoundException: /etc/
passwdXYZ (No such file or directory)

The FileReader constructor throws a FileNotFoundException when the
file specified by the argument does not exist:
http://download.oracle.com/javase/6/docs/api/java/io/FileReader.html#FileReader(java.lang.String)
— and as you can see here, Clojure 1.3.0 wrapped it in a
RuntimeException, so the expected typed catch does not work.

However, if invoked in a way which bypasses reflection, the exception
is properly typed:

user= (try (java.io.FileReader. /etc/passwdXYZ)
 (catch java.io.FileNotFoundException fnfe
   FileNotFoundException caught)
 (catch RuntimeException ioe
   (str RuntimeException caught; cause: 
(.getCause ioe
FileNotFoundException caught

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


Exception handling changes in Clojure 1.3.0

2011-10-03 Thread Constantine Vetoshev
I ran into an interesting problem while porting appengine-magic to
Clojure 1.3.0.

The Google App Engine SDK uses checked exceptions on many of its API
methods. In many cases, I want to catch these exceptions and do
something Clojure-friendly with them. With Clojure 1.2.x, I had no
trouble catching checked exceptions by type, e.g.:

(try
  (some-app-engine-api-methods-called-here ...)
  (catch EntityNotFoundException ex ...))

This stopped working in 1.3.0. The caught exception does not match
EntityNotFoundException; it is now a RuntimeException with the
original typed exception chained to it.

I don't fully understand the implications of the exception handling
changes in 1.3 (https://github.com/clojure/clojure/commit/
8fda34e4c77cac079b711da59d5fe49b74605553). Does it mean that all
exceptions coming in from Java code into Clojure will now be wrapped
in an extra RuntimeException?

If so, then typed catch clauses become useless, and the equivalent
functionality will require writing code like this:

(catch Exception ex
  (cond (isa? (class (.getCause ex)) EntityNotFoundException) ...))

I can wrap that in some kind of a catch* macro (which would also
support directly catching an exception for Clojure 1.2.x
compatibility), but I'm wondering if I'm doing something wrong here.

-- 
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: Exception handling changes in Clojure 1.3.0

2011-10-03 Thread Constantine Vetoshev
On Oct 3, 12:27 pm, Stuart Halloway stuart.hallo...@gmail.com wrote:
 Catching checked exceptions seems to work fine. Try e.g.

 (try (throw (java.io.IOException.)) (catch java.io.IOException _ caught!))

 I suspect something else is going wrong in the GAE example. Can you
 narrow the code down to a block you can quote in full here?

Your example works because it doesn't trigger the use of
clojure.lang.Reflector. I'm having a hard time isolating a good
example where an exception passes through Reflector on its way from
Java into Clojure. (It doesn't happen when trivially calling simple
methods on simple Java classes.)

Here is the relevant stack trace, however. The top level invocation of
DatastoreServiceImpl.get throws the exception (level 0), and I hope to
catch it in retrieve (level 9).

  0:
com.google.appengine.api.datastore.DatastoreServiceImpl.get(DatastoreServiceImpl.java:
64)
  1: sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  2:
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
  3:
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
  4: java.lang.reflect.Method.invoke(Method.java:597)
  5: clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:92)
  6: clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:30)
  7: appengine_magic.services.datastore
$retrieve_helper.doInvoke(datastore.clj:363)
  8: clojure.lang.RestFn.invoke(RestFn.java:521)
  9: appengine_magic.services.datastore
$retrieve.doInvoke(datastore.clj:376)

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


[ANN] appengine-magic 0.4.0: Clojure on Google App Engine

2011-03-27 Thread Constantine Vetoshev
I would like to announce the release of appengine-magic version 0.4.0,
a library designed to make it easier to write Clojure applications for
Google App Engine.

appengine-magic abstracts away nearly all the boilerplate necessary to
deploy an App Engine application. It also enables interactive
development through the REPL. It has full support for most App Engine
services: the datastore, memcache, user Google account authentication,
the blobstore, sending and receiving email, task queues, image
processing, remote URL access, and server push.

0.4.0 is a significant improvement over previous versions, and
includes:

- Support for the latest App Engine SDK.
- Support for all App Engine API operations in the interactive
  REPL, as long as the application is running. This includes all
  datastore and memcache operations.
- Support for using the /_ah/admin console when running in
  interactive REPL mode.
- Support for deploying applications with multiple
  environments (e.g., production and staging can be deployed
  separately from the same project.clj definition).
- Bindings for the App Engine image processing API.
- Bindings for server push (Channel API).

https://github.com/gcv/appengine-magic

The library is available in Clojars. The README file fully documents
the available API. Please note that this release includes several
minor breaking changes; they are detailed in the HISTORY file.

Comments, bug reports, questions, and patches welcome.

Thanks,
Constantine Vetoshev

-- 
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 - .class files and GAE's too many files problem

2011-02-13 Thread Constantine Vetoshev
On Feb 10, 7:47 pm, Edgar Gonçalves edgar.goncal...@gmail.com wrote:
 So for future reference, if you come up with the same issue, the solution is
 to compile your gen'ed-classes and delete all the others from the
 war/WEB-INF directory, making sure you have a standalone jar along the
 remaining used jars (a uberjar may also work, can't see why not). If you
 happen to have a file-size problem on your jars, you can use a flag on the
 upload script. Google for --enable_jar_splitting for more details.

I realize you already solved the problem in your app, but for the
benefit of others reading this thread: appengine-magic takes care of
this for you. It bundles loose class files into you
application's .jar. This has the added benefit of making deployment
much faster. Unless you need AOT compilation for gen-class, you never
have to worry about managing compiled files.

http://github.com/gcv/appengine-magic

-- 
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: Library and development process for GAE

2011-01-09 Thread Constantine Vetoshev
On Jan 9, 10:54 am, Stefan Kamphausen ska2...@googlemail.com wrote:
 Given that decision I'd like to understand the general development process.  
 Does one always compile to a class (ns ...gen-class ..extends ..Servlet) and
 will the appengine development server pick up the changes, or will I just
 recompile a function (using a setup with Emacs and SLIME), what about the
 REPL mode of appengine-magic together with the datastore and other features.

I'm the author of appengine-magic, so my opinion is necessarily biased
in its favor. :)

appengine-magic is designed to be a self-contained, easy way to use
Google App Engine with Ring, or any Ring-compliant framework.
appengine-magic includes its own datastore abstraction layer, with a
(reasonably) high-level Clojure syntax and API. Most other App Engine
services are also included, with idiomatic Clojure wrappers.

I optimized the development process for interactive use. You write
code with Emacs and SLIME, recompile functions interactively, and your
local development web server will show all changes. No restarts and no
nasty watch this directory for changed class files kludges are
needed. In version 0.4.0 (https://github.com/gcv/appengine-magic/tree/
v0.4.0, use 0.4.0-SNAPSHOT as a dependency), the REPL mode works
fine with the datastore and other App Engine SDK features: you can run
datastore queries right from the REPL. I will probably finalize the
0.4.0 release soon, since it's a huge improvement over 0.3.x.

For deployment, you will have to compile .class files, but appengine-
magic provides Leiningen tasks to simplify the process. Please refer
to the documentation for more information, but you basically just run
lein appengine-prepare and then either run the SDK's deployment
script or lein appengine-update.

The README file has full instructions for getting started. To get
started, just install the SDK and make a Leiningen project with the
correct dependencies. Feel free to contact me if you have any
questions.

-- 
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: Automatically unmapping unit tests from namespaces

2010-12-22 Thread Constantine Vetoshev
On Dec 21, 7:16 pm, Phil Hagelberg p...@hagelb.org wrote:
 If you're already using swank then you can try clojure-test-mode; it
 clears out all deftests in between test runs.

 https://github.com/technomancy/clojure-mode/blob/master/clojure-test-...

 It also highlights failures in the test buffer for better feedback.

clojure-test-mode is pretty nice, but is there any way to make its
test namespace naming convention configurable?

It currently expects src/com/company/project/file.clj to correspond to
test/com/company/project/test/file.clj. I prefer test/test/com/company/
project/file.clj, i.e., just prefix the whole namespace with test,
rather than insert it as the penultimate namespace element. I find it
much easier to tell, at a glance, if I'm looking at a test namespace
if it just starts with test, rather than hunting through the entire
dotted string.

-- 
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: ANN: Dr. Evil - the evil web debugger

2010-11-30 Thread Constantine Vetoshev
On Nov 29, 2:25 pm, Miki miki.teb...@gmail.com wrote:
 Yeah, it uses load-string which IMO default to clojure.core
 namespace.
 I've tried some namespace hacking to allow the user to define the
 namespace, but couldn't make it work
 (there's a FIXME in the code about that).

 Currently I using names with namespace - (cv-test-1.core/some-func
 arg1 arg2). Will try to fix that soon.

Could (eval (read-string ...)) 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: ANN: Dr. Evil - the evil web debugger

2010-11-29 Thread Constantine Vetoshev
On Nov 22, 6:43 pm, Miki miki.teb...@gmail.com wrote:
 Dr.Evilis a simple web debugger that provides a REPL to your web
  application in a hidden location.

This is pretty useful, thanks!

I tried adding Dr. Evil into a test app, but I'm having trouble
switching namespaces in the REPL:

= *ns*
#Namespace clojure.core
= (in-ns 'cv-test-1.core)
#Namespace cv-test-1.core
= *ns*
#Namespace clojure.core

It seems to always reset the namespace to clojure.core.

-- 
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: appengine-magic 0.3.0: Clojure on Google App Engine

2010-11-24 Thread Constantine Vetoshev
On Nov 24, 6:41 am, Vesa Marttila vtmartt...@gmail.com wrote:
 I have a question about this release: I understood from this release
 announcement that entities can be saved from the REPL, but I was not
 able to do so and the official documentation still states that it
 can't be
 done, which is the case?

You can't directly use datastore functions from the REPL. When I said
interactive development through the REPL, I meant the ability to
recompile individual files and functions inside a running application
— this definitely works across the board; it was a design requirement
for appengine-magic. You need to use an editor-linked REPL for this
functionality, such as SLIME. I believe VimClojure, Enclojure
(NetBeans), Counterclockwise (Eclipse), and La Clojure (IntelliJ IDEA)
should also work, but do not use them myself.

That said, I hear you loud and clear. Several other people have asked
me about making it possible to use the datastore from the REPL. I
actually tried to get that into this release, but it requires a decent
amount of hackery. I'll see what I can do about putting this into the
next release.

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


[ANN] appengine-magic 0.3.0: Clojure on Google App Engine

2010-11-23 Thread Constantine Vetoshev
I would like to announce the release of appengine-magic version 0.3.0,
a library designed to make it easier to write Clojure applications for
Google App Engine.

appengine-magic abstracts away nearly all the boilerplate necessary to
deploy an App Engine application. It also enables interactive
development through the REPL. The new version has full support for
many App Engine services: the datastore, memcache, user Google account
authentication, the blobstore, sending and receiving email, task
queues, and remote URL access.

http://github.com/gcv/appengine-magic

The library is available in Clojars. The README file fully documents
the available API.

Comments, bug reports, questions, and patches welcome.

Thanks,
Constantine Vetoshev

-- 
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: appengine-magic: using Clojure with Google App Engine

2010-10-06 Thread Constantine Vetoshev
On Oct 4, 10:52 pm, Glen Stampoultzis gst...@gmail.com wrote:
 On 21 September 2010 07:15, Constantine Vetoshev gepar...@gmail.com wrote:
  I'd like to announce the release of a working version of appengine-
  magic, a library designed to make it easier to get started with Google
  App Engine using Clojure.
  .. chop ..

 I noticed it uses ring out of the box.  I was wondering if this is
 compatible with compojure?  There also seems to be a compojure-gae project
 floating around so I'm a little confused as to which project I should be
 using.

appengine-magic works well with Compojure (version 0.5.x). Any Ring-
compatible framework should also work, as long as it has no
dependencies blacklisted in the App Engine classloader. I should
probably put an example in the documentation, but here's one in the
meanwhile:

(use 'compojure.core)
(require '[appengine-magic.core :as ae])

(defroutes test-1-app-handler
  (GET / [] hello world)
  (ANY * []
   {:status 404
:headers {Content-Type text/plain}
:body not found}))

(ae/def-appengine-app test-1-app #'test-1-app-handler)

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


VerifyError with symbol metadata, macros, and defrecord

2010-09-26 Thread Constantine Vetoshev
In Clojure 1.2, compiling the code below blows up with:

error: java.lang.VerifyError: (class: t1/core/One, method: clinit
signature:
()V) Incompatible argument to function (core.clj:11)

Something about this problem causes damage to the running Clojure
process. Once
the exception happens, changing the macro to a working version will
not make the
sample work with the tagged symbol, almost as if the symbol 'one
(below) is
somehow corrupt. You either need to start a new REPL, or try to invoke
the macro
with a different tagged symbol.

I'm honestly not even sure if (1) I don't understand something, (2)
this is a
bug in Clojure, or (3) this is just a remarkably unhelpful error
message.


(ns t1.core)

(defmacro mac1 [name properties]
  ;; does not work:
  (let [key-info (keyword (first (filter #(meta %) properties)))]
  ;; works:
  ;(let [key-info (keyword (str (first (filter #(meta %)
properties]
(prn key-info)
;; commenting out the defrecord below also makes this work:
`(defrecord ~name ~properties)))

(mac1 One [^:key one, two])

-- 
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: Making Clojure really work with Google App Engine

2010-09-20 Thread Constantine Vetoshev
On Sep 20, 9:17 am, Stefan Kamphausen ska2...@googlemail.com wrote:
 So it might be a good idea to avoid creating threads automatically or
 importing file/socket packages.

I think you're right. Dependencies are always a double-edged sword,
and in the case of App Engine, they are more toxic than usual. Anyway,
I eliminated the ring-servlet dependency, and appengine-magic now
successfully deploys simple hello world Ring applications. I'll send
a more formal announcement to the mailing list shortly.

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


[ANN] appengine-magic: using Clojure with Google App Engine

2010-09-20 Thread Constantine Vetoshev
I'd like to announce the release of a working version of appengine-
magic, a library designed to make it easier to get started with Google
App Engine using Clojure.

appengine-magic abstracts away nearly all the boilerplate necessary to
deploy an App Engine application. It also enables interactive
development through the REPL.

http://github.com/gcv/appengine-magic

The library is available on Clojars. It does not currently provide any
App Engine services, but I wanted to get a usable version out as
quickly as possible. Please look through the README file for details.

Comments welcome, as always.

Constantine Vetoshev

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


Making Clojure really work with Google App Engine

2010-09-19 Thread Constantine Vetoshev
I recently spent some time trying to abstract away some of the
incidental complexity of using Google App Engine with Clojure. Right
now, setting up interactive development and understanding what to do
requires reading several blog posts, and pasting in a lot of
boilerplate code. I ended up making a small library, called appengine-
magic, which cuts the boilerplate down to (1) a single additional .jar
dependency, (2) a couple of macros, and (3) a couple of files
generated by a Leiningen plugin. It takes a Ring handler, and turns it
into an application suitable for App Engine.

http://github.com/gcv/appengine-magic

It doesn't do everything yet, but I feel that it already makes a much
easier starting point than any alternative. The README file explains
the details.

Unfortunately, I hit a major stumbling block. Live deployment to App
Engine does not work because of a dependency importing a blacklisted
class.

appengine-magic expects to deploy a Ring handler. This makes it
possible to write apps using any Ring-compliant Clojure web framework.
In order to deploy to App Engine, it needs to turn the handler into a
servlet. The ring-servlet library does this with its handy
ring.util.servlet/defservice function. The implementation of
defservice uses duck-streams/copy. duck-streams imports
java.net.Socket, a class blacklisted by App Engine, causing deployment
to fail.

So any innocuous dependency, which transitively depends on anything
which loads a file which imports a blacklisted class, can cause
deployment to fail. Even Clojure itself is not entirely safe: for
example, duck-streams is now clojure.java.io, which imports
java.net.Socket.

I can reimplement defservice, and so avoid depending on ring-servlet.
Still, the situation seems fragile and precarious. Suggestions and
comments welcome.

-- 
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: Extending Clojure's STM with external transactions

2010-09-07 Thread Constantine Vetoshev
On Sep 5, 8:56 pm, Alyssa Kwan alyssa.c.k...@gmail.com wrote:
 Any thoughts on how to marshal functions? What about vars and dynamic
 binding?

I don't think marshaling closures will ever happen without changes to
Clojure itself. I haven't looked into how much work it would require,
or how much it would impact Clojure's performance. It always seemed
like an excessively lofty goal anyway: if I could save plain Clojure
data structures (all primitives, all fully-evaluated collections, and
all records), I would be happy with it. In truth, I always wanted to
extend Cupboard to support some kind of semi-magical distributed
storage (like Oracle Coherence, but with better persistence guarantees
— database-like rather than cache-like), but wanted to get single-node
basics working properly first. The latest BDB JE has some replication
built-in, and I planned to use it.

As for dynamic binding, I'm not sure what you mean. The bound value
will evaluate using Clojure's normal rules when cupboard.core/make-
instance runs, and go into the database. cupboard.core/query will then
read it and make the value part of the returned map (it should really
be a Clojure 1.2 record). The code doesn't do anything except save and
restore fully-evaluated data structures.

Incidentally, Cupboard wraps BDB transactions, and does not attempt to
work with Clojure's STM subsystem. I always considered this a
weakness, but a difficult one to resolve. To counterbalance it, I
planned to avoid mixing STM and on-disk data structures in the same
code.

-- 
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: Extending Clojure's STM with external transactions

2010-09-05 Thread Constantine Vetoshev
On Aug 30, 5:02 pm, nchubrich nchubr...@gmail.com wrote:
 Persistence libraries always end up warping the entire codebase; I've
 never succeeded in keeping them at bay.  Using data with Incanter is
 different from ClojureQL, which is different from just using
 contrib.sql, and all of it is different from dealing with just
 Clojure.  (I've never even tried Clojure + Hibernate.)  You might as
 well rewrite the program from scratch depending on what you use.
 Maybe other people have had better luck; but whatever luck they have,
 I'm sure it is a fight to keep programs abstracted from persistence.

I feel the same way. Late last year, I wrote a small BDB-based library
for adding disk persistence to Clojure datatypes. It does require
knowing in advance which types you want to write to disk. I haven't
had time to work on it recently, but I'd like to pick it up again
sometime soon. (And I welcome help — the wonders of open-source
software and all that.)

http://github.com/gcv/cupboard

It has a few outstanding problems.

1. It needs to be updated for deftype and defrecord in Clojure 1.2.
2. Deadlock detection doesn't seem to work 100% of the time, and I
haven't yet tracked down the reasons. Parts of the test suite
currently fail as a result.
3. Reads are slow. Casual profiling hasn't revealed the reasons, so
it's a bit tricky to track down.

-- 
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: My non-ELPA Emacs swank-clojure setup

2010-04-11 Thread Constantine Vetoshev
On Apr 8, 12:45 pm, Ævar Arnfjörð Bjarmason ava...@gmail.com wrote:
 If I have 10 Clojure projects I'm going to have 10 src/clojure.jar
 files. Do they really need to be there or could I just use the clojure
 that comes with my operating system (Debian)?

 When I hack Common Lisp I don't copy sbcl into all my projects, I just
 install it once globally. I'd like to do the same with clojure.

Although I'm with you about ELPA and preferring the traditional way to
install Emacs packages, I disagree on this point. I find it
counterproductive to think of Clojure and its distribution in the same
terms as Common Lisp's. It's easier to think of Clojure apps more like
Java apps which happen to use a much better language.

I actually prefer to have a lib/clojure-X.Y.Z.jar in my project. This
guarantees that, as long as the deployment machine has a Clojure-
supporting JVM, the app has no other system-level dependencies. It
also allows flexibility with trying out unreleased and unpackaged
versions of Clojure. This eliminates the hideous mess in most
distributions of having packages like python24, python25, python26,
python30 (and resulting things like python24-somelib and python26-
somelib).

-- 
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: My non-ELPA Emacs swank-clojure setup

2010-04-11 Thread Constantine Vetoshev
This thread encouraged me to post what I did to make swank-clojure
1.1.0 work with the the latest SLIME. It does not use any of swank-
clojure's automatic .jar downloading features (as of version 1.1.0).
These instructions won't work on Windows, but may work if you have
Cygwin.

Note that this sets up some Common Lisp installations. Delete those
lines if you don't want them.

If you already figured out how to put SLIME and swank-clojure on your
classpath, omit that part of the setup. See the comments.

Assumptions:
 - SLIME in ~/.emacs.d/site-lisp/slime
 - swank-clojure in ~/.emacs.d/site-lisp/swank-clojure
 - your project is laid out with a src/ directory containing your
actual code; it goes on the classpath
 - you want all .jar files in your project on your classpath
 - several directories, including classes/ and resources/, also get
added to your classpath
 - you have exactly one file called clojure-version-number.jar in
the resulting classpath; this becomes the version of Clojure launched
by SLIME

Instructions:
 - put the code below into your .emacs.d/init.el or .emacs file
 - use M-x clojure-project to launch SLIME; this is my variant of
swank-clojure-project, but it makes no assumptions about Maven,
magical downloads, ELPA, or anything else

Limitation:
 - slime-connect doesn't seem to work right; you have to launch
Clojure and your app using clojure-project

One more thing: swank-clojure 1.1.0 requires a tiny patch to work with
the latest SLIME. This patch seems to already be in swank-clojure's
master branch, but be aware of it: 
http://groups.google.com/group/swank-clojure/msg/01ff818359061a28

Could this be a good start to making swank-clojure both newbie-and-
ELPA-friendly and Emacs-graybeard-friendly?



;;; generic Emacs utility
;;; --

(defun add-subdirs-to-load-path (dir)
  (let ((default-directory (concat dir /)))
(normal-top-level-add-subdirs-to-load-path)))


;;; basic load-path setup
;;; --

(add-to-list 'load-path ~/.emacs.d/site-lisp)
(add-subdirs-to-load-path ~/.emacs.d/site-lisp)


;;; SLIME and swank-clojure
;;; --

(require 'slime-autoloads)
(add-to-list 'load-path ~/.emacs.d/site-lisp/slime/contrib)
;(slime-setup '(slime-fancy slime-asdf))
(slime-setup '(slime-repl))

(setq slime-net-coding-system 'utf-8-unix)

(setq slime-lisp-implementations
  '((acl  (/opt/acl/alisp))
(sbcl (/opt/sbcl/run-sbcl.sh))
(ccl  (/opt/ccl/dx86cl64

(defmacro defslime-start (name mapping)
  `(defun ,name ()
 (interactive)
 (let ((slime-default-lisp ,mapping))
   (slime

(defslime-start acl 'acl)
(defslime-start sbcl 'sbcl)
(defslime-start ccl 'ccl)
(defslime-start clojure 'clojure)

(setq swank-clojure-classpath '(~/.emacs.d/site-lisp/swank-clojure/
src))
(setq swank-clojure-extra-vm-args
  (list -server -Xms128M -Xmx512M -Dfile.encoding=UTF-8))

(autoload 'clojure-mode clojure-mode A major mode for Clojure t)
(add-to-list 'auto-mode-alist '(\\.clj$ . clojure-mode))
(require 'swank-clojure)

(add-hook 'slime-mode-hook
  (lambda ()
(setq slime-truncate-lines nil)
(slime-redirect-inferior-output)))

(defun clojure-slime-reset ()
  Helper function which resets Clojure in SLIME's list of
   implementations. Useful for changing Clojure's classpath.
  (setq slime-lisp-implementations
(cons `(clojure ,(swank-clojure-cmd) :init swank-clojure-init)
  (remove-if #'(lambda (x) (eq (car x) 'clojure))
 slime-lisp-implementations

(defun clojure-project-prompt (path)
  (interactive GProject path: )
  (list path))

(defun clojure-project (path)
  Set up Clojure classpath and other swank-clojure variables for
   the project with root at 'path'. Include all *.jar files under
   path. Also include 'classes' subdirectory.
  (interactive
   (let* ((dominating-file (locate-dominating-file buffer-file-name
   src/))
  (default-directory (if (and buffer-file-name dominating-
file)
 dominating-file
 default-directory)))
 (call-interactively 'clojure-project-prompt)))
  (when (and (fboundp 'slime-connected-p) (slime-connected-p))
(slime-quit-lisp)
(sleep-for 1)
(slime-kill-all-buffers))
  (flet ((clojure-jar-p (s) (string-match
 clojure\\(-[0-9a-f\\.]*\\)?\\.jar$
 s))
 (validate-path (p) (when (file-accessible-directory-p p)
  (list p
(let* ((src-path
(append
 (validate-path (expand-file-name src path))
 (validate-path (expand-file-name source path))
 (validate-path (expand-file-name code path
   (test-path

Re: Clojure for financial applications

2010-03-09 Thread Constantine Vetoshev
On Mar 8, 11:50 am, Jonathan Shore jonathan.sh...@gmail.com wrote:
 How would I encapsulate this into a data structure to be passed into 
 functions efficiently?    I could use a map of symbols to various structures, 
 but that would be inefficient in access and memory.   I could bind into a 
 closure but then how do I evolve the closure.

Doug Hoyte's book Let Over Lambda (http://letoverlambda.com) has
plenty of tips on how to hack closures, including accessing closed-
over values. The book uses Common Lisp, but most of it maps easily to
Clojure. The relevant chapter on anaphoric macros is not available in
the free preview, unfortunately.

To summarize in Clojure terms, you make a wrapper macro for fn,
called, e.g., pfn. pfn then works exactly like fn, except you may also
use it with some predetermined arguments. Those arguments make the
closure return closed-over values.

-- 
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: Prepping clojure for packaging (was: Re: Clojure for system administration)

2010-02-06 Thread Constantine Vetoshev
On Feb 6, 1:06 pm, Peter Schuller peter.schul...@infidyne.com wrote:
 But the practical issue
 remains that if I want to write some software that I want sysadmins in
 various situations to want to use effortlessly (in my case, a backup
 tool), problems like these do get in the way of choosing Clojure.

 Maybe uberjars are the pragmatic approach after all. But then what
 about GPL libraries and similar license hassles?

I can't comment on the licensing problem, but could you expand on what
exactly you don't like about packaging jars (as uberjars or separates)
and distributing them as part of your application? If you distribute
your app with precisely the jars you tested with, you don't have to
worry about subtle incompatibilities sneaking in. Except for obviously
bloated software (e.g., JBoss), Java jar files are relatively small.
When you package for Debian, put the jars in /usr/share/my-awesome-app/
jars, put in a dependency on sun-java-1.x, and provide a wrapper shell
script to start the whole thing (your classpath just includes the
stuff you provided). For the installing admin, your package is just an
aptitude install my-awesome-app away, and it just pulls down a JVM
dependency. Simple, and fairly lightweight.

I stopped using Python and Ruby and Perl partly because the packaging
situation for all those languages is a horrible mess. For example, if
you write a Ruby app, you are highly likely to run into trouble
packaging it even for a recent distribution because your dependencies
may not have been packaged or made available as rb-*.debs in the
official repository. Or, rb-*.debs exist, but provide an incompatible
version of the library you need. Ubuntu and Fedora may ship different
versions of common gems, so you can't even code against an obvious
lowest common denominator. (To make matters worse, gem install,
easy_install, and cpan -i all create weird parallel universes of
packages which may cause conflicts with system-provided packages.
Python's virtualenv helps mitigate the problem to some extent.)

C programs have it easier, because the overwhelming majority of
commonly used libraries are packaged and available in recent
distributions, and I have rarely had trouble with just writing against
a slightly older version of a library. It's perfectly reasonable to
dynamically link against libjpeg and make a note of a libjpeg
dependency in the package descriptor file.

In short, I think that the Java and Clojure way of packaging software
make life much easier for programmers, package maintainers, and
administrators, not harder. Making applications self-contained helps
avoid dependency hell at packaging and deployment time, not to mention
during development. It's a bit wasteful to have multiple copies of
log4j or whatever floating around, but I'd rather waste a few
gigabytes of disk space on duplicates than deal with system-wide
classpaths.

-- 
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: ANN: dgraph 1.0, a dependency graph library for Clojure

2010-01-19 Thread Constantine Vetoshev
On Jan 18, 2:14 am, mac markus.gustavs...@gmail.com wrote:
 Updating stuff in the map became a little bit of a hassle so I made
 versions of assoc-in and update-in that work on dgraphs. Here they are
 in case anyone else is interested:

 (defn assoc-node
   [dgraph m ks v]
   (dgraph m (assoc-in (dgraph m) ks v)))

 (defn update-node
   [dgraph m ks f  args]
   (dgraph m (apply update-in (dgraph m) ks f args)))

 Suppose we have a dgraph dg and a map in the dgraph with the key :gui-
 data, in the map we want to replace or update the key :message

 (assoc-node dg :gui-data [:message] Hello World!)
 (update-node dg :gui-data [:message] conj World!)

Thanks, Markus! I added these functions into dgraph as assoc-in-node
and update-in-node. The new version of dgraph with these additions is
1.1.0, available on GitHub and Clojars.

http://github.com/gcv/dgraph
http://clojars.org/dgraph
-- 
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: ANN: dgraph 1.0, a dependency graph library for Clojure

2010-01-17 Thread Constantine Vetoshev
On Jan 17, 4:05 am, Albert Cardona sapri...@gmail.com wrote:
 The link gives a not found--did you push?

I did, but then I moved the examples directory around to make
everything more Leiningen-layout-friendly. Here is the updated link:
http://github.com/gcv/dgraph/blob/master/examples/examples/dgraph/swing.clj

Please note that navigating the tree from the GitHub web interface has
strange redirect bugs right now. I opened a ticket with GitHub to
investigate the problem. Cloning the repository works fine.

 By the way dgraph looks really interesting for GUI programming. I am
 looking forward to trying it out.

Great! Let me know how it works out for you.
-- 
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: ANN: dgraph 1.0, a dependency graph library for Clojure

2010-01-16 Thread Constantine Vetoshev
On Jan 16, 4:01 am, mac markus.gustavs...@gmail.com wrote:
 I am just now in a situation where I have to do some swing programming
 and this seems like it has great potential!
 Since it's already version 1.0 you should put it on Clojars so that it
 is easier to use from leiningen or maven etc.

Good call. I just put it up on Clojars: http://clojars.org/dgraph. Let
me know how using dgraph works out for you.
-- 
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: ANN: dgraph 1.0, a dependency graph library for Clojure

2010-01-15 Thread Constantine Vetoshev
On Jan 14, 7:29 pm, Timothy Pratley timothyprat...@gmail.com wrote:
 To give me a
 head-start, are there key differences with clojure.contrib.dataflow so
 I can better understand?

Thank you for your interest. I have not extensively used c.c.dataflow,
so I apologize if I misrepresent it, but here are some key
differences:

1. c.c.dataflow feels imperative in nature. build-dataflow returns a
ref. Functions which manipulate these refs — such as update-values,
add-cells, and remove-cells — use destructive modification. dgraph
tries pretty hard to work functionally, just like Clojure's built-in
persistent data structures. A dgraph is immutable, but supports an
extend operation similar to assoc and conj. Extended dgraphs share
structure with original dgraphs as much as possible.

2. c.c.dataflow does not seem to support lazily computed nodes. A node
put in a dataflow computes itself immediately. dgraph supports this
behavior with eager nodes, but has two other modes: lazy and patient.
I tried to explain how those work in the README. Please let me know if
the documentation makes no sense. I'll add a more detailed example to
the source repository later today.
-- 
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: ANN: dgraph 1.0, a dependency graph library for Clojure

2010-01-15 Thread Constantine Vetoshev
On Jan 15, 5:59 am, Laurent PETIT laurent.pe...@gmail.com wrote:
 I would like to know, is there an essential reason for not having
 stored the dependency graph as a hidden property of the graph ?

I'm not sure I understand your question. You can see the stored graph
if you take the function returned by dg/make-dgraph and call it
without any arguments. I consider that an implementation detail,
though.

The dependency graph returned by dg/make-graph is a closure rather
than a data structure mainly to allow shortcut syntax for accessing
and setting node values: (my-dgraph :my-node) is just a function
call. So is (my-dgraph :my-node new-node-value). If my-dgraph was not
a function, there would have to be a more verbose calling convention.
(Reader macro support in Clojure would have taken away some of the
verbosity.)

 Do you have examples of where you see it interesting to use (and not
 abuse :-) ) side effects in combination with eager/patient ?

I just checked in a Swing usage example which uses side effects to
update the UI (http://github.com/gcv/dgraph/blob/master/src/examples/
dgraph/swing.clj). Please let me know if it makes sense. I hope the
concept is useful outside of just making Swing programming less
agonizing, though. :)

 Are there implicit hypothesis (not yet documented ? or maybe I
 overlooked) on the types that can be used for the keys of the graph ?

Not particularly, no. I have always used keywords, so they are best-
tested. Even so, any type usable as a key in a normal Clojure map
should work. If you find something not working with another type,
definitely let me know, and I'll try to fix it.

 For those of use who do not know cl cells, would it be easy to explain
 in which area it differs ?

Cells the Common Lisp library lets you put slots of CLOS objects on a
dependency graph. Put another way, any slot in any CLOS object can
become a node on the graph. The Clojure dgraph library isolates the
entire dependency graph in a separate, immutable data structure.
Clojure cannot readily adopt the Cells way of doing things, because it
has no CLOS and no meta-object protocol. dgraph also tries to at allow
and even encourage purely functional use, in spite of its usefulness
in side-effect-ridden UI code. Cells is more imperative in nature.

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

ANN: dgraph 1.0, a dependency graph library for Clojure

2010-01-14 Thread Constantine Vetoshev
I would like to announce the release of dgraph 1.0, a dependency graph
implementation for Clojure.

http://github.com/gcv/dgraph

dgraph provides a mostly pure functional data structure whose nodes
behave like cells in a spreadsheet. Data changes in stored nodes cause
their dependent computed nodes to invalidate and recalculate
themselves. Dependency graphs are immutable, just like Clojure's built-
in persistent data structures, so changing a stored node actually
augments an existing graph and returns a new one with shared
structure.

I wrote this to simplify UI programming, and it has helped reduce the
pain significantly. The README file in the GitHub repository has some
usage examples and ideas.

Comments and bug reports welcome.

Thanks,
Constantine Vetoshev
-- 
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: Clojure + Redis

2009-12-31 Thread Constantine Vetoshev
On Dec 30, 10:40 am, Robert Campbell rrc...@gmail.com wrote:
 I think anything which lowers the impedance mismatch between Clojure
 data structures and a persistent store is worth investigating. I'd
 love to find an ACID, transactional store which accepts native
 structures.

Have you looked at Cupboard (http://github.com/gcv/cupboard)? It tries
to make it easy to store native Clojure data structures, and it is as
ACID and transactional as the underlying Berkeley DB JE
implementation. If you have looked at it, I'd appreciate some feedback
as to where it fell short of your expectations. :)

I plan to start adding distributed storage support in the next few
months. The latest JE release has master-slave replication, which I
think will work well for Cupboard.

-- 
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: Clojure as a first programming language?

2009-12-01 Thread Constantine Vetoshev
On Dec 1, 12:38 am, Towle towle.m...@gmail.com wrote:
 So after shopping around
 thoroughly and picking up bits about on theoretical computer science
 and the history of programming languages, I decided to pick up a Lisp;
 I'm intrigued by the greater concept/idea behind the Lisp family of
 languages.

In your research, did you find Abelson and Sussman's book, Structure
and Interpretation of Computer Programs? The full text is freely
available at http://mitpress.mit.edu/sicp/, and video lectures from
the class are at 
http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/.
I have never seen a better introduction to programming and computing
than SICP. It uses Scheme, but you do not need to study the language
separately; you'll learn it naturally as you go through the book. Be
sure to do the exercises. :)

You can certainly go through SICP using Clojure, but you'll have to
deal with semantic differences between Scheme and Clojure (especially
in laziness and sequence behavior), so I don't recommend it. After you
have gone through the book, you'll pick up Clojure in no time at all,
and will probably find it an enjoyable language for real-world
programming.

-- 
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: A macro for flexible keyword argument handling

2009-11-20 Thread Constantine Vetoshev
On Nov 20, 8:33 am, nchubrich nicholas.chubr...@gmail.com wrote:
 I guess this is getting to be a pretty epic macro!  I figured it was
 worth inviting boos and/or cheers and suggestions before setting out...

Far be it from me to discourage making function invocation semantics
more flexible! Just one thing: you've been calling your macro
defnsk, which makes it sound like a wrapper for the def form. Don't
leave defmethod, fn, letfn, and every other way of making a function
in the dust. :)

-- 
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: A macro for flexible keyword argument handling

2009-11-18 Thread Constantine Vetoshev
On Nov 17, 11:33 pm, nchubrich nicholas.chubr...@gmail.com wrote:
 can it be any more
 general or minimal than this?

Seems to me that your suggestion effectively makes every positional
argument optional. You did note that the scheme calls for supplied-
predicates, but this pushes responsibility for checking required
arguments from the compiler to the programmer. That seems a little too
minimal to me, and barely an improvement from extracting everything
from an arguments 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
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: A macro for flexible keyword argument handling

2009-11-17 Thread Constantine Vetoshev
On Nov 16, 4:28 pm, Chouser chou...@gmail.com wrote:
 'let' is also careful to always have the user provide the symbol
 being bound as a symbol.  That is you say {:keys [a b c]} not
 {:keys [:a :b :c]}.  What do you think of having let-kw take
 symbols instead of keywords for the names being bound?

I think that's a good idea.

Updated version:

(defmacro let-kw
  Adds flexible keyword handling to any form which has a parameter
   list: fn, defn, defmethod, letfn, and others. Keywords may be
   passed to the surrounding form as  rest arguments, lists, or
   maps. Lists or maps must be used for functions with multiple
   arities if more than one arity has keyword parameters. Keywords are
   bound inside let-kw as symbols, with default values either
   specified in the keyword spec or nil. Keyword specs may consist of
   just the bare keyword symbol, which defaults to nil, or may have
   the general form [keyword-name keyword-default-value*
   keyword-supplied?*].  keyword-supplied?  is an optional symbol
   bound to true if the keyword was supplied, and to false otherwise.
  [kw-spec-raw kw-args  body]
  (let [kw-spec  (map #(if (sequential? %) % [%]) kw-spec-raw)
symbols  (map first kw-spec)
keywords (map (comp keyword name) symbols)
defaults (map second kw-spec)
destrmap {:keys (vec symbols) :or (zipmap symbols defaults)}
supplied (reduce
  (fn [m [k v]] (assoc m k v)) (sorted-map)
  (remove (fn [[_ val]] (nil? val))
  (partition 2 (interleave
keywords
(map (comp second rest)
 kw-spec)
kw-args-map (gensym)]
`(let [kw-args# ~kw-args
   ~kw-args-map (if (map? kw-args#)
kw-args#
(apply hash-map kw-args#))
   ~destrmap ~kw-args-map]
   ~@(if (empty? supplied)
 body
 `((apply (fn [~@(vals supplied)]
~...@body)
  (map (fn [x#] (contains? ~kw-args-map x#))
   [~@(keys supplied)])))

-- 
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: SLIME REPL broken

2009-11-17 Thread Constantine Vetoshev
On Nov 17, 2:52 pm, David Nolen dnolen.li...@gmail.com wrote:
 Thanks for pursuing this so adamantly :) For a long time (more than a year)
 it was possible to use SLIME tip. It would be great for that to continue.

You can still use SLIME; just avoid the slime-autodoc contrib. Use

(slime-setup '(slime-repl))

to initialize SLIME. At least, this works for me. Make sure you don't
use (slime-setup '(slime-fancy)), because slime-fancy includes slime-
autodoc. You lose the nicer minibuffer function argument display, but
at least the basic environment works.

-- 
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: A macro for flexible keyword argument handling

2009-11-16 Thread Constantine Vetoshev
1. Looks like everyone prefers the let-kw name. Sounds good to me.

2. I tried it with the more let-like form, but I don't like the number
of opening braces required. For a full kw-spec, the form would end up
(let-kw [[[:kw default supplied?]] kw-args] ...). Clojure tends to err
on the side of fewer braces and parentheses, and three opening braces
looks excessive to me. That said, I see the point of keeping it
consistent with the other binding forms.

3. Unnecessary interleave replaced with zipmap.

4. With regard to the generality of the interface: I put all those
features in there because I have wanted to use them. I often find
myself writing or wrapping API-like code, and slicing and dicing
arguments and passing them through to other functions, as vectors or
maps, has been useful.

5. As for putting the macro in clojure-contrib, thanks for the vote of
confidence. :) I'll drop a signed Contributor Agreement in the mail
today, and get an Assembla ticket and patch out soon.

Thanks for all the feedback and suggestions. New version:

(defmacro let-kw
  Adds flexible keyword handling to any form which has a parameter
   list: fn, defn, defmethod, letfn, and others. Keywords may be
passed
   to the surrounding form as  rest arguments, lists, or maps. Lists
or
   maps must be used for functions with multiple arities if more than
   one arity has keyword parameters. Keywords are bound inside let-kw
as
   symbols, with default values either specified in the keyword spec
or
   nil. Keyword specs may consist of just the bare keyword, which
   defaults to nil, or may have the general form [:keyword-name
   keyword-default-value* keyword-supplied?*]. keyword-supplied?  is
an
   optional symbol bound to true if the keyword was supplied, and to
   false otherwise.
  [kw-spec-raw kw-args  body]
  (let [kw-spec  (map #(if (sequential? %) % [%]) kw-spec-raw)
keywords (map first kw-spec)
symbols  (map (comp symbol name) keywords)
defaults (map second kw-spec)
destrmap {:keys (vec symbols) :or (zipmap symbols defaults)}
supplied (reduce
  (fn [m [k v]] (assoc m k v)) (sorted-map)
  (remove (fn [[_ val]] (nil? val))
  (partition 2 (interleave keywords
   (map (comp second
rest)
kw-spec)
kw-args-map (gensym)]
`(let [kw-args# ~kw-args
   ~kw-args-map (if (map? kw-args#)
kw-args#
(apply hash-map kw-args#))
   ~destrmap ~kw-args-map]
   ~@(if (empty? supplied)
 body
 `((apply (fn [~@(vals supplied)]
~...@body)
  (map (fn [x#] (contains? ~kw-args-map x#))
   [~@(keys supplied)])))

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


A macro for flexible keyword argument handling

2009-11-15 Thread Constantine Vetoshev
A couple of days ago, I finally had enough of manually extracting
function keyword arguments. defnk is cool and all, but it does nothing
for fn, letfn, defmethod, or any other form with a parameter list. Map
destructuring is also cool, but providing defaults requires writing
each symbol twice, once in :keys and once in :or.

The macro I ended up with, fn-keywords, owes much to Common Lisp's
lambda lists. Instead of an outer wrapper for Clojure's various
function forms, it provides a kind of inner wrapper, really a let form
specialized for keyword arguments. Each keyword is defined in a
keyword spec, which allows for an optional default value, and for an
optional symbol to be bound to true if the keyword was actually
provided in the function call.

Note that keywords arguments may be  rest in style, or provided as
either maps or vectors. This should cover all useful cases for keyword
arguments, including their use in functions with multiple arities.


Example:

(defn test1 [req1 req2  kw-args]
  (fn-keywords [:kw1
[:kw2 kw2 default]
[:kw3 kw3 default kw3-supplied?]]
  kw-args
;; function body
{:req1 req1 :req2 req2 :kw1 kw1 :kw2 kw2
 :kw3 kw3 :kw3-supplied? kw3-supplied?}))

 (test1 1 2 :kw3 there)
{:req1 1, :req2 2, :kw1 nil, :kw2 kw2 default,
 :kw3 there, :kw3-supplied? true}
 (test1 1 2 :kw1 there)
{:req1 1, :req2 2, :kw1 there, :kw2 kw2 default,
 :kw3 kw3 default, :kw3-supplied? false}
 (test1 1 2 :kw1 hello :kw2 there)
{:req1 1, :req2 2, :kw1 hello, :kw2 there,
 :kw3 kw3 default, :kw3-supplied? false}


Macro code:

(defmacro fn-keywords
  Adds flexible keyword handling to any form which has a parameter
list: fn,
   defn, defmethod, letfn, and others. Keywords may be passed to the
surrounding
   form as  rest arguments, lists, or maps. Lists or maps must be
used for
   functions with multiple arities if more than one arity has keyword
   parameters. Keywords are bound inside fn-keywords as symbols, with
default
   values either specified in the keyword spec or nil. Keyword specs
may consist
   of just the bare keyword, which defaults to nil, or may have the
general form
   [:keyword-name keyword-default-value* keyword-bound?*]. keyword-
bound? is an
   optional symbol bound to true if the keyword was supplied, and to
false
   otherwise.
  [kw-spec-raw kw-args  body]
  (let [kw-spec  (map #(if (sequential? %) % [%]) kw-spec-raw)
keywords (map first kw-spec)
symbols  (map (comp symbol name) keywords)
defaults (map second kw-spec)
destrmap {:keys (vec symbols)
  :or (apply hash-map (interleave symbols defaults))}
supplied (reduce (fn [m [k v]] (assoc m k v)) (sorted-map)
 (remove (fn [[_ val]] (nil? val))
 (partition 2
(interleave keywords
(map (comp
second rest)
 kw-
spec)
kw-args-map (gensym)]
`(let [kw-args# ~kw-args
   ~kw-args-map (if (map? kw-args#) kw-args# (apply hash-map
kw-args#))
   ~destrmap ~kw-args-map]
   ~@(if (empty? supplied)
 body
 `((apply (fn [~@(vals supplied)]
~...@body)
  (map (fn [x#] (contains? ~kw-args-map x#))
   [~@(keys supplied)])))


More examples:

(defmulti test2 (fn [x  rest] (class x)))

(defmethod test2 java.lang.Integer [req  kw-args]
  (fn-keywords [[:kw1 default kw1-supplied?]] kw-args
{:method integer
 :req req
 :kw1 kw1
 :kw1-supplied? kw1-supplied?}))

(defmethod test2 java.lang.String [req  kw-args]
  (fn-keywords [[:kw1 default]] kw-args
{:method string
 :req req
 :kw1 kw1}))

(defn test3
  ([req1 kw-args]
 (fn-keywords [:kw1 :kw2] kw-args
   {:req1 req1 :kw1 kw1 :kw2 kw2}))
  ([req1 req2 kw-args]
 (fn-keywords [:kw1 :kw2] kw-args
   {:req1 req1 :req2 req2 :kw1 kw1 :kw2 kw2})))

(defn test4 []
  (letfn [(inner [ kw-args]
(fn-keywords [:kw1 :kw2] kw-args
  {:kw1 kw1 :kw2 kw2}))]
(inner :kw1 hello :kw2 world)))


Credit where it's due: I lifted ideas and bits of code from defnk.
Thanks, Meikel!

Comments welcome.

--
Constantine Vetoshev

-- 
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: A macro for flexible keyword argument handling

2009-11-15 Thread Constantine Vetoshev
Looks like Google Groups posting software forced line wraps at less
than 80 columns, breaking the code. Lovely. Here's the fn-keywords
macro reformatted for 72 column wrapping.

(defmacro fn-keywords
  Adds flexible keyword handling to any form which has a
   parameter list: fn, defn, defmethod, letfn, and
   others. Keywords may be passed to the surrounding form as 
   rest arguments, lists, or maps. Lists or maps must be used for
   functions with multiple arities if more than one arity has
   keyword parameters. Keywords are bound inside fn-keywords as
   symbols, with default values either specified in the keyword
   spec or nil. Keyword specs may consist of just the bare
   keyword, which defaults to nil, or may have the general form
   [:keyword-name keyword-default-value*
   keyword-bound?*]. keyword-bound? is an optional symbol bound
   to true if the keyword was supplied, and to false otherwise.
  [kw-spec-raw kw-args  body]
  (let [kw-spec  (map #(if (sequential? %) % [%]) kw-spec-raw)
keywords (map first kw-spec)
symbols  (map (comp symbol name) keywords)
defaults (map second kw-spec)
destrmap {:keys (vec symbols)
  :or (apply hash-map
(interleave symbols defaults))}
supplied (reduce (fn [m [k v]] (assoc m k v)) (sorted-map)
 (remove (fn [[_ val]] (nil? val))
 (partition 2
(interleave
 keywords
 (map (comp second rest)
  kw-spec)
kw-args-map (gensym)]
`(let [kw-args# ~kw-args
   ~kw-args-map (if (map? kw-args#)
kw-args#
(apply hash-map kw-args#))
   ~destrmap ~kw-args-map]
   ~@(if (empty? supplied)
 body
 `((apply (fn [~@(vals supplied)]
~...@body)
  (map (fn [x#] (contains? ~kw-args-map x#))
   [~@(keys supplied)])))

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


ANN: Cupboard, an embedded database library for Clojure

2009-10-15 Thread Constantine Vetoshev

I would like to announce the release of Cupboard, an embedded database
library for Clojure.

In a nutshell, it allows saving arbitrary struct maps to a database.
It supports indices on struct keys, ACID transactions, and retrieval
using non-trivial queries. For more details and sample code, please
see its README file.

http://github.com/gcv/cupboard

The documentation is still fairly minimal, but, along with the
provided examples, should be enough to get started. Cupboard is built
on top of Berkeley DB JE (and includes a fairly complete Clojure
wrapper for JE as a separate API), so some familiarity with Berkeley
DB will help, but is not required.

All comments and bug reports welcome.

Thanks,
Constantine Vetoshev
--~--~-~--~~~---~--~~
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, namespaces, and lexical scope

2009-09-26 Thread Constantine Vetoshev

On Sep 26, 7:35 am, Meikel Brandmeyer m...@kotka.de wrote:
 The problem is, that you quote the symbol you inject into the inner
 defmacro. Hence it does not get resolved. The solution in this case
 seems to be to syntax-quote the symbol correctly before injection.
 Replace the two ~'~ with ~~ and call the macro as (def-with-db-macro
 with-foo `open-foo `close-foo). This correctly resolves the symbols in
 the namespace calling def-with-db-macro and injects them into the with-
 foo expansion. I haven't really tested this, but it seems to be
 consistent with the macro machinery.

Thank you. That works. I had tried ~~ by itself, and it didn't fly. I
didn't think to syntax-quote the symbol in its place of expansion.

So referring back to http://paste.lisp.org/display/87734, the solution
is:

user (defmacro make-myfoo [foo] `(defmacro ~'myfoo [s#] `(~~foo
~s#)))
   = #'user/make-myfoo
user (ns tmp)
tmp (user/make-myfoo `foo)
   = #'tmp/myfoo
tmp (macroexpand '(tmp/myfoo bar))
   = (tmp/foo bar)

As expected, in the tmp namespace.

 This seems indeed useless at a first glance, but looking down the
 cause trace usually shows the real problem.

Full stack trace follows, although I still don't know what it means.

No message.
  [Thrown class java.lang.ExceptionInInitializerError]

Backtrace:
  0: sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)
  1: sun.reflect.NativeConstructorAccessorImpl.newInstance
(NativeConstructorAccessorImpl.java:39)
  2: sun.reflect.DelegatingConstructorAccessorImpl.newInstance
(DelegatingConstructorAccessorImpl.java:27)
  3: java.lang.reflect.Constructor.newInstance(Constructor.java:513)
  4: java.lang.Class.newInstance0(Class.java:355)
  5: java.lang.Class.newInstance(Class.java:308)
  6: clojure.lang.Compiler$FnExpr.eval(Compiler.java:3428)
  7: clojure.lang.Compiler.eval(Compiler.java:4531)
  8: clojure.core$eval__3990.invoke(core.clj:1728)

--~--~-~--~~~---~--~~
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, namespaces, and lexical scope

2009-09-25 Thread Constantine Vetoshev

(I asked these questions on #clojure, and the friendly locals
suggested I open the question up for a wider audience.)

I'm trying to write a macro-writing-macro. My code has a bunch of
resources which have -open and -close type of calls, and they could
all benefit from with- wrappers. The with- wrappers all have similar
structure, and I thought I would be better off defining them with
another macro:

(defmacro def-with-db-macro [macro-name open-fn close-fn]
  `(defmacro ~macro-name [[var#  open-args#]  body#]
 `(let [~var# (apply ~'~open-fn [...@open-args#])]
(try
 ~...@body#
 (finally (~'~close-fn ~var#))

Sample use:

(def-with-db-macro with-db-env db-env-open db-env-close)

(def-with-db-macro with-db db-open db-close)

(def-with-db-macro with-db-txn db-txn-begin
  (fn [txn] (when (= @(txn :status) :open) (db-txn-commit txn

This mostly works. It breaks if I try using, e.g., with-db-env in a
namespace which does not import db-env-open or db-env-close.

Chris Houser has summarized the problem here more succinctly than I
can: http://paste.lisp.org/display/87734

While searching for a workaround, I thought maybe I could capture the
functions I need during expansion of def-with-db-macro, but kept
getting a useless exception. I ended up reducing that problem to this:

(let [f1 #(inc %)]
  (defmacro m1 [x]
`(~f1 ~x)))

(m1 12)
= No message.
  [Thrown class java.lang.ExceptionInInitializerError]

The equivalent works in Common Lisp (Allegro CL and SBCL):

(let ((f1 (lambda (y) (1+ y
  (defmacro m1 (x)
`(funcall ,f1 ,x)))

(m1 12)
= 13

Thoughts on either of these brain teasers?

Thanks!

PS: To read the IRC discussion, see 
http://clojure-log.n01se.net/date/2009-09-25.html
and scroll down to the discussion starting at 15:16.
--~--~-~--~~~---~--~~
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, namespaces, and lexical scope

2009-09-25 Thread Constantine Vetoshev

On Sep 25, 6:02 pm, John Harrop jharrop...@gmail.com wrote:
 I don't think you can use things like defmacro in a let.

This works:

(let [y 10]
  (defmacro m1 []
`(list ~y)))

(m1) =
(10)

--~--~-~--~~~---~--~~
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: Schema for data structures

2009-09-24 Thread Constantine Vetoshev

On Sep 24, 10:59 am, Miron Brezuleanu mbr...@gmail.com wrote:
 Well, I only want to enforce duck-typing :-) - for instance, make sure
 via unit tests that a function that should return a data structure
 with certain properties always returns such a data structure.

Not exactly what you asked for, but I added a defstruct* helper to my
utils.clj. I'm still not entirely sure it's a good idea, but here it
is:

(defmacro defstruct*
  Wrapper for defstruct which also creates a simple duck type
checking
   function.
  [name  slots]
  `(do
 (defstruct ~name ~...@slots)
 (defn ~(symbol (str is- name ?)) [x#]
   (if (map? x#)
   (let [sample# (struct ~name)]
 (empty? (clojure.set/difference
  (set (keys sample#)) (set (keys x#)
   false

Use it just like you use defstruct, e.g.: (defstruct* person :first-
name :last-name :age), but it will also create a little type-checker
function: is-person? Here are some tests to see how it works:

(defstruct* duck-typed-struct :a :b :c)

(deftest duck-typed-predicates
  (let [dt1 (struct duck-typed-struct 1 2 3)
dt2 {:a 4 :b 5 :c 6}
dt3 (struct duck-typed-struct 1 2)
dt4 {:a 4 :b 5 :c nil}
not-dt1 {:a 4 :b 5}
not-dt2 {:d 7 :e 8}
not-dt3 {:a 4 :b 5 :d 7}]
(is (is-duck-typed-struct? dt1))
(is (is-duck-typed-struct? dt2))
(is (is-duck-typed-struct? dt3))
(is (is-duck-typed-struct? dt4))
(is (not (is-duck-typed-struct? not-dt1)))
(is (not (is-duck-typed-struct? not-dt2)))
(is (not (is-duck-typed-struct? not-dt3)

--~--~-~--~~~---~--~~
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: Redefining Special Forms

2009-09-18 Thread Constantine Vetoshev

On Sep 17, 2:55 pm, Chouser chou...@gmail.com wrote:
 In a new thread, vars always start with their root binding.

 There's an ongoing discussion about the best way to provide
 other options when this is not the desired behavior:

 http://www.assembla.com/spaces/clojure/tickets/170-bound-fn-macro

That discussion implies that code on a different thread has to
explicitly ask for other threads' bindings. Is there a way to provide
some kind of inherited-binding macro, which works just like binding
but allows all threads started within its scope to automatically have
access to variables it has bound?

As icing on the cake, I'd like to allow binding and inherited-binding
to create new variables with dynamic extent. Right now, binding always
has to rebind previously def'ed or declare'd variables. This change
would allow applying the power of dynamic variables in a more targeted
manner, and make them less like glorified globals.
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



Correct idiom for looping inside a catch or finally form?

2009-09-13 Thread Constantine Vetoshev

I have some code which opens a bunch of resources (say, files), and
needs to make sure they all get closed. Something like this:

(let [files (atom [])]
  (try
   (open-my-many-files files)
   ;; the files atom now refers to a vector of open file handles
   (do-dangerous-io @files)
   (finally
(doseq [file @files]
  (.close file)

The Clojure compiler does not like this:
  error: java.lang.UnsupportedOperationException: Cannot recur from
catch/finally

Does Clojure have a lower-level iteration primitive than loop and
recur, which I can use inside exception handling code? I can obviously
put a letfn inside the finally and use good old recursion, but I feel
uncomfortable doing this without TCO. (Yes, I know I'm likely to run
out of file descriptors before I run out of available stack frames,
but this is still the wrong way to do things.) I would also very much
prefer not to have to write and call out to Java helper classes for
something as trivial as a loop.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Correct idiom for looping inside a catch or finally form?

2009-09-13 Thread Constantine Vetoshev

Apparently I oversimplified my example. In reality, I am trying to
deal with a bunch of open Berkeley DB cursors which I need to combine.
They cannot be processed serially. I need to ensure that all those
cursors close at the end even if an exception occurs, so I need to
loop over the resulting list or vector of open cursor handles. This
list happens to be stored in an atom, but that is completely
irrelevant to the problem I am trying to resolve: Clojure does not
seem to support iteration inside catch or finally forms.

Thanks,
CV

On Sep 13, 5:09 pm, Kevin Downey redc...@gmail.com wrote:
 you are using an atom as a temporary variable. please don't do that.

 (doseq [f files]
   (with-open [of (open-file f)]
     (do-dangerous-io of)))

 On Sun, Sep 13, 2009 at 1:05 PM, Constantine Vetoshev



 gepar...@gmail.com wrote:

  I have some code which opens a bunch of resources (say, files), and
  needs to make sure they all get closed. Something like this:

  (let [files (atom [])]
   (try
    (open-my-many-files files)
    ;; the files atom now refers to a vector of open file handles
    (do-dangerous-io @files)
    (finally
     (doseq [file @files]
       (.close file)

  The Clojure compiler does not like this:
   error: java.lang.UnsupportedOperationException: Cannot recur from
  catch/finally

  Does Clojure have a lower-level iteration primitive than loop and
  recur, which I can use inside exception handling code? I can obviously
  put a letfn inside the finally and use good old recursion, but I feel
  uncomfortable doing this without TCO. (Yes, I know I'm likely to run
  out of file descriptors before I run out of available stack frames,
  but this is still the wrong way to do things.) I would also very much
  prefer not to have to write and call out to Java helper classes for
  something as trivial as a loop.

 --
 And what is good, Phaedrus,
 And what is not good—
 Need we ask anyone to tell us these things?
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Correct idiom for looping inside a catch or finally form?

2009-09-13 Thread Constantine Vetoshev

On Sep 13, 11:18 pm, Richard Newman holyg...@gmail.com wrote:
 I think the OP's issue was that he has a sequence of things to close,  
 determined at runtime. with-open itself is no use there, because the  
 things to close must be known at compile-time.

Exactly.

 He is correct that finally and catch do not permit iteration. They do  
 permit function calls, hence my workaround.

Thank you, Richard. Your suggestion works.
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



Inheriting Clojure special variables in child threads

2009-08-18 Thread Constantine Vetoshev

Clojure's binding form only establishes vars with dynamic extent
limited to the current thread. This makes a lot of sense. However, I
have a use case where I'd like it to establish the dynamic extent in a
way which affects the current thread and all threads started within
the current thread.

Suppose, for example, that I want to launch a couple of different
instances of the embedded Jetty server. I have no control over what
threads Jetty starts and stops, but I want to make sure that my code
running inside that entire instance has a specific global variable
binding:

(declare *x*)

(binding* [*x* 3]
  (start-jetty :port 8001 :my-servlet servlet-implemented-in-clojure))

(binding* [*x* 5]
  (start-jetty :port 8002 :my-servlet servlet-implemented-in-clojure))

That way, code I wrote to run inside of Jetty can blindly refer to
*x*, and the first instance would then use the value 3, and the second
instance would use the value 5. Basically, I'd like a binding* macro
to establish a dynamic binding visible only in thread hierarchies
started in its scope.

Aside from the utility in my use case, I think a binding* macro like
this would improve the current concurrency situation, where any thread
can alter a def'ed global variable for any other thread. If the thread
starts in a binding*, it would, at worst, affect itself and its
children. Seems useful.

Any comments? Is this possible? How difficult would this be to
implement?

Best regards,
Constantine Vetoshev

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