Fork me on GitHub
#clojure
<
2017-08-29
>
noisesmith00:08:17

#(into (empty %1) (distinct) (conj %1 %2)) is useful, I guess it’s not in core because when you need it it has bad algorithmic complexity

noisesmith00:08:59

I guess it could be replaced with an insertion ordered set

qqq04:08:34

is there a line counting program that counts number of functions? (something slightly more advanced than grepping for defn)

didibus08:08:59

I guess def is both binding and assignment, because it implicitly wraps the value in a Var and assign the var a new value if called where a binding for the symbol already existed.

didibus08:08:13

And I guess set! was made to not work on global vars because it wouldn't be atomic and could cause concurrency issues? So instead alter-var-root! was introduced as an atomic way to assign to the root of a global var?

didibus08:08:48

And why wasn't set! used for atoms, when it is used for refs, agents and dynamic vars?

leonoel08:08:27

set! doesn't work with refs nor agents

didibus02:08:21

Hum, then the doc is misleading:

Only Java fields, Vars, Refs and Agents are mutable in
Clojure. See  for more information.

didibus02:08:27

It kond of imply set! Can be used for assignment to all mutable things, and that only vars, refs and agents are mutable.

didibus02:08:45

Is set! only for assigning dynamic vars?

leonoel06:08:08

I agree this is misleading

leonoel07:08:47

set! works with : - dynamic vars, only if the current thread is running inside a binding block involving this var - public, non-final fields of java objects - deftype fields, only if tagged as :unsynchronized-mutable or :volatile-mutable and only if called in the body of a method - flags defined in clojure.core such as *warn-on-reflection* etc

leonoel07:08:55

I can't speak for the language designers, but my guess is that assignment doesn't really mean anything in multithreaded context because there is a bunch of strategies that can be used to make a mutation visible to other threads - static vars use locks - dynamic vars use a mix of ThreadLocal and volatile - refs rely on STM which ultimately uses locks - atoms use CAS - agents use Executors

leonoel08:08:10

TIL the reason why set! works with compiler flags : it's not a special treatment, it's because they're dynamic and they're bound by the compiler itself when the namespace is evaluated

didibus22:09:15

Ya, just would have been nice for set! to be polymorphic on all those, instead of each having its unique method to do assignment.

misha09:08:18

(map list [:a :b :c] [:x :y :z :w])
;; or
(partition 2 (interleave [:a :b :c] [:x :y :z :w]))))
;; ?

misha09:08:11

vararg map-indexed bellissimo

(map list (range) [:a :b :c] [:x :y :z :w])
=> ((0 :a :x) (1 :b :y) (2 :c :z))

hmaurer13:08:13

to re-define a multmethod (the dispatch function), am I forced to ns-unmap first? If I do not the multimethod does not seem to be updated

dominicm14:08:57

@hmaurer I believe this is one of the cases where a redefine doesn't just work. Highly recommend using tools.namespace to reload your code.

hmaurer16:08:05

If I have preconditions on a multimethod, where should I put them? On the dispatch function?

noisesmith18:08:51

it depends, is it a precondition that underlies the multimethod itself, or is it specific to some dispatch?

bschrag18:08:05

Trying to port a third-party API to Clojure. API was originally written in C, vendor has packaged this as JNI, providing Java API. Vendor's java bin directory includes .jar, .dll, and .lib files. I am new to Clojure (longtime Common Lisper), have no real Java background. I got some help on #beginners a while back (https://clojurians-log.clojureverse.org/beginners/2017-08-05.html --- thanks, @noisesmith) but am still stuck. I haven't found a Clojure use case like this by Googling---just on Java-only JARs or on building a JNI from scratch and using that. I am using lein and CIDER on Windows. My defproject form now includes the following.

:jvm-opts ["-Djava.library.path=c:/NeticaJ_Win/NeticaJ_504/bin/"]
  :resource-paths ["c:/NeticaJ_Win/NeticaJ_504/bin/NeticaJ.jar"]
My ns form includes...
(:import [norsys.netica.Environ]
           []
           [norsys.neticaEx.aliases.Node])
I am getting errors like this:
edit-server.core> norsys.netica/Environ
CompilerException java.lang.ClassNotFoundException: norsys.netica, compiling:(*cider-repl edit-server*:1:7209) 
edit-server.core> (norsys.netica/Environ. nil)
ClassNotFoundException norsys.netica  java.net.URLClassLoader.findClass (URLClassLoader.java:381)
Thanks for any insight.

noisesmith18:08:52

norsys.netica/Environ isn’t valid

noisesmith18:08:05

it would be Environ with those imports

noisesmith18:08:19

though norsys.netica.Environ is also allowed

juanjo.lenero18:08:51

Is it possible to have underscores for readability in numeric literals? E.g. 1_000_000

juanjo.lenero18:08:10

As far as I know Java has this, but clojure throws a number format exception.

noisesmith18:08:24

it is not a valid number format for clojure

juanjo.lenero18:08:17

It’s really hard for me to read numbers like this 100000 especially when they get bigger.

juanjo.lenero18:08:48

Could I do something about it?

noisesmith18:08:52

=> (long 1e+6)
1000000
this works

noisesmith18:08:24

though that means an extra conversion and if your not careful it might do the conversion at runtime instead of compile time

juanjo.lenero18:08:25

I can live with that, thank you.

noisesmith18:08:29

there’s also 1e+6M which is a java.math.BigDecimal

bschrag18:08:05

@noisesmith That helps, thanks! Still a DLL issue, though:

edit-server.core> (norsys.netica.Environ. nil)
UnsatisfiedLinkError C:\NeticaJ_Win\NeticaJ_504\bin\NeticaJ.dll: Can't find dependent libraries  java.lang.ClassLoader$NativeLibrary.load (ClassLoader.java:-2)
edit-server.core> 

noisesmith18:08:00

yeah, sounds like you need to fix your path for native libs, but that’s something I don’t have much experience with

noisesmith18:08:57

do you have a sample java command line that is supposed to work with that lib?

urzds19:08:41

Which of these would be more clojury and/or efficient? (into {} (map (fn [k] [(str k) {}]) some-seq)) or (zipmap (map str some-seq) (repeat {}))?

driphter19:08:00

I'd prefer the latter, I think.

urzds19:08:05

Or is there a third way that would be even better?

urzds19:08:54

I was wondering, since the (zipmap (map ...) ...) appears to iterate twice over some-seq.

petterik19:08:58

I tend to use juxt when I use (into {} ..) (into {} (map (juxt str (constantly {}))) some-seq)

noisesmith19:08:19

> (transduce (map str) (completing #(assoc! % %2 {}) persistent!) (transient {}) [1 2 3 4])
{"1" {}, "2" {}, "3" {}, "4" {}}
- fixed

bschrag19:08:00

@noisesmith Vendor instructions to run demo are to run two batch files, in order, from demo directory. Contents follow. 1:

"C:\Program Files\Java\jdk1.8.0_131\bin\javac.exe" -deprecation -classpath ..\bin\NeticaJ.jar  *.java
2:
set PATH=..\bin;%PATH%
   java  -classpath .;..\bin\NeticaJ.jar -Djava.library.path=..\bin  Demo
Results: 1: New file Demo.class. 2: Demo runs fine. I've been trying to execute my translation of a form in Demo.java --- new Environ (null); --- as (norsys.netica.Environ. nil).

urzds19:08:17

Does assoc-in have some dissoc-in counterpart?

noisesmith19:08:33

that is the right translation, yes - you should be able to run the exact same commands except pointing to clojure.jar instead of the java files (plus a file running the clojure code you need)

noisesmith19:08:47

@urzds no because there’s no consensus on what it would do if the key is already missing

noisesmith19:08:58

(it’s discussed on Jira somewhere…)

bschrag19:08:56

@noisesmith Instead of using lein, defproject?

noisesmith19:08:13

no no I’m saying using java - then when you find what works translate to lein

noisesmith19:08:00

fundamentally, lein is a tool for managing java deps, so when your java deps are such that lein can’t manage them, you can skip lein.

java -classpath clojure.jar;..\binNeticaJ.jar;src -Djava.library.path=..\bin clojure.main some.clojure.ns

noisesmith19:08:26

if src is the dir with your clojure code in it that is

noisesmith19:08:45

(fix to point to the actual location of a clojure.jar, or copy a clojure.jar to the current ns)

urzds19:08:58

Found the missing dissoc-in task in JIRA: https://dev.clojure.org/jira/browse/CLJ-1063

bschrag19:08:26

@noisesmith Thanks, will try.

noisesmith19:08:13

@bschrag also you can leave off the namespace arg and just get a bare repl (no line editing and no namespaces pre-required though)

bschrag20:08:43

@noisesmith I gather that your some.clojure.ns plays the role of "script" in documentation from clojure.main --help: . For this, I might use my core.clj, including the ns form?

noisesmith20:08:16

no, it’s a namespace arg to clojure.main - I think I forgot the -m that needs to go before that; so just a string is a file name, -m is the namespace to find and run (based on classpath) and -e is just code to eval

noisesmith20:08:28

@bschrag btw this works

$ java -jar ~/bin/clojure.jar --help
Usage: java -cp clojure.jar clojure.main [init-opt*] [main-opt] [arg*]

  With no options or args, runs an interactive Read-Eval-Print Loop

  init options:
    -i, --init path     Load a file or resource
    -e, --eval string   Evaluate expressions in string; print non-nil values

  main options:
    -m, --main ns-name  Call the -main function from a namespace with args
    -r, --repl          Run a repl
    path                Run a script from a file or resource
    -                   Run a script from standard input
    -h, -?, --help      Print this help message and exit

  operation:

    - Establishes thread-local bindings for commonly set!-able vars
    - Enters the user namespace
    - Binds *command-line-args* to a seq of strings containing command line
      args that appear after any main option
    - Runs all init options in order
    - Calls a -main function or runs a repl or script if requested

  The init options may be repeated and mixed freely, but must appear before
  any main option. The appearance of any eval option before running a repl
  suppresses the usual repl greeting message: "Clojure ~(clojure-version)".

  Paths may be absolute or relative in the filesystem or relative to
  classpath. Classpath-relative paths have prefix of @ or @/

bschrag22:08:07

@noisesmith This works (!):

c:\NeticaJ_Win\NeticaJ_504\demo>java -classpath C:\Users\Schrag\.m2\repository\org\clojure\clojure\1.8.0\clojure-1.8.0.jar;c:\NeticaJ_Win\NeticaJ_504\bin\NeticaJ.jar -Djava.library.path=c:\NeticaJ_Win\NeticaJ_504\bin clojure.main
java -classpath C:\Users\Schrag\.m2\repository\org\clojure\clojure\1.8.0\clojure-1.8.0.jar;c:\NeticaJ_Win\NeticaJ_504\bin\NeticaJ.jar -Djava.library.path=c:\NeticaJ_Win\NeticaJ_504\bin clojure.main
Clojure 1.8.0
user=> (norsys.netica.Environ. nil)
#object[norsys.netica.Environ 0x6ca18a14 "norsys.netica.Environ@6ca18a14"]
user=> 
Any idea about how to get the same effect with lein?

noisesmith22:08:14

the string you give to classpath can go in :resource-paths and the -D… can go in :jvm-opts I think - you might need a ^:replace prefix on the jvm-opts value

noisesmith22:08:11

but I bet there’s something more elegant that lets you leverage the maven ecosystem properly (I’m not super good at the library.path stuff though…)