Fork me on GitHub
#clojure
<
2016-08-21
>
lvh11:08:31

Crud; can I change the title of my issue on the clojure issue tracker? I messed up: http://dev.clojure.org/jira/browse/CLJ-2006

anmonteiro12:08:09

@lvh you should see an “Edit” button button on the top left corner

anmonteiro12:08:37

it may be the case that you don’t have the necessary permissions, which you need to request to an admin

anmonteiro12:08:34

Oh it seems you already knew that, reading your comment

anmonteiro12:08:38

happy to change it for you

lvh12:08:24

I don’t know if that means I don’t have the permissions or I’m just going blind and can’t find the button you’re talking about 🙂

lvh12:08:41

the title should end just before the comma

moxaj15:08:51

@hiredman definterface still follows the old version of type hinting (ie. on the symbol). Is that intentional?

sandbags16:08:35

Hi @yogthos wanted to say thank you for clj-pdf. So great that there’s an easy library for generating PDF’s available.

yogthos16:08:22

@sandbags: thanks, glad to hear it's useful 😉

sandbags16:08:48

very much so, the hiccup like approach is especially welcome

sandbags16:08:41

that it actually just seems to work is also cool, last time i tried generating PDF’s (a few years ago it has to be said) it seemed like a nightmare

yogthos16:08:54

yeah that was the main motivation

sandbags16:08:58

i ended up generating HTML and automating print-to-PDF

sandbags16:08:10

which wasn’t ideal

yogthos16:08:11

I had to do a lot of report generation, and found all the libs available at the time were just painful to use

machty16:08:05

can someone help me understand what's "special" about Lisp REPLs? how is it different than ruby's irb or python's repl?

myguidingstar16:08:52

I think it's not that special 🙂 Clojurians prefer their time with REPL-connected editors instead

machty16:08:56

so when you spin up a luminus server w lein run

myguidingstar16:08:03

something interesting is that Clojure code is often short and well-encapsulated, so calling doc and source against a symbol (function, macro...) is helpful

machty16:08:24

it starts a repl server as well. is the idea here that the repl server lets a connected repl live-inspect objects/running code on the web server?

machty16:08:21

i guess, why is it significant that spinning up the web server also spins up a repl server? why couldn't i just spin it up separate?

jasongilman16:08:11

Connectivity of your editor to the REPL is one one of the most undersold aspects of Clojure. During development you can modify your running server on the fly or inspect data flowing through your system.

myguidingstar16:08:09

i'm not sure if the ability to control running app from repl is special. I don't know if Python and Ruby support it well

myguidingstar17:08:09

the reason to start both is just about economics: start up time 🙂

myguidingstar17:08:39

wait, it isn't. You should start them from the same shell prompt so the repl can control the web server later

seancorfield17:08:49

We run a REPL server inside all our long-running processes - even in production. That way we can attach to a running process and inspect it, and apply live patches if necessary (which we do from time to time).

seancorfield17:08:10

When developing, we try to run as much as possible of the application in the REPL (using Stuart Sierra's Component these days) so we can live edit as we're developing.

seancorfield17:08:51

Do the Python / Ruby REPL support that sort of workflow?

plexus17:08:11

Being a lisp makes it very suitable for sending code from an editor to a REPL, because it's airways clear what the form before /after the cursor is. In other languages that's ambiguous. So e.g. There's inf-ruby for emacs, and it's pretty cool, but not as easy to work with as inferior-lisp

plexus17:08:53

that said it's also just cultural. Some languages like to have automatic test runners as the main feedback loop, for lisps it tends to be more repl driven

Alex Miller (Clojure team)18:08:17

@moxaj definterface puts it in a different place to echo Java placement - that's intentional

hueyp19:08:39

can you instantiate a record if its passed as an argument? e.g. (let [foo Foo] (foo. 123)) (Foo is a (defrecord Foo [x]))

machty19:08:12

@plexus: what do you mean about the clear airways?

plexus19:08:38

sorry that was autocorrect, I meant "it's always clear"

machty19:08:39

@plexus what do you mean the cursor? do you mean syntactically you always know when the "whole" lisp command is complete and ready to be sent because parentheses make it clear vs newlines/indentation?

plexus19:08:46

I mean if you're in a position in a buffer in Emacs and press C-x C-e, it will evaluate the form before "point" (the cursor position). Because it's s-expressions this is well defined and easy to parse. For other languages it's much harder to figure out where the expression starts and ends, and it may even be up for debate

plexus19:08:32

x = foo && bar("baz")| with | indicating the cursor position. Do I want to evaluate bar("baz"), foo && bar("baz") or x = foo & bar("baz")? there's no way to tell, you can agree on one interpretation, but the user no longer has a choice

plexus20:08:06

(def x (and foo (bar "baz")))| now by moving my cursor I can show exactly which expression I'm interested in

machty20:08:32

so usually when sending "commands"/expressions to the server repl, you usually send a snippet by pointing the cursor to inside an s-expr and only that s-expr gets sent for eval

plexus20:08:27

yeah that's a very common way of doing it, and if it's all plain values and pure functions then you can evaluate the inside forms, see what their results are, then move inside out and really get an understanding of what data is going through your system

plexus20:08:33

it's a great way to poke at things when they aren't working as expected, "is this getting the inputs I'm expecting?" "is it generating the output I'm expecting?", "how about the next thing?"

machty20:08:44

but if you grab a s-expr that includes symbols external to the portion you selected (which seems like a very common thing), how do you supply those values for the repl?

plexus20:08:59

yeah that is of-course common, I would just copy the form I'm interested in (again easy because of s-expressions) and fill in the gaps with hardcoded values, either directly, or by wrapping it in a let

machty20:08:36

cool. thank you!

machty20:08:47

@seancorfield I come from a rails-y background, and most of the servers i spin up use forking / threading to spin up multiple instances of the same server; if your prod servers spin up a repl, do you just avoid the forking (come to think of it i don't think you can fork in java), or is there any complications live-patching a multithreaded server?

plexus20:08:13

in the Ruby/Rails world the multiprocess model is very common because Ruby's lack of native threads plus the GVL (global vm lock) mean it can only really occupy a single core at a time. Java has native threads, and web-servers will use threads and thread pools to handle requests, so a single JVM can utilize the full CPU

plexus20:08:07

when you connect to a repl inside that process and redefine a function then all threads will pick that up

machty20:08:39

so that's what a live patch is. just providing a new series of defs / defns

machty20:08:01

and the immutable nature makes that a reasonable safe/feasible thing to do relative to other languages

plexus20:08:31

yeah, basically. It's pretty cool, you can figure out a bug and have it fixed in production in seconds. The time it takes to set up an SSH tunnel and do M-x cider-connect

plexus20:08:11

of course usual warnings of messing with production apply, but on the other hand you can revert to the old definition just as quickly

plexus20:08:27

can also be handy for quickly running some ad-hoc queries

machty20:08:48

@plexus btw i believe ruby has native threads even though it used to only be green threads

machty20:08:02

since 1.9 i think

machty20:08:29

i'd be curious to hear the in-depth technical details as to how Clojure supports live patching whereas w Ruby/Rails i believe you run into issues of class caching if you tried something like that

plexus20:08:47

you're right about the threads, but the GVL still prevents them from actually running in parallel

plexus20:08:53

try this in irb, require 'securerandom'; 4.times {Thread.new { loop { SecureRandom.base64(100) }}}, then have a look at htop, you should see 4 cores at close to 100%, but you don't

machty20:08:35

rubinius gets rid of GIL though i think

machty20:08:48

but confirm on mri

lvh21:08:09

alexmiller: Thanks for the edit permission!

yogthos22:08:57

@machty: if you’re interested to see how the REPL driven workflow works in Clojure, I live coded a small Luminus app in a talk I gave recently http://chariotsolutions.com/screencast/philly-ete-2016-2-dmitri-sotnikov-transforming-enterprise-development-clojure/

tom22:08:57

Has anyone used Lambada? I have an executable (ffmpeg) and I used the lein app template with lambada to compile a stand alone jar. I added the executable alongside the uberjar in the root of the zip file. When I run it, though, the name of the function is not found. https://github.com/uswitch/lambada