Fork me on GitHub
#clojure
<
2017-11-01
>
Arno Rossouw06:11:23

is a lambda function the same as a closure?

cmdrdats09:11:34

hey all - I'm having super slow compile times on my clojure app - I remember there being a way to report on which namespace the compiler is busy working on, but can't find it anywhere now?

Alex Miller (Clojure team)14:11:39

that doesn’t ring any bells for me other than the :verbose flag in require. Getting that set at the right place in your code might help. There is a particularly bad exponential problem in compilation that was fixed in the 1.9 alphas - curious if you’re using a 1.9.0 beta or 1.8.0 etc?

cmdrdats09:11:11

I suspect one or two namespaces to be culprits, so would like to identify them and then see what I can do

reborg09:11:08

@arno They are not the same. A lambda is a function as a value (you can assign it, pass it around, execute etc). A closure is an implementation detail. It has to do with visibility of symbols when the function is created inside another function (think of it as an implicit map). The inner function "closes over" the context of the outer function, thus creating a closure. This allows the inner fn to refer to symbols that are not declared locally to it. The wikipedia entry does a decent job describing it: https://en.wikipedia.org/wiki/Closure_(computer_programming)

Ben Redden11:11:48

excellent comparison. by the way, your avatar is incredible. always glad to meet a fellow Dead head, especially a developer Dead head metal

reborg13:11:54

Apart from repainting with clj colors, I've just stolen a logo with long history 🙂 http://xahlee.info/UnixResource_dir/lambda_logo.html

Arno Rossouw10:11:16

are there people that set clojure to strict type checking?

Empperi10:11:32

you mean typed clojure?

jjttjj13:11:30

I'm trying to scrape the slack logs here for a quick analysis thing but am getting a javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure with slurp/http-kit/clj-http. anyone know a solution for this?

qqq13:11:05

in clojure, is it possible to use , in large numbers, like entering 1e9 as 1,000,000,000 ?

jjttjj13:11:11

@qqq no, commas are equal to whitespace so they would be read as separate numbers

qqq13:11:14

@jjttjj: thanks for concise explaination

jumar14:11:53

@jjttjj slurp works for me:

(slurp "")
<!DOCTYPE html>
<html>
,,,

chrisblom14:11:42

is there a tool to detect unused functions in a clojure project?

Alex Miller (Clojure team)14:11:03

Cursive colors them a gray color by default

Alex Miller (Clojure team)14:11:25

not sure if that’s reusing something public or not

Alex Miller (Clojure team)14:11:49

kibit or eastwood would be good places to look

Empperi15:11:08

@alexmiller I think Cursive uses it’s own static analysis to do that

Alex Miller (Clojure team)15:11:21

that would be my suspicion too

danm15:11:25

It can be harder than that too. Cursive colours them grey, but if you have a unit test exercising that function then it is 'used', even if it's only the test and nothing in the 'actual' codebase that uses it

danm15:11:50

i.e. Cursive won't colour a fn grey if there is a test for it

Alex Miller (Clojure team)15:11:05

more incentive not to test :)

Empperi15:11:17

one could theoretically write relatively easily a tool which goes through the code and finds which parts are used and which aren’t

Empperi15:11:25

that is effectively very close to tree shaking

Empperi15:11:43

I think cgrand did some work on this

Alex Miller (Clojure team)15:11:46

I’ve done some stuff with tools.analyzer that could answer these questions, but it’s not in a consumable form atm

daveliepmann15:11:39

@chrisblom As I recall from some months ago, I didn't see unused-function checking in kibit or eastwood. This extremely simple bash script was enough for me at the time: https://gist.github.com/joelittlejohn/4729776

lwhorton16:11:30

hey guys, what’s the idiomatic clojure way to handle accessing a data source from multiple disparate points? say you had some data db and “features” a and b that needed to get into that data. on one hand it feels wrong to just use direct interactions like get get-in etc. we should be programming to an interface, no? on the other hand, an interface feels clunky if mostly all it’s doing is using get get-in itself. am I thinking about this incorrectly?

noisesmith16:11:20

@lwhorton the data type is made of a number of interfaces

noisesmith16:11:00

it's considered idiomatic to put things in plain data, and access it as plain data, and not hide things with private values or accessor functions

lwhorton16:11:54

i see. and the “interface” to which you are programming is just stricter rules on schema mutations? such as accretion instead of deletion?

noisesmith16:11:08

unless you made something mutable and have to prevent invalid operations... then you probably want to just do it the way you would in java, but seriously second guess whether it actually needs to be mutable

noisesmith16:11:40

the data structure itself, eg. hash-map, implements a number of interfaces. We use those to manage the data in the map.

noisesmith16:11:34

on a more abstract level there are things like spec and schema if you want to make assertions about the content and shape of the data, but honestly clojure isn't designed for making these sorts of restrictions

noisesmith16:11:05

it's possible, but a bit clunky, and it's easy to make a mess if you try to program with that mindset in a clojure codebase

lwhorton16:11:49

I think I understand. it’s a whole new world, coming from a different paradigm. I just can’t help but think about some sort of data access layer, or a (spooky) data access object. it allows you to aggregate things like logging/monitoring, and provides a “single door” through which everyone has to walk. leaving that behind feels uncomfortable

noisesmith16:11:59

if you think giving up controlling data access is scary, just try using clojure for a while then trying to go back and write code with mutable objects again - that stuff is horrifying

noisesmith16:11:31

there are other languages where you both have strictness about access and types, and immutability, but they have their own trade offs too (typically clumsy and complex language design, and spending a large amount of your time trying to make the compiler happy instead of solving your problem directly)

laujensen16:11:34

https://news.ycombinator.com/item?id=15603023 <--- For those interested, we're also looking for more developers

qqq18:11:36

on vectors, is last guaranteed to be O(1) time and pop guaranteed to be O(log_32 n) time ?

hiredman18:11:04

last is a seq function and is O(n)

ghadi18:11:51

and that is a feature, not a bug ^

bronsa18:11:00

use peek for O(1) on vectors

qqq18:11:12

changed last to peek. Can someone please explain why, on vectors, it's O(n) on purpose ?

chris18:11:07

because using a seq is generic

ghadi18:11:15

you don't want polymorphic performance

eraserhd20:11:31

Hey, Alex's tweeting has reminded me of a particular case that I find difficult to deal with in Clojure. I wonder if there's an interesting way to deal with it.

eraserhd20:11:08

The recent example was turning nested maps which would work for transacting to Datomic except for having reverse attributes in them, into a sequence of maps which do work because they have entities broken out with forward references.

eraserhd20:11:51

The part of it that's difficult (for me) to handle in Clojure is the recursion on a tree structure /and/ collecting multiple values.

eraserhd20:11:18

How would one use for?

hiredman20:11:35

lemme see if I have a good gist

tanzoniteblack20:11:15

@eraserhdanything that involves "complex thing on nested data structure" generally has me reaching for #specter ; it'll probably still be somewhat complex though

hiredman20:11:52

((fn map-paths [path m]
   (if (map? m)
     (for [[k v] m
           i (map-paths (conj path k) v)]
       i)
     [[path m]]))
 []
   {:a {:b 1
        :c [3]}
    :w {:x 1}})
([[:a :b] 1] [[:a :c] [3]] [[:w :x] 1])

hiredman20:11:58

something in that style

timgilbert21:11:05

Hi all, I was looking for a shortcut to see whether a key in a map was present, and was mildly surprised that this didn't work:

(def s [{:a 1} {:a 2} {:a 1} {:a 0}])          ; I want to filter for {:a 1}
Using an anonymous function is trivial:
user=> (filter #(= (:a %) 1) s)
({:a 1} {:a 1})
But I sort of expected this to work just as well, and it doesn't seem to:
user=> (filter (comp :a #{1}) s)
()

dpsutton21:11:58

(filter (comp #{1} :a) s) => ({:a 1} {:a 1})

dpsutton21:11:15

compose applies right to left

timgilbert21:11:21

Oh, darn it! Got the order backwards

dpsutton21:11:26

(comp fn ... f2 f1)

dpsutton21:11:43

simple bugs are the best bugs 🙂

dpsutton21:11:21

just think of compose as smashing its functions into the argument provided