Anyone spent time with Kawa Scheme?

2018-04-02 Thread 'somewhat-functional-programmer' via Clojure
I've recently come across Kawa Scheme and am very intrigued by it.  It's Java 
integration is superb like Clojure and it's very fast.  Has anyone here used it 
to build something?

So far I've only tried it with small toy programs.  Things I like about it:
  - Starts up very quickly
  - Java method notation lends itself to auto-complete
 (instance:method param1 param2)
  - Can pre-compile and use it on Android
  - Repl has line numbers so compilation errors on repl forms have source lines

Maybe Kawa fits into a niche that Clojure leaves open with its heavier runtime? 
 Maybe I'm just trying toy programs and those toy programs are fast? :-)

One thing that intrigues me here though since java integration is so easy with 
Kawa is the notion of using Clojure's immutable data structures from Kawa -- 
maybe even making a clojure "core" library for use from Kawa.

-lc

-- 
You 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: Anyone spent time with Kawa Scheme?

2018-04-03 Thread 'somewhat-functional-programmer' via Clojure
Thank you for posting these video links along with the time markers.  I thought 
I'd enjoyed all of Rich Hickey's presentations before but I actually hadn't 
seen his "Clojure for Lisp Programmers".  Clojure is the only lisp I "know" 
(still relatively a beginner) but have been fortunate enough to use full-time 
for the last few years -- given my Java background, I naturally had started 
with his "Clojure for Java Programmers".

I did not intend to suggest that Clojure should have been a library to a Scheme 
or Common Lisp.  I love the language as it is and not having a prior lisp 
background, absolutely appreciated watching the "Clojure for Lisp Programmers" 
(as now having some lisp experience, I could more fully appreciate some of 
Clojure's roots).  I've dabbled with toy programs in both ABCL/SBCL as well as 
Kawa mostly out of curiosity.

My reasons for asking my questions about other people's use of Kawa is that the 
performance characteristics of its runtime made me think maybe it may be 
applicable to some areas where Clojure may be a tougher choice (Android, CLI 
utilities).  I think Clojure startup time correlates with how many vars 
defined, and startup time of my projects increases with var counts.  I'm 
curious if any more thought has gone into this topic on the wiki: 
https://dev.clojure.org/pages/viewpage.action?pageId=950293.

I can't give up writing software in an immutable/functional style after using 
Clojure for a couple of years, and was starting to think about what a program 
using Kawa could look like using Clojure's immutable data structures and STM.

What I've settled into doing for using Clojure for CLI utilities thus far has 
been to just leave an instance running a socket repl on my machine always 
running and connect to it via rlwrap and socat (only using it interactively 
though):

rlwrap  socat STDIN TCP4:localhost:

Anyhow, thanks again for the video link, always a treat to watch a Rich Hickey 
Clojure talk that I hadn't seen before.

‐‐‐ Original Message ‐‐‐
On April 4, 2018 3:23 AM, 'André' via Clojure  wrote:

> They maybe relevant too:
>
> https://www.youtube.com/watch?v=2V1FtfBDsLU, around 1h4min
>
> On 04/03/2018 05:29 PM, 'André' via Clojure wrote:
>
>> Rich has covered some of the motivation of why not extending existing 
>> Lisp->Java integrations, like Kawa and ABCL:
>>
>> https://www.youtube.com/watch?v=cPNkH-7PRTk, around 3:25
>>
>> On 04/02/2018 05:53 PM, 'somewhat-functional-programmer' via Clojure wrote:
>>
>>> I've recently come across Kawa Scheme and am very intrigued by it.  It's 
>>> Java integration is superb like Clojure and it's very fast.  Has anyone 
>>> here used it to build something?
>>>
>>> So far I've only tried it with small toy programs.  Things I like about it:
>>>   - Starts up very quickly
>>>   - Java method notation lends itself to auto-complete
>>>  (instance:method param1 param2)
>>>   - Can pre-compile and use it on Android
>>>   - Repl has line numbers so compilation errors on repl forms have source 
>>> lines
>>>
>>> Maybe Kawa fits into a niche that Clojure leaves open with its heavier 
>>> runtime?  Maybe I'm just trying toy programs and those toy programs are 
>>> fast? :-)
>>>
>>> One thing that intrigues me here though since java integration is so easy 
>>> with Kawa is the notion of using Clojure's immutable data structures from 
>>> Kawa -- maybe even making a clojure "core" library for use from Kawa.
>>>
>>> -lc
>>>
>>> --
>>> You 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 

Re: Anyone spent time with Kawa Scheme?

2018-04-04 Thread 'somewhat-functional-programmer' via Clojure
Appreciate the response -- grench looks like a great way for me to continue to 
use my always-on repl in actual scripts and not just interactively.  I've 
lately ironically become more interested in Clojure startup time now than when 
I started developing with it because I'm starting to accumulate enough valuable 
snippets of code that I'd love to expose functions here and there from the 
command line.  What I'd started to move towards was interactively using the 
Clojure repl as more of a command shell than I'd ever had before (not just as a 
development support/workflow).  Grench looks perfect for driving things from 
bash/cron.  Also could be cool to deploy it with server side apps for O&M 
functionality -- peer into a running web app for instance and print out metrics 
for instance...

‐‐‐ Original Message ‐‐‐
On April 4, 2018 10:43 AM, Gary Trakhman  wrote:

> If you're looking for fast CLI utilities, ocaml can be a good fit, or 
> grenchman for loading clojure code, in this particular case (written in 
> ocaml): https://github.com/technomancy/grenchman
>
> You don't really need persistent data structures for those use-cases, do you? 
>  But it does have seqs and async pipes (like channels) etc. My employer uses 
> Jane St's core/async libs which bundle all that in a semi-coherent fashion.
>
> Any of those options might be a tradeoff for mindshare and cases covered, but 
> common lisp might also be a good choice.
>
> On Wed, Apr 4, 2018 at 12:35 AM 'somewhat-functional-programmer' via Clojure 
>  wrote:
>
>> Thank you for posting these video links along with the time markers.  I 
>> thought I'd enjoyed all of Rich Hickey's presentations before but I actually 
>> hadn't seen his "Clojure for Lisp Programmers".  Clojure is the only lisp I 
>> "know" (still relatively a beginner) but have been fortunate enough to use 
>> full-time for the last few years -- given my Java background, I naturally 
>> had started with his "Clojure for Java Programmers".
>>
>> I did not intend to suggest that Clojure should have been a library to a 
>> Scheme or Common Lisp.  I love the language as it is and not having a prior 
>> lisp background, absolutely appreciated watching the "Clojure for Lisp 
>> Programmers" (as now having some lisp experience, I could more fully 
>> appreciate some of Clojure's roots).  I've dabbled with toy programs in both 
>> ABCL/SBCL as well as Kawa mostly out of curiosity.
>>
>> My reasons for asking my questions about other people's use of Kawa is that 
>> the performance characteristics of its runtime made me think maybe it may be 
>> applicable to some areas where Clojure may be a tougher choice (Android, CLI 
>> utilities).  I think Clojure startup time correlates with how many vars 
>> defined, and startup time of my projects increases with var counts.  I'm 
>> curious if any more thought has gone into this topic on the wiki: 
>> https://dev.clojure.org/pages/viewpage.action?pageId=950293.
>>
>> I can't give up writing software in an immutable/functional style after 
>> using Clojure for a couple of years, and was starting to think about what a 
>> program using Kawa could look like using Clojure's immutable data structures 
>> and STM.
>>
>> What I've settled into doing for using Clojure for CLI utilities thus far 
>> has been to just leave an instance running a socket repl on my machine 
>> always running and connect to it via rlwrap and socat (only using it 
>> interactively though):
>>
>> rlwrap  socat STDIN TCP4:localhost:
>>
>> Anyhow, thanks again for the video link, always a treat to watch a Rich 
>> Hickey Clojure talk that I hadn't seen before.
>>
>> ‐‐‐ Original Message ‐‐‐
>> On April 4, 2018 3:23 AM, 'André' via Clojure  
>> wrote:
>>
>>> They maybe relevant too:
>>>
>>> https://www.youtube.com/watch?v=2V1FtfBDsLU, around 1h4min
>>>
>>> On 04/03/2018 05:29 PM, 'André' via Clojure wrote:
>>>
>>>> Rich has covered some of the motivation of why not extending existing 
>>>> Lisp->Java integrations, like Kawa and ABCL:
>>>>
>>>> https://www.youtube.com/watch?v=cPNkH-7PRTk, around 3:25
>>>>
>>>> On 04/02/2018 05:53 PM, 'somewhat-functional-programmer' via Clojure wrote:
>>>>
>>>>> I've recently come across Kawa Scheme and am very intrigued by it.  It's 
>>>>> Java integration is superb like Clojure and it's very fast.  H

Re: Anyone spent time with Kawa Scheme?

2018-04-04 Thread 'somewhat-functional-programmer' via Clojure
Appreciate the pointer towards Lumo and Planck -- I've tried Lumo though not 
Planck.  I have used Clojurescript at work (not for scripting but for webapps) 
and it's been more challenging for me only because I am not as familiar with 
the Javascript ecosystem as I am the Java ecosystem.

What I've been hoping to do though is leverage a lot of the JVM Clojure code 
I've written in small CLI utilities.  I find that the library overlap between 
my Clojure and Clojurescript code in my usage is mainly of the 
plumbing/infrastructure variety (which is most useful) -- like 
EDN/transit/Sente/Timbre/Specter rather than the meat of what my apps are 
actually doing server-side.

As I write this it's dawning on me I could just expose my JVM Clojure code as 
services and figure out how to use Clojurescript from node.js...  it just 
sounds so much more complicated to me at the moment than something like the 
previously mentioned grench or even just interactive repl use (for simply 
exposing a function that say translates CSV data to something else) (and 
annoying if I'm trying to specify a local file reference etc).

I've been fairly content with my own interactive repl use for these things 
(convert this CSV file etc), but I don't think it translates to non-clojure 
developers and when I hand over instructions/procedures to folks I work with 
I'd like to give them something simple they can run from bash etc.  That's 
really where a lot of the startup costs are killer, you give something with a 
10-20 second startup time over to other teams and it only justifies their 
hatred of the JVM (I'd never tell them it was Clojure then the cat would be out 
of the bag :-)).

Anyhow I appreciate the response -- thanks!

‐‐‐ Original Message ‐‐‐
On April 4, 2018 5:48 PM, Gary Johnson  wrote:

> If you haven't given it a try yet, Clojurescript is really the goto for a lot 
> of Clojure programmers when it comes to cover the CLI and Android use cases.
>
> Lumo and Planck are awesome Clojurescript runtimes that start up virtually 
> instantaneously and make great choices for writing scripts.
>
> Clojurescript + React Native can create apps for Android, iOS and Windows.
>
> Have fun and happy hacking!
>   Gary
>
> --
> You 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: Anyone spent time with Kawa Scheme?

2018-04-07 Thread 'somewhat-functional-programmer' via Clojure
Thanks -- I had seen some Clojure startup benchmarks in relation to Java 9: 
https://mjg123.github.io/2017/10/04/AppCDS-and-Clojure.html.  I did try these 
on one of my projects that uses a lot of Clojure library deps and I went from 
~11 second startup to ~5 (both were AOT/direct linking compiled).

I appreciate the discussion.  I think it's helped me think a little more 
clearly about what my goals/requirements are.  I started thinking about why 
I've chosen to use any JVM language over just plain Java.  After all, no JVM 
language is going to execute faster or have more support behind it than Java 
itself.  I won't enumerate all the reasons writing Java code is more painful 
than  code as the reasons are mostly personal per 
developer, and I'm guessing that most people here in this particular forum have 
already come to the same conclusion.

I'd love to know why people here have chosen Clojure.  Everyone chooses it for 
persistent data structures and functional programming, as Clojure essentially 
forces you to use them.  I've found structuring my code that way seems less 
prone to bugs and more reusable and compose-able.  However, with Java now 
having lambda functions it's possible to get *some* of the same advantages 
there.

For me the selling point of Clojure was the learning a lisp.  My motivation for 
wanting to learn a lisp, and the fact that Clojure was so perfectly practical I 
could potentially use it professionally (JVM!) started me down the path.  Where 
I hoped I would end up is leveraging macros.  I've always done a lot of code 
generation in my Java projects... from things like using templating languages 
to generate java source files to using annotations to generate additional java 
code at compile time.  What I've found with Clojure and macros is -- it's 
so much easier to do those same things.  I know there's a huge emphasis in 
the Clojure community (and maybe all lisps) of not over-using macros... and I'm 
not disagreeing with that.  But to me that's the heart of why I would ever use 
a lisp.

So finally full circle (back to Kawa)...  *my* primary benefit of Clojure could 
be summarized as "JVM + Macros" (which to me is orthogonal to the 
immutable/functional benefit - as it is possible to program this way in other 
languages, and I'd argue writing in Clojure/ usually 
limits projects to small teams of experts and on those types of teams it would 
be possible to be disciplined enough to do so in a language that doesn't force 
it).  Kawa has "JVM + Macros" (though at the moment I find scheme macros much 
less approachable than CL or Clojure macros).  It also has different 
development trade-offs, but the things I like:
  - Little to no overhead over plain Java
- I think this would make it sell-able in the enterprise world for 
*libraries* or *part* of a project.  Could a couple of experts using Kawa 
replace a lot of the code I used to generate in far more awful ways than macros 
(templates or annotation processors)?  If Kawa easily compiles to Java and has 
good code completion (i.e., not IFn passing Objects but actual static method 
definitions with types)...  I bet "regular" Java-based software projects 
wouldn't mind consuming libraries written in Kawa.  And if there wasn't a 10-20 
second startup penalty for using the library... (even though I know, in 
"situated" programs this really doesn't matter at all -- but it does from a 
language adoption standpoint.  I think I couldn't convince a project to let me 
write a library in Clojure if it took 20 seconds to load the library).
  - Still has macros and sexps
- I prefer Clojure's syntax to scheme (maybe just because I'm used to it).  
But it's really the same argument people have against using Clojure 
(parenthesis :-)).  Other low overhead JVM languages like Scala don't have 
macros.
  - I could still use Clojure's data structures and even STM from Kawa
- Clojure's runtime is very approachable and a beautiful piece of software 
(I don't even mind the Java source formatting -- reminds of C# actually -- why 
indent *everything* when the language says you must have a top level "form" 
(namespace in C# / class in Java? :-)).  Using its data structures and even STM 
would be very straightforward.

My motivations in writing here is to get people's feedback about using Kawa / 
other lisps when their main motivation is to stay in the JVM ecosystem.  I'd 
love to see both Kawa and Clojure be so easy to intertwine into a larger Java 
project that they could be used even within large enterprise-y Java projects 
(for some portion of the project).  My interest in that is mostly personal :-). 
 I think using them in this manner would be a real benefit to both those 
projects and to developers on them.  That's what gets me excited about Kawa -- 
I think I maybe I could sell it's use as a library in a large corporate project 
simply because there's no runtime overhead.

‐‐‐ Original Message ‐‐‐

On April 5, 2018 4:00 AM, 

Prototype code for enhanced CIDER code completion for Java methods

2018-10-11 Thread 'somewhat-functional-programmer' via Clojure
I'd like to share an idea and prototype code for better Java code completion in 
CIDER.  While my main development environment is CIDER, the small modifications 
I made to support this idea were both to cider-nrepl and compliment -- which 
are both used by other Clojure tooling besides CIDER -- so maybe this is 
immediately more widely applicable.

In an effort to make it easier on the tooling, I'm using a slightly different 
syntax for calling Java methods.  My inspiration is Kawa scheme, and the 
notation is very similar:

(String:charAt "my-string" 0) => \m
(Integer:parseInt "12") => 12
(possibly.fully.qualified.YourClassName:method this args)

For this syntax to be properly compiled of course it needs to be wrapped in a 
macro:

One form:
(jvm (String:charAt "my-string" 0))

Any number of forms:
(jvm
  (lots of code)
  (JavaClass:method ...)
  (more code)
  (AnotherJavaClass:method ...))

The jvm macro will transform any symbol it finds in the calling position of a 
list that follows the ClassName:method convention.  I was thinking maybe of 
limiting it to just a particular namespace to absolutely prevent any name 
collisions with real clojure functions, something like:

(jvm/String:charAt "my-string" 0)

This will also work with the one-off test code I'm including here for folks to 
see what they think.

I actually like the syntax (though I wish I didn't have to wrap it in a jvm 
macro -- though if this actually idea was worth fully implementing, I'd imagine 
having new let or function macros so you don't even have to sprinkle "jvm" 
macros in code much at all).

There is one additional advantages to this style of Java interop besides the 
far better code completion:
  - The jvm macro uses reflection to find the appropriate method at compile 
time, and as such, you get a compile error if the method cannot be found.
- This is a downside if you *want* reflection, but this of course doesn't 
preclude using the normal (.method obj args) notation.

You could even use this style for syntactic sugar for Java method handles:
  - Though not implemented in my toy code here, you could also pass 
String:charAt as a clojure function -- assuming there were no overloads of the 
same arity.

So, I'm hoping you will try this out.  Two things to copy/paste -- one is a 
boot command, the other is the 100-200 lines of clojure that implements a 
prototype of this.

This command pulls the necessary dependencies as well as starts up the 
rebel-readline repl (which is fantastic tool, and it also uses compliment for 
code completion):

# Run this somewhere where you can make an empty source directory,
# something fails in boot-tools-deps if you don't have one
#   (much appreciate boot-tools-deps -- as cider-nrepl really needs to
#be a git dep  for my purpose here since it's run through mranderson for 
its normal distro)
mkdir src && \
boot -d seancorfield/boot-tools-deps:0.4.6 \
 -d compliment:0.3.6 -d cider/orchard:0.3.1 \
 -d com.rpl/specter:1.1.1 -d com.taoensso/timbre:4.10.0 \
 -d com.bhauman/rebel-readline:0.1.4 \
 -d nrepl/nrepl:0.4.5 \
 deps --config-data \
 '{:deps {cider/cider-nrepl {:git/url 
"https://github.com/clojure-emacs/cider-nrepl.git"; :sha 
"b2c0b920d762fdac2f8210805df2055af63f2eb1"}}}' \
 call -f rebel-readline.main/-main

Paste the following code into the repl:

(require 'cider.nrepl.middleware.info)

(ns java-interop.core
  (:require
   [taoensso.timbre :as timbre
:refer [log  trace  debug  info  warn  error  fatal  report
logf tracef debugf infof warnf errorf fatalf reportf
spy get-env]]
   [clojure.reflect :as reflect]
   [clojure.string :as s :refer [includes?]]
   [com.rpl.specter :as sp]
   [orchard.java :as java]))

(defn specific-class-member? [prefix]
  ;; NOTE: get a proper java class identifier here
  (when-let [prefix (if (symbol? prefix)
  (name prefix)
  prefix)]
(and
 (not (.startsWith prefix ":"))
 (not (includes? prefix "::"))
 (includes? prefix ":"

(def select-j-path
  (sp/recursive-path
   [] p
   (sp/cond-path
#(and (seq? %) (specific-class-member? (first %)))
[(sp/continue-then-stay sp/ALL-WITH-META p)]
map? (sp/multi-path
  [sp/MAP-KEYS p]
  [sp/MAP-VALS p])
vector? [sp/ALL-WITH-META p]
seq? [sp/ALL-WITH-META p])))

(defmacro j [[s & [obj & args]]]
  ;; FIXME: Add better error checking later
  ;; FIXME: Java fields can have the same name as a method
  (let [[clazz-str method-or-field & too-many-semis] (.split (name s) ":")
method-or-field-sym (symbol method-or-field)
clazz-sym (symbol clazz-str)]
(if-let [{:keys [flags return-type]} (first
  (filter
   #(= (:name %) method-or-field-sym)
   (:members
(reflect/reflect
 

Re: Prototype code for enhanced CIDER code completion for Java methods

2018-10-16 Thread 'somewhat-functional-programmer' via Clojure
I apologize for diving into a solution in my first email -- let me give a 
little more of the background as to what I am trying to accomplish.

I'm proposing an additional syntax for Java interop for the purpose of allowing 
support for more precise code-completion of Java fields and methods in Clojure 
tooling.  The new syntax proposal is why I'm emailing this list rather than 
directly going to the project owners of the projects I've modified to support 
this.  If there is high resistance to any additional syntax for Java interop, 
there's not much reason to try to convince the project owners of cider-nrepl 
and compliment to support something just for my personal use :-).

Note also that when I say "propose additional syntax" I do not mean "please add 
this to clojure lang" -- I've implemented this as a couple of macros which 
should be the way the language normally gets extended.  I just want feedback 
and am trying to gauge interest, because if no one wants this then it's not 
worth any of the additional effort to "publish" it -- I'll just manage it as a 
utility library for myself.

So when I say more precise code completion for Java fields and methods, I mean 
this:
  - I want my development environment or REPL to know the type of the Java 
object I'm operating on so it can limit the completion list to fields or 
methods that are valid for that particular type.
- For example, when typing:
  (.get
  I'd somehow like my environment to know that I want code completion for a 
Java object of type "this.is.AType"
  and as such, I would only see methods or fields starting with ".get" for 
that type
What happens for me now, is I see some Java methods and fields starting 
with ".get" but on a number of Java objects (and not a complete list at that).
  (I believe the tooling looks through symbols in your namespace, finds 
Java symbols, and starts pulling methods and fields from any of them).  Using 
only the text "(.get" the environment cannot know what I'm trying to do.

Now the tooling could do static code analysis, it could look at the 
surrounding top-level form, and say, what are the locals, are they type-hinted, 
and only show me Java methods and fields from locals that have type hints.  
Even this approach though, which is complex and error prone to implement, still 
doesn't limit my list to just methods and fields of "this.is.AType" unless I 
only have one type-hinted local symbol.

So...  if we had a syntax that looked like:
(Type:method obj? args)
My tooling becomes drastically simpler.  Now my tooling is fed:
  "Type:method"
And code completion simply becomes:
  - Look up Type in my active namespace symbols (to find out if it's a Java 
type I've imported) (or it could simply be fully qualified, both are supported)
  - Use reflection to find a list of candidate fields and methods
No static analysis required, simple to implement.

It's so simple to implement that I hastily pasted in my 
proof-of-concept/prototype code in the first message -- which hopefully is easy 
for folks to just try.  I hope that people will try it and think: this would be 
great if I were writing a lot of Java interop code -- or better yet, give 
suggestions on how to improve it.

So try this by:
1) Install boot (or update it via "boot -u")
2) Make a new temp directory and navigate to it
3) Run the first command from my prior email in bash
4) Paste in the code snippet to the resulting rebel-readline repl
5) Try the limited completion right in rebel-readline
6) Connect using your cider-nrepl based tooling (CIDER, inf-clojure, 
vim-fireplace, others?), and try it from one of those tools.  I've only tested 
with CIDER -- in my CIDER I get eldoc, help at symbol at point (I wish this 
displayed javadoc inline), and better code completion.
7) Feedback! :-)

I also realize that this stuff is complex enough that there might be some set 
of CIDER settings that solve this problem that I just simply don't know about 
or didn't find.  Love to hear about how others get better Java interop code 
completion.  Some of my clojure projects involve lots of Java interop and this 
would have been so nice to have while writing those projects (in my 
opinion).

I think there are other advantages to this style syntax (besides supporting 
code completion):
  - Right now I have the jvm macro throw an error if it can't find the java 
symbol -- so you would get a compile time error rather than just a reflection 
warning about a non-existent java method.
  - In addition to making easier to *write* Java interop, I think it makes it 
easier to *read* Java interop
I immediately know the Java type while reading the code, no need to hunt 
down the type annotations elsewhere.  I've been writing Java since Java 1.1 and 
I still like the reminder of what class a method is from.

‐‐‐ Original Message ‐‐‐
On Tuesday, October 16, 2018 4:23 PM, Timothy Baldridge  
wrote:

> I don't understand why this is needed. Why can't ci

Re: Prototype code for enhanced CIDER code completion for Java methods

2018-10-16 Thread 'somewhat-functional-programmer' via Clojure
Comments inline...

‐‐‐ Original Message ‐‐‐
On Tuesday, October 16, 2018 3:47 PM, 'Tatu Tarvainen' via Clojure 
 wrote:

> Nice. I like the syntax, I'll try it out.

Thanks -- let me know if the boot command doesn't work...  I had to update boot 
on one of my boxes to get it to work ("boot -u" -- to 2.8.2 I think).

> But it seems unlikely to me that the interop forms would be changed in core 
> at this late stage.

I agree -- I probably should have worded "propose new syntax" differently -- 
this was never intended to be a candidate for clojure lang -- it was always 
intended to be a macro similar to the prototype code I put in my last message.

> As metadata tags can be added to symbols, could we write (^String .charAt 
> "test-string" 0)
> It doesn't look as nice as your proposed syntax, but is possible without 
> modifications.

Interesting -- I don't believe I'd get the full "(^String .prefix" in the place 
in the compliment library where I made my addition (as the "prefix") -- but I 
would get the "context" (from some but potentially not all clojure tooling) -- 
the context being the surrounding top-level form which would include the 
"^String" -- so in theory it would be possible for some clojure tooling to use 
this to accomplish the same thing.

I think it would look odd for those places where you still had to type hint to 
avoid reflection:
(defn avoid-reflection-warning-by-doing-this [a]
  (^InputStream .read ^InputStream a))

(The macro on the other hand automatically adds the type hint to avoid 
reflection)

> perjantai 12. lokakuuta 2018 3.22.37 UTC+3 somewhat-functional-programmer 
> kirjoitti:
>
>> I'd like to share an idea and prototype code for better Java code completion 
>> in CIDER.  While my main development environment is CIDER, the small 
>> modifications I made to support this idea were both to cider-nrepl and 
>> compliment -- which are both used by other Clojure tooling besides CIDER -- 
>> so maybe this is immediately more widely applicable.
>>
>> In an effort to make it easier on the tooling, I'm using a slightly 
>> different syntax for calling Java methods.  My inspiration is Kawa scheme, 
>> and the notation is very similar:
>>
>> (String:charAt "my-string" 0) => \m
>> (Integer:parseInt "12") => 12
>> (possibly.fully.qualified.YourClassName:method this args)
>>
>> For this syntax to be properly compiled of course it needs to be wrapped in 
>> a macro:
>>
>> One form:
>> (jvm (String:charAt "my-string" 0))
>>
>> Any number of forms:
>> (jvm
>>   (lots of code)
>>   (JavaClass:method ...)
>>   (more code)
>>   (AnotherJavaClass:method ...))
>>
>> The jvm macro will transform any symbol it finds in the calling position of 
>> a list that follows the ClassName:method convention.  I was thinking maybe 
>> of limiting it to just a particular namespace to absolutely prevent any name 
>> collisions with real clojure functions, something like:
>>
>> (jvm/String:charAt "my-string" 0)
>>
>> This will also work with the one-off test code I'm including here for folks 
>> to see what they think.
>>
>> I actually like the syntax (though I wish I didn't have to wrap it in a jvm 
>> macro -- though if this actually idea was worth fully implementing, I'd 
>> imagine having new let or function macros so you don't even have to sprinkle 
>> "jvm" macros in code much at all).
>>
>> There is one additional advantages to this style of Java interop besides the 
>> far better code completion:
>>   - The jvm macro uses reflection to find the appropriate method at compile 
>> time, and as such, you get a compile error if the method cannot be found.
>> - This is a downside if you *want* reflection, but this of course 
>> doesn't preclude using the normal (.method obj args) notation.
>>
>> You could even use this style for syntactic sugar for Java method handles:
>>   - Though not implemented in my toy code here, you could also pass 
>> String:charAt as a clojure function -- assuming there were no overloads of 
>> the same arity.
>>
>> So, I'm hoping you will try this out.  Two things to copy/paste -- one is a 
>> boot command, the other is the 100-200 lines of clojure that implements a 
>> prototype of this.
>>
>> This command pulls the necessary dependencies as well as starts up the 
>> rebel-readline repl (which is fantastic tool, and it also uses compliment 
>> for code completion):
>>
>> # Run this somewhere where you can make an empty source directory,
>> # something fails in boot-tools-deps if you don't have one
>> #   (much appreciate boot-tools-deps -- as cider-nrepl really needs to
>> #be a git dep  for my purpose here since it's run through mranderson for 
>> its normal distro)
>> mkdir src && \
>> boot -d seancorfield/boot-tools-deps:0.4.6 \
>>  -d compliment:0.3.6 -d cider/orchard:0.3.1 \
>>  -d com.rpl/specter:1.1.1 -d com.taoensso/timbre:4.10.0 \
>>  -d com.bhauman/rebel-readline:0.1.4 \
>>  -d nrepl/nrepl:0.4.5 \
>>  deps --config-data \
>>  '{:dep

Re: Prototype code for enhanced CIDER code completion for Java methods

2018-10-16 Thread 'somewhat-functional-programmer' via Clojure
Comments inline...  I really appreciate you taking the time to look at this.  I 
think I am still imprecise in my language -- I hope the comments below doesn't 
come across as too tedious :-)...

‐‐‐ Original Message ‐‐‐
On Tuesday, October 16, 2018 7:46 PM, Timothy Baldridge  
wrote:

> As you say, this is a limitation in the code completer. In Cursive this 
> problem doesn't exist to this extent, when I type `(.get` the completer 
> responds with a list of methods and classes that could be completed to that 
> method, starting with classes in the namespace I'm currently editing.

I think we are saying the same thing here.  I believe compliment (the library 
CIDER/other clojure tooling uses for code completion) does what we are 
describing (showing Java methods and fields from multiple Java types that are 
imported into the namespace currently being edited (or type hinted in 
locals/function definitions).  My point is I want more -- I want the completion 
list to only include methods and fields from the type I as a developer know 
that I have.

Like a Java IDE:
MyType a = new MyType();
Now typing "a." yields just completions valid for MyType, and not 5 other types 
I've used nearby.

> Yes, this takes static analysis, or perhaps some indexing and introspection. 
> But changing the syntax is never really going to gain traction here, as 
> manually typing the name of every method just so my editor can produce a list 
> seems like me conforming to my tool rather than my tool learning to work with 
> me.

Just to make sure I'm completely clear -- I'm *not* advocating a change to 
clojure lang -- only proposing a macro/library.  The prototype macro I wrote 
simply transforms the (Type:method ...) syntax into the (. instance-expr 
member-symbol) that (.method ...) macroexpands into anyhow.  This is not 
intended to replace (.method obj args) notation.

I'm not sure what you mean by "manually typing the name of every method just so 
my editor can produce a list".

The way this works is, you type "(MyType:" and get presented with a list of 
completions that are *only* applicable to MyType -- there's no manually typing 
lists of methods and fields anywhere.  And, the way this works for me in CIDER, 
I type "(My" and I get "(MyType", then I add a ":", and now I get 
completions just for MyType -- it also shows me the Java signature of the 
methods as I highlight a potential completion.  There's no manually seeding the 
list anywhere...

> The imported classes in the current namespace are stored in the mappings 
> attribute. It seems like an editor should be able to install hooks into that 
> and index the methods on the classes to provide this feedback. 
> https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Namespace.java#L123

Yes I agree -- and I believe that's exactly what the existing tooling already 
does -- I just want more precision.

Some of my motivation has been working with monstrously large class libraries 
in Java.  GIS libraries in Java are notoriously class/method heavy and after 
importing many of these classes into a namespace, completion that cannot narrow 
down to the exact type I'm using for the reasons we agree on -- simply is 
painful to work with.

> On Tue, Oct 16, 2018 at 1:26 PM 'somewhat-functional-programmer' via Clojure 
>  wrote:
>
>> I apologize for diving into a solution in my first email -- let me give a 
>> little more of the background as to what I am trying to accomplish.
>>
>> I'm proposing an additional syntax for Java interop for the purpose of 
>> allowing support for more precise code-completion of Java fields and methods 
>> in Clojure tooling.  The new syntax proposal is why I'm emailing this list 
>> rather than directly going to the project owners of the projects I've 
>> modified to support this.  If there is high resistance to any additional 
>> syntax for Java interop, there's not much reason to try to convince the 
>> project owners of cider-nrepl and compliment to support something just for 
>> my personal use :-).
>>
>> Note also that when I say "propose additional syntax" I do not mean "please 
>> add this to clojure lang" -- I've implemented this as a couple of macros 
>> which should be the way the language normally gets extended.  I just want 
>> feedback and am trying to gauge interest, because if no one wants this then 
>> it's not worth any of the additional effort to "publish" it -- I'll just 
>> manage it as a utility library for myself.
>>
>> So when I say more precise code completion for Java fields and methods, I 
>> mean this:
>>   - I want my development envir

Re: Prototype code for enhanced CIDER code completion for Java methods

2018-10-17 Thread 'somewhat-functional-programmer' via Clojure
I appreciate your detailed response, and you've certainly done great work with 
Cursive.  I always recommend it to any Java programmer who is starting to learn 
Clojure.  I will start to more seriously weigh the pros and consadditional of 
switching away from emacs.  The cult of emacs has had a strong pull on me but 
your good work may mean I should leave it for Clojure work too (and not just 
for Java work :-)).

Cursive is doing much more in trying to match the Clojure compiler than I 
believe the compliment library has done to date.  Part of me likes the 
readability of the syntax:
(String:charAt my-string 0)
over
(-> ^String my-string (.charAt 0))
But I realize that is much more subjective than anything else.  I have to say, 
in delving into this even a little -- I appreciate the time you must have spent 
matching the Clojure compiler.  I just remember looking at Kawa's syntax for 
Java method calls and thinking, wow, I wish Clojure had that -- so much more 
readable!

I like your last example a lot:
(foo .method) => getting turned into (.method foo) automatically by the editor.
I've actually looked at doing a similar thing with my macro -- basically using 
it in my editor, and then adding an nREPL middleware to transform it to the 
much beloved (.method obj args) notation.  Since I subjectively like the 
readability of (String:charAt obj 0) better than (.charAt ^String obj 0) I 
didn't go that route in this discussion.

I'm curious though, why additional macro / slightly differences from 
"idiomatic" seems so important to avoid.  I think something as simple as 
(String:charAt obj 0) notation would be pretty simple for a third syntax (since 
we already have two built in ways of doing it) -- and closer to the static 
method invocation syntax -- so really a third built-in syntax (Integer/parseInt 
"12").  But that's more a philosophical question I suppose :-).  LISP curse 
anyone? :-)

‐‐‐ Original Message ‐‐‐
On Wednesday, October 17, 2018 8:40 AM, Colin Fleming 
 wrote:

> Cursive already allows this with no syntax changes, but it does require 
> reproducing Clojure's type inference in the editor. Cursive performs this 
> type inference, so (modulo bugs) it knows the types of basically everything 
> that the Clojure compiler does (and in fact in some situations can do better, 
> but I deliberately use just what the compiler knows right now).
>
> This is used in various ways in completion. All of the cases that Aaron 
> enumerates above work, since Cursive can correctly propagate the types in 
> threading forms/doto etc (| is the caret):
>
> (-> "my-string"
> (.ch|)); <- Only String methods here
>
> (-> (new MyType)
> (.|))  ; <- MyType methods here
>
> (def foo "hello")
>
> (-> ^String foo
> (.to|)); <- String completions here too, because of the type hint.
>;Cursive can do better here even though the Clojure 
> compiler doesn't.
>;Currently I restrict this, but completing could e.g. 
> automagically insert the type hint.
>
> (let [foo "string"]
>   (-> foo (.to|)) ; <- No type hint required, since we know the type of foo
>
> Additionally, Cursive supports the following:
>
> (let [foo (ArrayList.)
>   iterator (.iterator foo)]
>   (.ne|))  ; <- Here, .next will be offered even though Iterator isn't 
> imported,
>;because Cursive knows the types we have in scope at the 
> caret.
>
> (let [foo (ArrayList.)]
>   (foo .i|))   ; <- Here, I've put the receiver first, then I'm completing 
> the method call.
>;Since Cursive knows the type of foo, only ArrayList 
> methods will be completed.
>;When I select a completion, Cursive will swap the two 
> around, like:
> (let [foo (ArrayList.)]
>   (.iterator foo|))
>
> I use this last one all the time, and it basically makes Clojure completion 
> as good as Java completion. Someone pointed out to me that this should really 
> use the existing dot syntax, like:
>
> (let [foo (ArrayList.)]
>   (. foo it|))  ; <- completes to:
>
> (let [foo (ArrayList.)]
>   (.iterator foo|))
>
> But I haven't implemented that yet.
>
> I don't do any of the more tricky stuff that IntelliJ does like transitively 
> searching across chained method calls based on the type, etc, but that's just 
> a time issue - there's nothing preventing Cursive from doing that too. Also, 
> offering completions from classes that are not imported but are in scope 
> makes a huge difference, even without any switching trickiness.
>
> Cheers,
> Colin
>
> On Wed, 17 Oct 2018 at 04:34, Didier  wrote:
>
>> How does the new syntax help the tooling figure out the type?
>>
>> (def var (SomeType.))
>> (.method var)
>>
>> Or
>>
>> (jvm (var.method))
>>
>> I'm not sure how you narrow down to only the SomeType methods?
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@googlegro

Re: Prototype code for enhanced CIDER code completion for Java methods

2018-10-17 Thread &#x27;somewhat-functional-programmer&#x27; via Clojure
It's not really:
(jvm (var.method))
but
(jvm (JavaType:method var))

Because the completion engines get "JavaType:" as a prefix, they can look up 
the type via reflection and present a list of methods for *just* that type.

‐‐‐ Original Message ‐‐‐
On Wednesday, October 17, 2018 4:34 AM, Didier  wrote:

> How does the new syntax help the tooling figure out the type?
>
> (def var (SomeType.))
> (.method var)
>
> Or
>
> (jvm (var.method))
>
> I'm not sure how you narrow down to only the SomeType methods?
>
> ---
>
> You 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: Prototype code for enhanced CIDER code completion for Java methods

2018-10-17 Thread &#x27;somewhat-functional-programmer&#x27; via Clojure
I appreciate your thoughtful response -- I wish some of the other tooling could 
do this level of analysis but I can only imagine the time it took Colin to 
implement :-).  Like I mentioned in my response to him -- I'm going to have to 
seriously consider leaving the cult of emacs not only for Java but maybe 
Clojure too :-).

‐‐‐ Original Message ‐‐‐
On Wednesday, October 17, 2018 3:56 AM, Aaron Cohen  wrote:

> This seems like it could be done using threading.
>
> (-> "my-string"
>(.ch<-- completion should give you good results here, for only String 
> methods
>
> (-> (new MyType)
>   (.<-- completion should give you only methods of MyType
>
> ; One interesting case is the following:
> (def foo "hello")
>
> ; foo's type isn't known, so would need to be hinted
> (-> ^String foo
> (.to  <-- good completions again, because of the type hint
>
> I think you won't be able to get all the way to your jvm macro, but likely 
> pretty close, and it's much more idiomatic...
>
> The doto macro is also useful in a similar way, and often what you want when 
> using some of the more byzantine java libraries.
>
> (All of the above works in Cursive, I'm not sure about how it works in CIDER, 
> but I assume it's equivalent).
>
> --Aaron
>
> On Tue, Oct 16, 2018 at 8:30 PM 'somewhat-functional-programmer' via Clojure 
>  wrote:
>
>> Comments inline...  I really appreciate you taking the time to look at this. 
>>  I think I am still imprecise in my language -- I hope the comments below 
>> doesn't come across as too tedious :-)...
>>
>> ‐‐‐ Original Message ‐‐‐
>> On Tuesday, October 16, 2018 7:46 PM, Timothy Baldridge 
>>  wrote:
>>
>>> As you say, this is a limitation in the code completer. In Cursive this 
>>> problem doesn't exist to this extent, when I type `(.get` the completer 
>>> responds with a list of methods and classes that could be completed to that 
>>> method, starting with classes in the namespace I'm currently editing.
>>
>> I think we are saying the same thing here.  I believe compliment (the 
>> library CIDER/other clojure tooling uses for code completion) does what we 
>> are describing (showing Java methods and fields from multiple Java types 
>> that are imported into the namespace currently being edited (or type hinted 
>> in locals/function definitions).  My point is I want more -- I want the 
>> completion list to only include methods and fields from the type I as a 
>> developer know that I have.
>>
>> Like a Java IDE:
>> MyType a = new MyType();
>> Now typing "a." yields just completions valid for MyType, and not 5 other 
>> types I've used nearby.
>>
>>> Yes, this takes static analysis, or perhaps some indexing and 
>>> introspection. But changing the syntax is never really going to gain 
>>> traction here, as manually typing the name of every method just so my 
>>> editor can produce a list seems like me conforming to my tool rather than 
>>> my tool learning to work with me.
>>
>> Just to make sure I'm completely clear -- I'm *not* advocating a change to 
>> clojure lang -- only proposing a macro/library.  The prototype macro I wrote 
>> simply transforms the (Type:method ...) syntax into the (. instance-expr 
>> member-symbol) that (.method ...) macroexpands into anyhow.  This is not 
>> intended to replace (.method obj args) notation.
>>
>> I'm not sure what you mean by "manually typing the name of every method just 
>> so my editor can produce a list".
>>
>> The way this works is, you type "(MyType:" and get presented with a list of 
>> completions that are *only* applicable to MyType -- there's no manually 
>> typing lists of methods and fields anywhere.  And, the way this works for me 
>> in CIDER, I type "(My" and I get "(MyType", then I add a ":", and now I 
>> get completions just for MyType -- it also shows me the Java signature of 
>> the methods as I highlight a potential completion.  There's no manually 
>> seeding the list anywhere...
>>
>>> The imported classes in the current namespace are stored in the mappings 
>>> attribute. It seems like an editor should be able to install hooks into 
>>> that and index the methods on the classes to provide this feedback. 
>>> https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Namespace.java#L123
>>
>> Yes I agree -- and I believe that's exactly wha

Re: Prototype code for enhanced CIDER code completion for Java methods

2018-10-21 Thread &#x27;somewhat-functional-programmer&#x27; via Clojure
Comments inline...

I appreciate the discussion to date!

‐‐‐ Original Message ‐‐‐
On Saturday, October 20, 2018 10:13 AM, Colin Fleming 
 wrote:

>> I'm curious though, why additional macro / slightly differences from 
>> "idiomatic" seems so important to avoid.
>
> I can think of a couple of reasons off the top of my head:
>
> - It won't work with any tooling that's unaware of it, e.g. Cursive.

I agree -- my goal here isn't to add work everywhere.  I think most Cursive 
users probably would care less if it isn't added to Cursive, and if there was 
an actual demand, at least the code to implement would already be done in 
another library, and a trivial amount of code.

One nice thing about cider-nrepl/compliment is that multiple tools use them -- 
I like having this code complete from rebel-readline for example, and in theory 
(I say this because I haven't tested it), it should work in 
vim-fireplace/vim-replant/etc.

I like using it from a rebel-readline REPL over SSH for example -- completely 
outside of emacs/CIDER.

I think this "style" of tooling (not my syntax -- but tooling that is always 
integrated/present in the clojure process) yields this type of benefit -- I can 
use it from wherever I run my code if I'd like, actually independent of any 
editor or development environment.

> - It's very verbose - it's even worse than Java, because instead of 
> annotating each variable once where it's declared you have to annotate every 
> method call, and those annotations remain forever in the code, not just when 
> you're writing it. This is true even when the type is trivially obvious, e.g. 
> (String:charAt "my-string" 0).Modern languages are moving towards more 
> sophisticated type inference for a reason - it's much more comfortable.
>
> Really, this feature is just to make editors work better. Why not do 
> something similar to what Cursive does, and allow the user to type 
> (String:ch|) . Then just show the method completions from String and when the 
> user selects "charAt" just convert to (.charAt |)? This is really a feature 
> to aid code writing after all, not reading. Then the feature wouldn't require 
> macros at all, it could be a purely Emacs thing.

I agree -- if I knew more about emacs lisp I would have gone down this route 
initially.  However, my personal opinion is that this syntax does improve 
readability, at the price of additional verbosity -- a verbosity I personally 
don't mind while editing/writing because my editor helps me out.  The syntax 
itself is similar to C++/Java lambda method references...  Type:method.  I love 
immediately seeing what class a method is from when looking over code where I'm 
unfamiliar with the Java types being used.  But I agree -- this is subjective, 
and if I had more emacs lisp knowledge/time I would have thought much more 
about that route.  My main goal posting here was:
- Hey try this syntax out, it's helped me tremendously with Java interop in 
CIDER, and hopefully elicit some feedback (and I appreciate yours)
I hope it's obvious from the idea of pasting code into a repl to try the 
feature that this isn't *done/released/supported/warrantied/whatever*, but 
really is the beginnings of an idea being explored.  In fact, since I'm now 
starting to use this code more in one of my new interop-heavy projects, I've 
already made a couple of minor changes to it.  It took me much longer to find a 
minimal boot command that used tools/deps/cli and a paste-able code-snippet 
than writing it in the first place :-).

I don't see how this is related to type-inferencing at all.  Type-hinting the 
way we do in clojure is really a type declaration -- it isn't really trying to 
infer that say, something is a number based on usage (say, by being a 
participant in the '+' function --- on the contrary, if I want smart numerical 
"typing", I have to ^long or ^double).  Clojure simply casts/boxes to whatever 
the interop function expects.  If you're referring to the new Java syntax of 
'var x = new blah();' -- I think that's mainly a reaction to 
HowStill>>>>...
I'd almost argue what we do in Clojure is more like gradual typing -- I start 
to type for performance/interop reasons (numerical computing or Java interop) 
but only sparingly.  I don't doubt you are doing type inference in Cursive -- 
sounds like that's precisely how you are getting good completion lists.

> On Wed, 17 Oct 2018 at 11:13, 'somewhat-functional-programmer' via Clojure 
>  wrote:
>
>> I appreciate your detailed response, and you've certainly done great work 
>> with Cursive.  I always recommend it to any Java programmer who is starting 
>> to learn Clojure.  I wil

Re: Prototype code for enhanced CIDER code completion for Java methods

2018-10-21 Thread &#x27;somewhat-functional-programmer&#x27; via Clojure
I agree :-).  For me the cost/benefit decision is easy -- I'm using it in a new 
interop-heavy project.  I posted it here in case others who used cider-nrepl 
based tooling may also potentially benefit -- if enough interest maybe I'd take 
the extra time to publish it as a library.

Often times I have had small macros / functions that I imagine would be of use 
to others but never know how to share them.  I personally have a bad reaction 
against pulling in a named dependency for 1 or 2 functions -- how to share such 
things?  I bet most developers in a lisp start to have their own utility 
libraries.  I've always imagined there would be much for me to learn by seeing 
those libraries from seasonsed lispers.

‐‐‐ Original Message ‐‐‐
On Friday, October 19, 2018 9:58 AM, Matching Socks  
wrote:

> The cost/benefit is hard to work out.  Look ahead 7 years - we would have the 
> ceremonial (jvm... (MyType:baz...)) in some places and the good old elegant 
> (.baz ...) in others, and the tooling will work just as well with it.  On the 
> other hand, if you routinely do tons of interop with a wide variety of 
> classes whose method names are subtly distinct and mostly 40 letters or more, 
> then (jvm...) will seem like genius!  Nonetheless, I hope your work will 
> inspire code completers to go the extra mile, once and for all.  In the 
> meantime, you could wrap that dreadful interop with a library whose method 
> names are shorter.
>
> --
> You 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.


Question: How do you organize large clojure projects?

2018-11-14 Thread &#x27;somewhat-functional-programmer&#x27; via Clojure
This is somewhat of a retrospective -- so please bear with me.  I've had the 
privilege of working on a clojure project for a couple of years now, and have 
accumulated some 15-20k lines of clojure code.  I'm taking a little time to 
look back over what has worked for me and what hasn't in terms of code/project 
organization -- and *I'd love to know what has worked for other people (or 
hasn't)* for similarly large projects.

I knew my project was going to grow to at least as much code as it has now at 
the start, and my domain problem was fairly well-defined.  From the very 
beginning I organized my code into many (15-20) different clojure 'projects' 
using lein.  Rather than organizing code into these projects *by function 
area*, I found myself organizing code into projects by their *dependencies*.  
So any code that used libraries X,Y,Z went into a project that declared those 
dependencies -- even if a function made sense in a different namespace by name 
-- if it needed deps that I already had in another project, I moved the 
function to that project.  For example, in the Java GIS world, if you do 
anything with swing components, you can easily pull in 100s of MBs of 
dependencies.  My project involves GIS work both server-side rest-apis, but 
it's also nice to pull up a quick swing component showing data on a map for 
debugging etc.  I don't have these things in the same project even though there 
is some library overlap because the GUI deps are just too many.

I think for me on my project, the only reason to separate anything into 
'projects' is for reuse based on dependencies -- i.e., to use a function/set of 
functions I've written again, what's the minimal amount of deps to pull in.  
It's worked well for me in that sense -- I'm able to create a new 'main' 
project, include libraries that I want from my project, and not pull in 2,000 
dependencies unless I need it.  The dependencies I'm mostly concerned with here 
are Java deps and not clojure deps.  I've found a relatively small core set of 
clojure deps I almost always want available to me (specter, timbre, core.async) 
-- though even still I have a utility library project where I have a hard rule 
of zero dependencies (for basic macros like (ignore-exception body-forms)).

I've used lein's checkouts and managed dependencies fairly successfully though 
I still forget to lein install everything before I lein uberjar my final 
delivery artifacts and end up debugging old code before realizing what happened 
(and my way of installing everything is a bash for loop :-)).

I've found this approach somewhat tedious and have been wondering if there's a 
better way -- and am very curious what others do.

What I've been playing around with lately is a different concept for my own 
code organization:
  - What if all my clojure code could go in one place, or one project? (Even if 
it ended up being 20k+ lines of code)
  - What if namespaces contained their required dependencies in their metadata?
  - What if upon namespace creation, a namespace's dependencies were 
automatically added to the classpath?
  - What if functions declared in a namespace could also declare additional 
dependencies?  These would be added to the classpath upon first invocation of 
the function.  This is great for my seldom used functions that need many 
dependencies -- code could live in the namespace that is matches its function 
instead of squirreled away in a project just to match its deps.

I have written a basic library that does these things, and am currently trying 
it out on a small scale.  Concerns I've already been trying to address:
  - Dynamically adding things to the classpath is generally considered a /bad/ 
thing to do.
- My code reads all pom.xmls on the classpath to determine what libraries 
are already on the classpath -- and does not re-add libraries that are already 
on the classpath.  I think this alone takes care of a lot of issues with 
dynamically adding deps to the classpath (multiple versions of libraries on the 
classpath).
  - Production deployments should not need to calculate classpaths dynamically
- This technique should be able to be used whether the classpath is 
precomputed (i.e., for production), or dynamically during development.

Example namespace loaded deps:
(ns test
  {:dependencies 'com.taoensso/timbre "4.10.0"}
  (:require [taoensso.timbre :as timbre
 :refer [info debug error warn spy]]))
-or-
(ns test
  {:deps '{[[com.taoensso/timbre {:mvn/version "4.10.0"]]}}}
  (:require [taoensso.timbre :as timbre
 :refer [info debug error warn spy]]))

Now these namespace deps would be loaded dynamically by aliasing the ns macro 
for development with one that loads deps dynamically.  In production, the 
metadata is simply attached to the namespace per normal use of the ns form, no 
deps added dynamically.

(defn-deps test-fn-deps
 "Test Function with optional deps"
 {:dependencies '[[diffit "1.0.0"]
  

Re: Prototype code for enhanced CIDER code completion for Java methods

2018-11-26 Thread &#x27;somewhat-functional-programmer&#x27; via Clojure
Very cool!  By the way, thanks for all the work you have put in to compliment.  
Sometimes it's hard to know when/how to thank people.  I myself am all too 
often guilty of, "Thanks, can I have a new feature or bug fix?"

You, Mr. Emerick, Mr. Batsov -- and many others -- thanks!

I'd start a thanksgiving thread for clojure, but I'm afraid my list would be 
quite long, and sort of sound presumptuous, as if I'd accomplished something 
worthy of thanking the many folks whose work made it possible.  So how about 
this --
  Thanks to all the different folks in the community for sharing your work, 
whether I've used it or not, I've learned many things from:
  - Presentations by Rich Hickey
  - The Joy of Clojure
  - CIDER
  - Figwheel and ClojureScript
  - core.async, manifold, ring, sente, timbre, specter, seesaw, ...

‐‐‐ Original Message ‐‐‐
On Sunday, November 25, 2018 5:53 PM, Alexander Yakushev  
wrote:

> To anyone who's interested in having precise completion for Java classes – a 
> feature like this is available in the latest CIDER snapshot: 
> https://twitter.com/unlog1c/status/1066748173094453248. You can get a 
> filtered completion by prepending a type tag to the next symbol.
>
> On Friday, October 12, 2018 at 3:22:37 AM UTC+3, 
> somewhat-functional-programmer wrote:
>
>> I'd like to share an idea and prototype code for better Java code completion 
>> in CIDER.  While my main development environment is CIDER, the small 
>> modifications I made to support this idea were both to cider-nrepl and 
>> compliment -- which are both used by other Clojure tooling besides CIDER -- 
>> so maybe this is immediately more widely applicable.
>>
>> In an effort to make it easier on the tooling, I'm using a slightly 
>> different syntax for calling Java methods.  My inspiration is Kawa scheme, 
>> and the notation is very similar:
>>
>> (String:charAt "my-string" 0) => \m
>> (Integer:parseInt "12") => 12
>> (possibly.fully.qualified.YourClassName:method this args)
>>
>> For this syntax to be properly compiled of course it needs to be wrapped in 
>> a macro:
>>
>> One form:
>> (jvm (String:charAt "my-string" 0))
>>
>> Any number of forms:
>> (jvm
>>   (lots of code)
>>   (JavaClass:method ...)
>>   (more code)
>>   (AnotherJavaClass:method ...))
>>
>> The jvm macro will transform any symbol it finds in the calling position of 
>> a list that follows the ClassName:method convention.  I was thinking maybe 
>> of limiting it to just a particular namespace to absolutely prevent any name 
>> collisions with real clojure functions, something like:
>>
>> (jvm/String:charAt "my-string" 0)
>>
>> This will also work with the one-off test code I'm including here for folks 
>> to see what they think.
>>
>> I actually like the syntax (though I wish I didn't have to wrap it in a jvm 
>> macro -- though if this actually idea was worth fully implementing, I'd 
>> imagine having new let or function macros so you don't even have to sprinkle 
>> "jvm" macros in code much at all).
>>
>> There is one additional advantages to this style of Java interop besides the 
>> far better code completion:
>>   - The jvm macro uses reflection to find the appropriate method at compile 
>> time, and as such, you get a compile error if the method cannot be found.
>> - This is a downside if you *want* reflection, but this of course 
>> doesn't preclude using the normal (.method obj args) notation.
>>
>> You could even use this style for syntactic sugar for Java method handles:
>>   - Though not implemented in my toy code here, you could also pass 
>> String:charAt as a clojure function -- assuming there were no overloads of 
>> the same arity.
>>
>> So, I'm hoping you will try this out.  Two things to copy/paste -- one is a 
>> boot command, the other is the 100-200 lines of clojure that implements a 
>> prototype of this.
>>
>> This command pulls the necessary dependencies as well as starts up the 
>> rebel-readline repl (which is fantastic tool, and it also uses compliment 
>> for code completion):
>>
>> # Run this somewhere where you can make an empty source directory,
>> # something fails in boot-tools-deps if you don't have one
>> #   (much appreciate boot-tools-deps -- as cider-nrepl really needs to
>> #be a git dep  for my purpose here since it's run through mranderson for 
>> its normal distro)
>> mkdir src && \
>> boot -d seancorfield/boot-tools-deps:0.4.6 \
>>  -d compliment:0.3.6 -d cider/orchard:0.3.1 \
>>  -d com.rpl/specter:1.1.1 -d com.taoensso/timbre:4.10.0 \
>>  -d com.bhauman/rebel-readline:0.1.4 \
>>  -d nrepl/nrepl:0.4.5 \
>>  deps --config-data \
>>  '{:deps {cider/cider-nrepl {:git/url 
>> "https://github.com/clojure-emacs/cider-nrepl.git"; :sha 
>> "b2c0b920d762fdac2f8210805df2055af63f2eb1"}}}' \
>>  call -f rebel-readline.main/-main
>>
>> Paste the following code into the repl:
>>
>> (require 'cider.nrepl.middleware.info)
>>
>> (ns java-interop.core
>>   (:require
>>[taoensso.timb

Re: Question: How do you organize large clojure projects?

2018-11-26 Thread &#x27;somewhat-functional-programmer&#x27; via Clojure
Thank you, it does help.  I almost went the monorepo route but for some reason 
thought I'd have one project.clj file with one giant list of dependencies.  
Having a monorepo but with different dependency sets makes a ton of sense and I 
think would have been much easier to manage.

‐‐‐ Original Message ‐‐‐
On Thursday, November 15, 2018 7:12 AM, Patrik Sundberg 
 wrote:

> I've been happy using a monorepo with boot, and a build.boot with many 
> building blocks that can be mixed and matched for many deployables (uberjars 
> in my case).
>
> In my build.boot I define my internal blocks, but also defs for external deps 
> like eg postgres and grpc. That way I have one place for these groups of 
> dependencies to manage, and can merge them into many of my own building 
> blocks in a flexible and consistent way.
>
> There are no checkouts, multiple outputs and consistent usage of dependencies.
>
> If I need different release management/deployment process for different 
> deployables of my own I tend to use different release branches by deployable 
> that my ci/CD setup triggers from.
>
> Hope that helps!
>
> -
>
> You 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.


1.8.0/1.9.0/1.10.0-RC1 -> 1.10.0 regression: Extending protocols with metadata / datafy combined with macros/symbols

2019-02-27 Thread &#x27;somewhat-functional-programmer&#x27; via Clojure
I finally moved one of my clojure projects from 1.10.0-RC1 to 1.10.0 and 
encountered some very strange behaviour.  Code that had previously compiled 
fine under 1.8.0, 1.9.0, and 1.10.0-RC1 no longer compiled under 1.10.0 with 
the following error:

Execution error (IllegalArgumentException) at bug.core$eval7278/ 
(form-init3641919424619236070.clj:49).
No matching ctor found for class clojure.reflect$typesym$fn__11912

Basically, symbols used inside of macros that had the new datafy protocol added 
to their metadata caused this failure.

My use case that lead my to having this issue in the first place:
  - I use macros in my project to help wrap Java APIs, or convert Java objects 
to/from clojure data structures.
  - In these macros I often use clojure.reflect to aid in adding Java type tags 
to the code I am generating.
  - New in 1.10.0, the symbols you get back from clojure.reflect now contain a 
datafy protocol implementation in their metadata.
  (Note that in 1.10.0-RC1 there was no datafy protocol implementation 
returned in the metadata)
  - The strange exception above occurs when the returned symbol from 
clojure.reflect is used within a macro

I narrowed down a minimalist test case to help illustrate what I am saying:

(require 'clojure.reflect)

;; returns the symbol int, which now in 1.10.0 includes a datafy protocol 
implementation in the metadata of the returned symbol
(defn example-reflect-type-return []
  (->>
   java.lang.String
   (clojure.reflect/reflect)
   (:members)
   (filter #(= (:name %) 'length))
   (first)
   (:return-type)))

;; this macro fails on 1.10.0, but works in 1.10.0-RC1, 1.9.0, and 1.8.0
(defmacro has-the-bug []
  `{:should-have-int-val '~(example-reflect-type-return)})

;; this macro works in 1.10.0, 1.9.0, and 1.8.0
;;  (Basically I had to manually remove the datafy protocol implementation from 
the symbol's metadata)
(defmacro this-works []
  `{:should-have-int-val '~(with-meta
 (example-reflect-type-return)
 nil)})

Works under 1.10.0, 1.9.0, and 1.8.0:
(this-works) => {:should-have-int-val int}

Fails /only/ under 1.10.0:
(has-the-bug)

Failure error:
#error {
:cause "No matching ctor found for class clojure.reflect$typesym$fn__11912"
:via
[{:type java.lang.ExceptionInInitializerError
   :message nil
   :at [jdk.internal.reflect.NativeConstructorAccessorImpl newInstance0 
"NativeConstructorAccessorImpl.java" -2]}
  {:type java.lang.IllegalArgumentException
   :message "No matching ctor found for class clojure.reflect$typesym$fn__11912"
   :at [clojure.lang.Reflector invokeConstructor "Reflector.java" 288]}]
:trace
[[clojure.lang.Reflector invokeConstructor "Reflector.java" 288]
  [clojure.lang.LispReader$EvalReader invoke "LispReader.java" 1317]
  [clojure.lang.LispReader$DispatchReader invoke "LispReader.java" 853]
  [clojure.lang.LispReader read "LispReader.java" 285]
  [clojure.lang.LispReader read "LispReader.java" 216]
  [clojure.lang.LispReader read "LispReader.java" 205]
  [clojure.lang.RT readString "RT.java" 1874]
  [clojure.lang.RT readString "RT.java" 1869]
  [bug.core$eval7278  "form-init3641919424619236070.clj" 49]
  [jdk.internal.reflect.NativeConstructorAccessorImpl newInstance0 
"NativeConstructorAccessorImpl.java" -2]
  [jdk.internal.reflect.NativeConstructorAccessorImpl newInstance 
"NativeConstructorAccessorImpl.java" 62]
  [jdk.internal.reflect.DelegatingConstructorAccessorImpl newInstance 
"DelegatingConstructorAccessorImpl.java" 45]
  [java.lang.reflect.Constructor newInstance "Constructor.java" 488]
  [java.lang.Class newInstance "Class.java" 560]
  [clojure.lang.Compiler$ObjExpr eval "Compiler.java" 4996]
  [clojure.lang.Compiler eval "Compiler.java" 7175]
  [clojure.lang.Compiler eval "Compiler.java" 7131]
  [clojure.core$eval invokeStatic "core.clj" 3214]
  [clojure.core$eval invoke "core.clj" 3210]
  [clojure.main$repl$read_eval_print__9068$fn__9071 invoke "main.clj" 414]
  [clojure.main$repl$read_eval_print__9068 invoke "main.clj" 414]
  [clojure.main$repl$fn__9077 invoke "main.clj" 435]
  [clojure.main$repl invokeStatic "main.clj" 435]
  [clojure.main$repl doInvoke "main.clj" 345]
  [clojure.lang.RestFn invoke "RestFn.java" 1523]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__1115 invoke 
"interruptible_eval.clj" 87]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.core$apply invokeStatic "core.clj" 665]
  [clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1973]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1973]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invokeStatic 
"interruptible_eval.clj" 85]
  [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke 
"interruptible_eval.clj" 55]
  
[clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__1160$fn__1163
 invoke "interruptible_eval.clj" 222

Re: Keys spec with :additional-keys boolean option

2019-03-05 Thread &#x27;somewhat-functional-programmer&#x27; via Clojure
I assume you are forced to use XML (if you are choosing the format, I 
wholeheartedly recommend EDN!).  If you /do/ control the choice of XML/EDN but 
want to interoperate with other languages, check out: 
https://github.com/edn-format/edn/wiki/Implementations - maybe you could use 
EDN anyhow if you have forgiving consumers (hat tip to Alex Miller who pointed 
this page out again recently).

If you must use XML, have you considered the approach of using a generic XML 
data structure (which would by definition have the in-memory definition mirror 
the serialized version)?  You could write a transform function to turn it into 
something you'd rather use from clojure, or simply define accessor functions 
into your data.  I've used data.xml (https://github.com/clojure/data.xml) 
before along with specter (https://github.com/nathanmarz/specter) to 
transform/modify/access XML data.  Though I have to admit, every time I do, I 
curse immutable data structures -- they are unwieldy for /modifying/ highly 
nested structures (XML!).  Specter is the best library I've seen for modifying 
deeply nested structures, and is worth the learning curve (you'll use it 
everywhere once you get used to it -- it's really fantastic), but still isn't a 
perfect fit for XML.

Here's an example of something simpler I wrote to read out the bits of maven 
pom files that I cared about:

(defn collapse-xml
  "Collapses xml data in the form from clojure.data.xml (:tag :t :content 
[\"some whitespace\" {:tag :another-element ...}])
into {:t {:another-element \"value\"}}

   This works well for many configuration style xml files, but you will lose 
all textual content surrounding elements.  For example:
This is some bold text. Is a terrible use case for this, as 
it will return {:p {:bold \"text\"}}

   This does work very well for pom files however."
  [m {:keys [tag content]}]
  (assoc
   m
   tag
   (if (every? string? content)
 (let [s (clojure.string/join content)]
   (if (clojure.string/blank? s) nil s))
 (reduce
  collapse-xml
  {}
  (filter map? content)

If you are using mainly "configuration" style small XML files like maven pom 
files, something simple like this could give you an ergonomic /accessor/ 
clojure data structure (not one suitable for editing and transforming back to 
an on-disk representation though).

Every time I have to use XML from clojure I have yet to find a solution that 
feels clean.  I yearn for xpath and a mutable API (maybe just using a good set 
of Java APIs via interop is really the best answer here).

Given that I can't find a clean solution for XML in clojure, I find the idea of 
trying to use clojure.spec for validation purposes for XML data even more 
difficult to imagine than if the serialized representation were simply EDN to 
begin with.  In fact, I think that's the only time I've gotten any value out of 
clojure.spec in my own projects -- I've used it for verifying serialized EDN 
and found its validation error message output useful (though /so/ verbose for 
large specs!).  I relentlessly spec'd out my projects' data structures in the 
beginning when spec was released (I started my clojure journey when 1.9 was in 
alpha and spec just released), not even looking at plumatic schema or other 
alternatives since clojure.spec was going to be built into core.  However, what 
I ended up with was pages of attribute specs which mostly looked like int?, or 
string?, or keyword?, or map key lists (though some regexes and ranges!).  From 
the reader's perspective it was tough to see what the data was actually going 
to /look/ like.  And then, where to actually use the specs?  Runtime 
performance was too slow to use everywhere...  My most egregious use of spec 
was in multimethods or cond forms, essentially trying to dispatch on the /type/ 
of a map (not knowing in advance what I would get).  Needless to say I have 
stopped using spec as I couldn't manage to figure out a way forward for me 
where its benefits outweighed its costs.  I kept trying to use it as a type 
system, which I think it is ill-suited for (and even if it were suited to it -- 
it's too slow to use as such).

I have since settled on using truss, a wonderful little library 
(https://github.com/ptaoussanis/truss) and have never looked back.  I highly 
recommend looking at it -- you get great error messages for essentially 
run-time type assertions only where you need them (or are currently debugging). 
 That plus typical spy-like macros go a long way (see another great library by 
same author as truss, timbre (https://github.com/ptaoussanis/timbre) which 
includes a nice spy macro).  I made one that defs the value being spied in the 
current namespace if an optional condition is met on the data value.

I had high hopes I would grok clojure.spec enough to get more value out of it 
than time I put into it.  But as of now, simpler solutions have served me far 
better.

‐‐‐ Original Message ‐‐‐
On Monday

Re: No matching field found: length for class byte array

2019-03-18 Thread &#x27;somewhat-functional-programmer&#x27; via Clojure
These are so old, but I (still) often find them laugh-out-loud amusing :-)
https://despair.com/products/apathy

No offense is meant :-).  This next one is an apt description of me when I was 
super-obsessed with clojure startup time:
https://despair.com/collections/retired/products/stupidity

I'm too old for development! I fit into the cranky clojure developer 
demographic Mr. Hickey discussed in his 10 years of clojure talk.  But every 
once in a while it's good to laugh at perceptions, regardless of however close 
they are to reality :-).

‐‐‐ Original Message ‐‐‐
On Monday, March 18, 2019 10:38 AM, Matching Socks  wrote:

> That suggestion of a more humane and helpful error message (", use alength 
> function for array length") is [Jira ticket 
> 1448](https://dev.clojure.org/jira/browse/CLJ-1448).
>
> Back in 2014, it got closed as "declined".  But that was before the recent 
> growth of interest in usable error messages.  The proposed mitigation looks 
> like it would hit the nail on the head.  Its only apparent run-time cost 
> would be on the error path.  One nit: this patch may be step down a slippery 
> slope leading to a more helpful message concerning yet another fake field, 
> Class.class.  (Are there any more?)
>
> Seems like a clear-cut, useful case to me.  Alex, could issue 1448 be 
> reopened?
>
> --
> You 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.