Re: Closure for object pattern? A good idea?

2016-12-10 Thread Didier
Logan's point about being able to add new functions on a stopwatch is 
valid. That's often the argument to why protocols are better then classic 
OO. Though I still feel like in some scenarios, I think this is a good 
pattern, and can serve us better, the stopwatch being one good example.

Nothing in the pattern necessitate this to be mutable either, though I 
guess this pattern does seem to have some of its advantages from when you 
need mutability for some reason. Then I like how it isolates the mutable 
data behind the functionality.

It feels like a lighter weight version of both OO and protocols/records. 
I'm curious to benchmark it against records, which is what I would have 
used before for something like a stopwatch.

I think this could come in handy when doing libraries with options. My 
current pattern was to have a function create an options, and then the user 
would need to manage the options map, and pass it to all my library 
functions. Or I would use a var instead the library to store the options 
map, and offer it as a binding so users could rebind their own options. The 
problem with the latter is that you can't run the library with two 
different option set at the same time, while the former forces you to have 
to manage an options map and pass it around everywhere. So I feel there's 
something I could do here, with wrapping everything in this pattern, and 
having the options be captured in the closure.

On Friday, 9 December 2016 23:47:34 UTC-8, Didier wrote:
>
> I'm wondering what everyone thinks of using closures to mimic a simplistic 
> object system in Clojure? I'm not sure what to think of it yet, but the 
> idea is that you wrap object fields inside a closed function, and it 
> returns a map of methods that operates over those fields.
>
> Here's an example of using this pattern to implement a StopWatch:
>
> (import [java.lang System])
> (defn new-stopwatch []
>   (let [start-time (atom nil)
> elapsed (atom 0)]
> {:start (fn []
>   (when (nil? @start-time)
> (reset! start-time (System/currentTimeMillis
>  :stop (fn []
>  (when-not (nil? @start-time)
>(reset! elapsed
>(+ @elapsed
>   (- (System/currentTimeMillis) @start-time)))
>(reset! start-time nil))
>  @elapsed)
>  :reset (fn []
>   (reset! start-time nil)
>   (reset! elapsed 0)
>   @elapsed)
>  :elapsed (fn []
> (if-not (nil? @start-time)
> (- (System/currentTimeMillis) @start-time)
> @elapsed))}))
>
> (let [sw1 (new-stopwatch)
>   sw2 (new-stopwatch)]
>   ((:start sw1))
>   ((:start sw2))
>   (Thread/sleep 100)
>   ((:reset sw1))
>   ((:start sw1))
>   (println (str "Elapsed for SW1: " ((:elapsed sw1
>   (println (str "Elapsed for SW2: " ((:elapsed sw2
>   (Thread/sleep 100)
>   (println (str "SW1: " ((:stop sw1
>   (println (str "SW2: " ((:stop sw2)
>
> I find for certain things, like a stopwatch, this pattern is actually 
> pretty nice. I can't think of any alternative way to do this in Clojure 
> that I'd like better actually.
>
> What are your thoughts?
>

-- 
You 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: ava.lang.SecurityException: class "org.apache.poi.POIXMLDocumentPart"'s signer information does not match signer information of other classes in the same package

2016-12-10 Thread larry google groups
Not sure how to exclude an imported Java class?

lein deps :tree
Possibly confusing dependencies found:
[lein-checkall "0.1.1"] -> [jonase/eastwood "0.0.2"] -> 
[org.clojure/tools.namespace "0.1.2"]
 overrides
[lein-checkall "0.1.1"] -> [lein-kibit "0.0.8"] -> [jonase/kibit "0.0.8"] 
-> [org.clojure/tools.namespace "0.2.1"]
 and
[lein-checkall "0.1.1"] -> [lein-bikeshed "0.1.3"] -> 
[org.clojure/tools.namespace "0.2.3"]

Consider using these exclusions:
[lein-checkall "0.1.1" :exclusions [org.clojure/tools.namespace]]
[lein-checkall "0.1.1" :exclusions [org.clojure/tools.namespace]]

Retrieving org/clojure/tools.nrepl/0.2.12/tools.nrepl-0.2.12.pom from 
central
Retrieving 
clojure-complete/clojure-complete/0.2.4/clojure-complete-0.2.4.pom from 
clojars
Retrieving org/clojure/tools.nrepl/0.2.12/tools.nrepl-0.2.12.jar from 
central
Retrieving 
clojure-complete/clojure-complete/0.2.4/clojure-complete-0.2.4.jar from 
clojars
 [clj-stacktrace "0.2.7"]
 [clj-time "0.6.0"]
   [joda-time "2.2"]
 [clojure-complete "0.2.4" :exclusions [[org.clojure/clojure]]]
 [com.taoensso/timbre "4.3.1"]
   [com.taoensso/encore "2.36.2"]
 [com.taoensso/truss "1.1.1"]
 [org.clojure/tools.reader "0.10.0"]
   [io.aviso/pretty "0.1.23"]
 [dire "0.5.4"]
   [org.clojure/core.incubator "0.1.3"]
   [robert/hooke "1.3.0"]
 [expectations "2.0.9"]
   [junit "4.8.1"]
 [javax.xml.stream/stax-api "1.0-2"]
 [me.raynes/fs "1.4.4"]
   [org.apache.commons/commons-compress "1.4"]
 [org.tukaani/xz "1.0"]
 [org.apache.poi/poi-ooxml "3.9"]
   [dom4j "1.6.1"]
   [org.apache.poi/poi-ooxml-schemas "3.9"]
 [org.apache.xmlbeans/xmlbeans "2.3.0"]
   [stax/stax-api "1.0.1"]
 [org.apache.poi/poi "3.9"]
   [commons-codec "1.5"]
 [org.clojure/clojure "1.7.0"]
 [org.clojure/data.xml "0.1.0-beta1"]
 [org.clojure/test.check "0.9.0"]
 [org.clojure/tools.nrepl "0.2.12" :exclusions [[org.clojure/clojure]]]
 [org.eclipse.birt.runtime "4.2.2"]
   [commons-cli "1.0"]
 [commons-lang "1.0"]
 [commons-logging "1.0"]
   [milyn/flute "1.3"]
   [org.eclipse.birt.runtime.3_7_1/Tidy "1"]
   [org.eclipse.birt.runtime.3_7_1/com.lowagie.text "2.1.7"]
   [org.eclipse.birt.runtime.3_7_1/derby "10.5.101"]
   [org.eclipse.birt.runtime.3_7_1/javax.wsdl "1.5.1"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.bridge "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.css "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.dom.svg "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.dom "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.ext.awt "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.parser "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.pdf "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.svggen "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.transcoder "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.util.gui "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.util "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.batik.xml "1.6.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.commons.codec "1.3.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.xerces "2.9.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.xml.resolver "1.2.0"]
   [org.eclipse.birt.runtime.3_7_1/org.apache.xml.serializer "2.7.1"]
   [org.eclipse.birt.runtime.3_7_1/org.mozilla.javascript "1.7.2"]
   [org.eclipse.birt.runtime.3_7_1/org.w3c.css.sac "1.3.0"]
   [org.eclipse.birt.runtime.3_7_1/org.w3c.dom.smil "1.0.0"]
   [org.eclipse.birt.runtime.3_7_1/org.w3c.dom.svg "1.1.0"]
   [org.eclipse.birt.runtime/com.ibm.icu "4.4.2.v20110823"]
   [org.eclipse.birt.runtime/javax.xml.stream "1.0.1.v201004272200"]
   [org.eclipse.birt.runtime/org.apache.commons.logging 
"1.0.4.v201101211617"]
   [org.eclipse.birt.runtime/org.eclipse.core.contenttype 
"3.4.200.v20120523-2004"]
   [org.eclipse.birt.runtime/org.eclipse.core.expressions 
"3.4.401.v20120912-155018"]
   [org.eclipse.birt.runtime/org.eclipse.core.filesystem 
"1.3.200.v20130115-145044"]
   [org.eclipse.birt.runtime/org.eclipse.core.jobs 
"3.5.300.v20120912-155018"]
   [org.eclipse.birt.runtime/org.eclipse.core.resources 
"3.8.1.v20121114-124432"]
   [org.eclipse.birt.runtime/org.eclipse.core.runtime 
"3.8.0.v20120912-155025"]
  
 
[org.eclipse.birt.runtime/org.eclipse.datatools.connectivity.apache.derby.dbdefinition
 
"1.0.2.v201107221459"]
  
 [org.eclipse.birt.runtime/org.eclipse.datatools.connectivity.apache.derby 
"1.0.103.v201212070447"]
  
 [org.eclipse.birt.runtime/org.eclipse.datatools.connectivity.console.profile 
"1.0.10.v201109250955"]
   [org.eclipse.birt.runtime/org.eclipse.datatools.connectivity.db.generic 
"1.0.1.v201107221459"]
  
 
[org.eclipse.birt.runtime/org.eclipse.datatools.connectivity.dbdefinition.genericJDBC
 
"1.0.1.v201107221459"]
  
 [org.eclipse.birt.runtime/org.eclipse.datatools.connectivity.oda.consumer 
"3.2.5.v201109151100"]
   

ava.lang.SecurityException: class "org.apache.poi.POIXMLDocumentPart"'s signer information does not match signer information of other classes in the same package

2016-12-10 Thread larry google groups
I've never worked much with Java, so dealing with stuff like Maven is the 
stuff I understand least about Clojure. 

I've added these 3 items to the dependencies that I list in project.clj


 [org.apache.poi/poi "3.9"]   
 [org.apache.poi/poi-ooxml "3.9"]
 [org.eclipse.birt.runtime/org.eclipse.birt.runtime "4.2.2"]

When I run "lein uberjar" I get this: 

java.lang.SecurityException: class "org.apache.poi.POIXMLDocumentPart"'s 
signer information does not match signer information of other classes in 
the same package

How do I get around 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
--- 
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: "lein uberjar" gives me java.lang.OutOfMemoryError:

2016-12-10 Thread larry google groups
I seem to get around this by increasing:

  :jvm-opts ["-Xms300m" "-Xmx300m" "-XX:-UseCompressedOops"])

Is that possible? I didn't realize that effected "lein uberjar" I thought 
it only effected my app when my app was running. 




On Saturday, December 10, 2016 at 11:37:44 PM UTC-5, larry google groups 
wrote:
>
> I had a small app that was compelling, and then I added in a java class, 
> and now when I run "lein uberjar" I get  java.lang.OutOfMemoryError.
>
> I'm working on my MacBook Pro, 16 gigs of memory
>
> Dependencies were: 
>
>
>   :dependencies [
>  [org.clojure/clojure "1.7.0"]
>  [com.taoensso/timbre "4.3.1"]
>  [dire "0.5.4"]
>  [slingshot "0.12.2"]
>  [clj-time "0.6.0"]
>  [org.clojure/test.check "0.9.0"]
>  [me.raynes/fs "1.4.4"]
>  [clj-stacktrace "0.2.7"] 
>  [sax/sax "2.0.1"]
>  [xml-apis/xml-apis "2.0.2"]
>  [javax.xml.stream/stax-api "1.0-2"]
>  [overtone/at-at "1.2.0"]
>  [org.clojure/data.xml "0.1.0-beta1"]
>
>  [org.apache.poi/poi "3.9"]   
>  [org.apache.poi/poi-ooxml "3.9"]
>  ]
>
> And the above compiled, but then I added: 
>
>  [org.eclipse.birt.runtime/org.eclipse.birt.runtime 
> "4.2.2"]
>
> And that was about when things fell apart. 
>
> In my project.clj I also have: 
>
>   :source-paths  ["src/clojure"]
>   :java-source-paths ["src/java"]
>
> And I have added one Java file to src/java:
>
> package com.heddy.excel_to_csv;
>
>
> import java.io.InputStream;
> import java.util.Iterator;
> import java.util.LinkedHashMap;
> import java.util.Map;
>
> import org.apache.poi.openxml4j.opc.PackageAccess;
> import org.apache.poi.xssf.eventusermodel.XLSX2CSV;
> import org.apache.poi.xssf.eventusermodel.XSSFReader;
> import org.apache.poi.xssf.model.SharedStringsTable;
> import org.apache.poi.xssf.usermodel.XSSFRichTextString;
> import org.apache.poi.openxml4j.opc.OPCPackage;
> import org.xml.sax.Attributes;
> import org.xml.sax.ContentHandler;
> import org.xml.sax.InputSource;
> import org.xml.sax.SAXException;
> import org.xml.sax.XMLReader;
> import org.xml.sax.helpers.DefaultHandler;
> import org.xml.sax.helpers.XMLReaderFactory;
>
>
> public class SheetHandler extends DefaultHandler {
> private SharedStringsTable sst;
> private String lastContents;
> private boolean nextIsString;
> private SheetHandler(SharedStringsTable sst) {
> this.sst = sst;
> }
> public void startElement(String uri, String localName, String name,
>  Attributes attributes) throws SAXException {
> // c => cell
> if(name.equals("c")) {
> // Print the cell reference
> System.out.print(attributes.getValue("r") + " - ");
> // Figure out if the value is an index in the SST
> String cellType = attributes.getValue("t");
> if(cellType != null && cellType.equals("s")) {
> nextIsString = true;
> } else {
> nextIsString = false;
> }
> }
> // Clear contents cache
> lastContents = "";
> }
> public void endElement(String uri, String localName, String name)
> throws SAXException {
> // Process the last contents as required.
> // Do now, as characters() may be called more than once
> if(nextIsString) {
> int idx = Integer.parseInt(lastContents);
> lastContents = new 
> XSSFRichTextString(sst.getEntryAt(idx)).toString();
> nextIsString = false;
> }
>
> // v => contents of a cell
> // Output after we've seen the string contents
> if(name.equals("v")) {
> System.out.println(lastContents);
> }
> }
>
> public void characters(char[] ch, int start, int length)
> throws SAXException {
> lastContents += new String(ch, start, length);
> }
> }
>
> I have never used a Java file like this before, so I wasn't sure how to 
> proceed. I invented the "package" name, which could be all wrong. 
>
> I've stolen the Java code from here: 
>
>
> https://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java
>
> Any thoughts why I would get an OutOfMemory?
>
>
>
>
>
>
>

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

"lein uberjar" gives me java.lang.OutOfMemoryError:

2016-12-10 Thread larry google groups
I had a small app that was compelling, and then I added in a java class, 
and now when I run "lein uberjar" I get  java.lang.OutOfMemoryError.

I'm working on my MacBook Pro, 16 gigs of memory

Dependencies were: 


  :dependencies [
 [org.clojure/clojure "1.7.0"]
 [com.taoensso/timbre "4.3.1"]
 [dire "0.5.4"]
 [slingshot "0.12.2"]
 [clj-time "0.6.0"]
 [org.clojure/test.check "0.9.0"]
 [me.raynes/fs "1.4.4"]
 [clj-stacktrace "0.2.7"] 
 [sax/sax "2.0.1"]
 [xml-apis/xml-apis "2.0.2"]
 [javax.xml.stream/stax-api "1.0-2"]
 [overtone/at-at "1.2.0"]
 [org.clojure/data.xml "0.1.0-beta1"]

 [org.apache.poi/poi "3.9"]   
 [org.apache.poi/poi-ooxml "3.9"]
 ]

And the above compiled, but then I added: 

 [org.eclipse.birt.runtime/org.eclipse.birt.runtime "4.2.2"]

And that was about when things fell apart. 

In my project.clj I also have: 

  :source-paths  ["src/clojure"]
  :java-source-paths ["src/java"]

And I have added one Java file to src/java:

package com.heddy.excel_to_csv;


import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.xssf.eventusermodel.XLSX2CSV;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;


public class SheetHandler extends DefaultHandler {
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
private SheetHandler(SharedStringsTable sst) {
this.sst = sst;
}
public void startElement(String uri, String localName, String name,
 Attributes attributes) throws SAXException {
// c => cell
if(name.equals("c")) {
// Print the cell reference
System.out.print(attributes.getValue("r") + " - ");
// Figure out if the value is an index in the SST
String cellType = attributes.getValue("t");
if(cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}
// Clear contents cache
lastContents = "";
}
public void endElement(String uri, String localName, String name)
throws SAXException {
// Process the last contents as required.
// Do now, as characters() may be called more than once
if(nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = new 
XSSFRichTextString(sst.getEntryAt(idx)).toString();
nextIsString = false;
}

// v => contents of a cell
// Output after we've seen the string contents
if(name.equals("v")) {
System.out.println(lastContents);
}
}

public void characters(char[] ch, int start, int length)
throws SAXException {
lastContents += new String(ch, start, length);
}
}

I have never used a Java file like this before, so I wasn't sure how to 
proceed. I invented the "package" name, which could be all wrong. 

I've stolen the Java code from here: 

https://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java

Any thoughts why I would get an OutOfMemory?






-- 
You 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: Closure for object pattern? A good idea?

2016-12-10 Thread James Reeves
You don't need mutability to represent a stopwatch.

  (defn start [stopwatch]
(assoc stopwatch ::start-time (System/currentTimeMillis)))

  (defn elapsed-since-started [stopwatch]
(- (System/currentTimeMillis) (::start-time stopwatch)))

  (defn stop [stopwatch]
(-> stopwatch
(dissoc ::start-time)
(update ::elapsed (fnil + 0)
  (elapsed-since-started stopwatch

  (defn elapsed [stopwatch]
(::elapsed (stop stopwatch) 0)

  (defn reset [stopwatch]
(dissoc stopwatch ::start-time ::elapsed))

Mutability is typically only necessary for two reasons:

1. Communication across threads
2. Performance

- James

On 10 December 2016 at 07:47, Didier  wrote:

> I'm wondering what everyone thinks of using closures to mimic a simplistic
> object system in Clojure? I'm not sure what to think of it yet, but the
> idea is that you wrap object fields inside a closed function, and it
> returns a map of methods that operates over those fields.
>
> Here's an example of using this pattern to implement a StopWatch:
>
> (import [java.lang System])
> (defn new-stopwatch []
>   (let [start-time (atom nil)
> elapsed (atom 0)]
> {:start (fn []
>   (when (nil? @start-time)
> (reset! start-time (System/currentTimeMillis
>  :stop (fn []
>  (when-not (nil? @start-time)
>(reset! elapsed
>(+ @elapsed
>   (- (System/currentTimeMillis) @start-time)))
>(reset! start-time nil))
>  @elapsed)
>  :reset (fn []
>   (reset! start-time nil)
>   (reset! elapsed 0)
>   @elapsed)
>  :elapsed (fn []
> (if-not (nil? @start-time)
> (- (System/currentTimeMillis) @start-time)
> @elapsed))}))
>
> (let [sw1 (new-stopwatch)
>   sw2 (new-stopwatch)]
>   ((:start sw1))
>   ((:start sw2))
>   (Thread/sleep 100)
>   ((:reset sw1))
>   ((:start sw1))
>   (println (str "Elapsed for SW1: " ((:elapsed sw1
>   (println (str "Elapsed for SW2: " ((:elapsed sw2
>   (Thread/sleep 100)
>   (println (str "SW1: " ((:stop sw1
>   (println (str "SW2: " ((:stop sw2)
>
> I find for certain things, like a stopwatch, this pattern is actually
> pretty nice. I can't think of any alternative way to do this in Clojure
> that I'd like better actually.
>
> What are your thoughts?
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

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


Re: Index of an element in a vector of vectors

2016-12-10 Thread Tyler Perkins
Don't know what you mean about "swapping", but here's a solution that 
generalizes to a tree of any finite depth, where each node is either a leaf 
element or a seqable (say, a vector) of any length:

(defn coord-of

  ([elems target]
   (coord-of elems target []))

  ([elems target indexes]
   (first (keep-indexed
(fn [i x]
  (cond
(= x target)  (conj indexes i)
(seqable? x)  (coord-of x target (conj indexes i
elems

Then, for example,

cljs.user=> (coord-of [[] 11 [1 2 3] [4 5 6]] 5)
[3 1]
cljs.user=> (coord-of [[] 11 [1 2 3] [4 5 6]] 55)
nil

-- 
You 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: Closure for object pattern? A good idea?

2016-12-10 Thread Logan Buckley
I feel like you would be better off separating functions from the data they 
operate on here. In this case, you could represent the state of a stopwatch 
with a map containing the start time and the time elapsed, and have 
functions `stop`, `reset`, `start`, etc that take the stopwatch data 
structure as an argument and compute an answer or return a new stopwatch 
data structure as needed. If you need to share the state of the stopwatch 
you can always put that map in an atom when you need to.

This has the additional benefit that you can implement new functions on the 
stopwatch without changing the implementation stopwatch data structure 
itself, while in the case of the closure you need to change the 
implementation of `new-stopwatch` if you want to be able to do anything 
else with the stopwatch data - sort of the same rationale for 
clojure.core's extensive use of functions that operate on seqs instead of 
many specialized data structures.

You don't gain much by storing the state in a closure unless you need to 
guarantee that the user of your code can't access it, which with immutable 
data structures isn't often necessary.

-Logan


On Saturday, December 10, 2016 at 2:47:34 AM UTC-5, Didier wrote:
>
> I'm wondering what everyone thinks of using closures to mimic a simplistic 
> object system in Clojure? I'm not sure what to think of it yet, but the 
> idea is that you wrap object fields inside a closed function, and it 
> returns a map of methods that operates over those fields.
>
> Here's an example of using this pattern to implement a StopWatch:
>
> (import [java.lang System])
> (defn new-stopwatch []
>   (let [start-time (atom nil)
> elapsed (atom 0)]
> {:start (fn []
>   (when (nil? @start-time)
> (reset! start-time (System/currentTimeMillis
>  :stop (fn []
>  (when-not (nil? @start-time)
>(reset! elapsed
>(+ @elapsed
>   (- (System/currentTimeMillis) @start-time)))
>(reset! start-time nil))
>  @elapsed)
>  :reset (fn []
>   (reset! start-time nil)
>   (reset! elapsed 0)
>   @elapsed)
>  :elapsed (fn []
> (if-not (nil? @start-time)
> (- (System/currentTimeMillis) @start-time)
> @elapsed))}))
>
> (let [sw1 (new-stopwatch)
>   sw2 (new-stopwatch)]
>   ((:start sw1))
>   ((:start sw2))
>   (Thread/sleep 100)
>   ((:reset sw1))
>   ((:start sw1))
>   (println (str "Elapsed for SW1: " ((:elapsed sw1
>   (println (str "Elapsed for SW2: " ((:elapsed sw2
>   (Thread/sleep 100)
>   (println (str "SW1: " ((:stop sw1
>   (println (str "SW2: " ((:stop sw2)
>
> I find for certain things, like a stopwatch, this pattern is actually 
> pretty nice. I can't think of any alternative way to do this in Clojure 
> that I'd like better actually.
>
> What are your thoughts?
>

-- 
You 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: Thoughts on clojure.spec

2016-12-10 Thread Ben Brinckerhoff
I would certainly welcome and use an `overinstrument` function if added to 
schpec (or another library).

One reason spec is great because it provides "a la carte" validation: a can 
add an appropriate amount of validation to the parts of my code that would 
most benefit from it. In my experience using spec so far, optionally 
running `fn` and `ret` specs during instrumentation would give me more 
options to pick the correct amount of validation.

For instance, since side-effecting functions are harder to unit test (and 
difficult to test generatively), I would like to spec the functions and 
then run integration tests. Running `ret`/`fn` specs would help me detect 
errors closer to their source and also confirm the specs are accurate, 
which improves the value specs as documentation. In my current project, I 
have been avoiding writing `ret` specs for side-effecting functions because 
I worry they'll get out-of-sync and mislead other programmers.

Also, having `ret`/`fn` specs checked during instrumentation would add 
value during development when I'm not yet ready to build generative tests. 
For example, during early development of a function, I might just spec a 
parameter with `map?` even though it actually requires certain keys. That 
spec far too vague for generative testing, but immediately adds value when 
I turn on instrumentation, since it catches bugs where I've passed, say, 
`nil` as the parameter. When the feature is more stable, I can invest the 
time in creating a generator and running generative tests. With the current 
implementation of `instrument`, I find that I've been tempted to over-spec 
early in development in order to get working generative tests that will 
confirm my `ret` and `fn` specs are correct.

I understand Rich and Alex have thought all this through and have provided 
a detailed rationale for the current behavior. But in my own workflow, 
being able to turn on `ret`/`fn` specs during instrumentation would be a 
big help, and I'd very much like to see this feature added to schpec. I'm 
happy to look at this when my schedule allows (not this week or next due to 
travel). Perhaps the best approach is to add an `over-instrument` function 
that has options for turning on/off `args`, `fn`, and `ret` specs (enabling 
all by default) and see how people use it in practice?

Thanks to everyone who have worked so hard on all aspects of spec!
Ben










On Tuesday, December 6, 2016 at 4:42:44 PM UTC-7, Brandon Bloom wrote:
>
> I was just very surprised to discover my :ret specs were not being checked 
> via instrument. I've read the rationale above, but I'm not yet convinced. 
> While of course I can (and will) use spec/assert from a post condition, I 
> lose the nice selective instrumentation features.
>
> I'd also like to make a counter-point to this reasoning:
>  
>
>> Running return-value instrument-style checking on whatever few 
>> hand-written tests you might have isn’t going to give you better coverage 
>> than a simple (even hardwired) generator that captures similar ranges.
>
>
> In my case, I was already testing the root-level return value, but this 
> function is deeply recursive. A small non-conforming value deep in the 
> evaluation stack was yielding non-conformance at a path deep in the root 
> return value. I was confused by why the :ret check wasn't finding it 
> earlier. By relying on the top-level check rather than inline checks 
> per-call (as per instrument or :pre/:post) I lost access to the call stack. 
> Adding the post condition pin-pointed the problem instantly.
>

-- 
You 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] Odin 0.2.0 - Query DSL for Clojure

2016-12-10 Thread Timothy Baldridge
I just released the first official version of Odin (
https://github.com/halgari/odin). Odin is a declarative, extensible query
DSL for Clojure that leverages transducers to provide a high amount of
generality while still maintaining acceptable performance.

One of the biggest features of Odin is its ability to rapidly index and
query "normal" Clojure data structures. Here is a quick example of this
feature in practice:

(let [orders [{:customer/name "Sam"
   :customer/id   3411}
  {:customer/id 3411
   :order/items {1212 3}}
  {:customer/id 3411
   :order/items {2232 2 4242 3}}
  {:item/id1212
   :item/price 40.0}
  {:item/id2232
   :item/price 100}
  {:item/id4242
   :item/price 1.99}]]
  (->> (o/for-query
 (o/and
   (d/query orders ?customer :customer/name "Sam")
   (d/query orders ?customer :customer/id ?id)
   (d/query orders ?order :customer/id ?id)
   (d/query-in orders ?order [:order/items ?item-id] ?qty)
   (d/query orders ?item :item/id ?item-id)
   (d/query orders ?item :item/price ?price))
 (* ?qty ?price))
   (reduce + 0)))

;; => 325.97


In this example we are given a vector of maps, we are then finding a
customer by name,

then walking a path through the data to find all the items that
customer ordered, the

total price is then calculated via the normal multiply and sum.


There are several other features supported by Odin, including
transformation of data

(based on a query), tabling, Datomic support, and much more.


I also did a video series on the development process of Odin if anyone
is interested:
(https://www.youtube.com/watch?v=JyKySmcTR4g)

-- 
You 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: Spec of conform of spec

2016-12-10 Thread James Laver
This is exactly my use case as well. I want to provide the user a nice DSL 
but make it easy to automatically generate input. The idea I had was the 
user could write things in the DSL and for automatic generation you could 
just generate the conformed structure.

The other thing it's made me notice is that we really need a library to 
make errors clearer in large nested data structures.

/j

On Saturday, December 10, 2016 at 3:09:24 AM UTC+1, Leon Grapenthin wrote:
>
> Alex, I thought about this and it appears to be a convenience problem. 
> Spec is e. g. excellent to parse a e. g. a Query DSL (which is my current 
> side project) via conform. But then you have that large data structure that 
> you want to break down and operate on in several functions. So you need to 
> have the specs for the conformed structure built by spec. 
>
>>

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