# boot

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

juhoteperi 23:01:51

I know... but I hate that each time I do release I forget to run build-jar and then I can't do a release because it updates the readme just before push and then push fails because repo is not clean

juhoteperi 23:04:52

It's not possible to use javascript links in github, but it would probably be possible to link to a page which would copy the coordinate upon page load

richiardiandrea 23:07:02

Guys just a theoretical question, why do I need :scope "test" when declaring a dependency in boot? Is it the same meaning as in maven?

micha 23:08:26

@richiardiandrea: yes, it prevents that dependency from being included as a transitive dependency of a project that depends on your project

juhoteperi 23:08:50

Also prevents the dependency being included in uberjar

micha 23:09:33

it'll stil be in the generated pom.xml of course

mathiasx 23:10:30

hey micha, alandipert, are you guys still interested in using something like boot-sassc with JRuby + Sass (for Compass) or did you guys end up rolling your own solution?

richiardiandrea 23:10:46

in tenzing I see that it requires for instance boot-reload at the beginning of build.boot but can't I do it just in the development task (that is where I need it) ?

micha 23:10:56

@mathiasx: we're using boot-sassc currently with libsass

micha 23:11:14

@richiardiandrea: yes you can

mathiasx 23:11:30

@micha: OK to PM so I don’t clutter up the channel? lol

micha 23:11:36


micha 23:12:26

@richiardiandrea: the benefit of adding the test dependency is that you can resolve all your deps at once

micha 23:12:38

which reduces the possiblity of dependency conflicts

micha 23:12:50

like maven was really not designed for dynamically adding dependencies

micha 23:13:00

because of the way it internally resolves dependency conflicts

richiardiandrea 23:13:12

@micha thanks, I feel that after setting the options in development I could call the big require, or maybe split set-dev! where I just set deps and development where I actually require and do stuff...

richiardiandrea 23:13:23

@micha: great thanks for expanding on this

micha 23:13:54

like if the dependency you add dynamically has transitive dependencies that conflict with ones already loaded

micha 23:14:16

if you did them all at once aether would resolve those dependencies differently

micha 23:14:22

because it can see the whole graph

richiardiandrea 23:14:28

ah wow did not know that

richiardiandrea 23:14:34

make sense though

juhoteperi 23:17:20

Also, without top level require you can't refer to required vars directly but would need to use resolve to resolve symbols to vars in runtime

richiardiandrea 23:18:07

so I can't do
(deftask run [] (require '[adzerk.boot-cljs :refer [cljs]] '[adzerk.boot-cljs-repl :refer [cljs-repl start-repl]] '[adzerk.boot-reload :refer [reload]] '[pandeiro.boot-http :refer [serve]] '[crisptrutski.boot-cljs-test :refer [test-cljs]]) (comp (serve) (watch) (cljs-repl) (reload) (build)))

juhoteperi 23:19:02

(comp ((resolve 'pandeiro.boot-http/serve)) (watch) ((resolve 'adzerk.boot-cljs.repl/cljs-repl)) ... would work

juhoteperi 23:19:53

Clojure will read the whole file first and try to resolve all symbols to vars, without top-level require reader can't resolve symbols to vars.

richiardiandrea 23:20:08

understand, but I guess I can stick with the top level require, as the performance hit is minimal

richiardiandrea 23:20:34

boot is faster than lein in any case on my machine

micha 23:20:57

you can also wrap in eval instead of using resolve i think

micha 23:21:38

(deftask foo [] (require '[sadf.qwer :refer [foop]]) (eval '(foop 100)))

micha 23:21:43

i think that would work

richiardiandrea 23:21:56

less verbose, I can try that out

esnunes 23:23:17

where can I find example files?

richiardiandrea 23:23:54

clojure.lang.ExceptionInfo: Unable to resolve symbol: cljs in this context

esnunes 23:24:57

I want tasks to: build jar file, run tests whenever a file is saved, run repl, run app

micha 23:26:19

@esnunes: the README for boot on github is a start

esnunes 23:28:00

I read the whole README file, it tells me how boot works and how to create tasks. I've just realized there is "documentation" link right on the top, which points out to the wiki

esnunes 23:28:05

thanks @micha

richiardiandrea 23:28:10

(deftask build [] (require '[adzerk.boot-cljs :refer [cljs]]) (comp (speak) (resolve 'adzerk.boot-cljs/cljs))) does not work here, but I am just experiment, I will follow the standard path I guess :simple_smile:

micha 23:28:21

plenty of examples there :simple_smile:

richiardiandrea 23:28:37

just toying around

juhoteperi 23:28:47

@richiardiandrea: Try wrapping (resolve...) in paretheses

richiardiandrea 23:30:05

right because it returns a function :smile:

micha 23:30:06

@esnunes: also the boot wiki and api docs

esnunes 23:30:27

@micha I was avoiding search for examples right on google or github due to the fact that as boot is a very active project I might end up finding outdated examples, I will focus on wiki and api docs first :simple_smile:, thanks

richiardiandrea 23:30:53

(deftask build [] (require '[adzerk.boot-cljs :refer [cljs]]) (comp (speak) ((eval 'adzerk.boot-cljs/cljs)) )) works too!

micha 23:31:19

@esnunes: we haven't made any breaking changes since 2.0.0, which was december 2014 i think

micha 23:31:30

but the tasks may have changed since then, of course

esnunes 23:31:43

nice, I'm totally new to boot, actually new to clojure too

richiardiandrea 23:33:46

@micha: I guess you could even think about wrapping this require plus ((resolve ...)) in some sort of macro that does expose the symbol in the body...jst throwing ideas around :wink:

micha 23:35:46

yeah you could make a macro that evals each expression separately at runtime

micha 23:35:57

clojure does that itself for top level forms

micha 23:36:32

that's why you can do this in your build.boot:

micha 23:36:55

``` (require '[ :refer [baz]])

(baz 100) ```

micha 23:37:15

because the clojure compiler will compile and eval each top level form separately

micha 23:37:31

but each top level form is compiled as a unit

micha 23:37:59

so inside of there you can't introduce new bindings except with let etc

micha 23:38:13

i mean you can, but the compiler won't see them

micha 23:38:34

because the require that's inside the top level form won't be evaluated until the entire top level form is compiled

richiardiandrea 23:47:48

@micha it feels cleaner (to me at least) to have a require in the task that needs it, that is reason of my idea...but I can live with the way it is now :)

micha 23:48:29

yeah you can do that for tasks especially

micha 23:48:40

since the tasks don't have any transitive dependencies

micha 23:48:54

so there isn't any chance of the dependency problems i described before

jethroksy 05:09:35

@micha do you deploy with eb deploy or using the boot plugin?

micha 05:11:13

i've been using eb deploy

micha 05:11:26

@jethroksy: ^^

jethroksy 05:11:51

i'm using eb deploy but the docker images created are extremely weird

micha 05:12:01

how so?

jethroksy 05:12:19

I get no such task: /usr/bin/boot in my sdeouterr.log

jethroksy 05:12:36

then i check the docker images log and see that the command is /usr/bin/boot /usr/...

micha 05:12:40

does the docker image run locally?

micha 05:13:03

that's weird

jethroksy 05:13:51

I removed all appearances of /usr/bin/boot in my dockefile

jethroksy 05:14:07

and its still creating images with /usr/bin/boot /usr/.. as the command

micha 05:19:20

do you have a file?

jethroksy 05:22:27

its minimal

jethroksy 05:22:56

{ "AWSEBDockerrunVersion": "1", "Ports": [ { "ContainerPort": "3000" } ], "Volumes": [], "Logging": "/var/log/nginx" }

micha 05:23:54

it's weird that it runs locally

micha 05:24:09

docker image should eb a docker image

micha 05:24:20

that's the whole point of them lol

jethroksy 05:25:07

yeah... i'll try running it locally again to see if i broke something

jethroksy 05:35:58

local image works...
Current system: #' 03:31:38.601 INFO [org.projectodd.wunderboss.web.Web] (clojure-agent-send-off-pool-0) Registered web context / Autostarting the system: :started Reloading namespaces (edubot.pages.signup edubot.pages.partials edubot.slack edubot.core edubot.handler edubot.pages.errors edubot.pages.index) :reloading () 03:31:39.054 INFO [org.projectodd.wunderboss.web.Web] (clojure-agent-send-off-pool-0) Registered web context /

danielsz 05:38:07

Public announcement: the latest system snapshot supports abstractions derived from Duct: endpoints and handlers. Discussion around the upcoming changes is here:

micha 05:44:59

congratulations, @danielsz

micha 05:45:13

looks great

danielsz 05:45:31

Thanks, @micha !

jethroksy 06:17:53

@micha: I cloned and am trying to deploy it to EB

jethroksy 06:18:39

So I cloned, did eb init with all the usual stuff

jethroksy 06:19:42

``` FROM adzerk/boot-clj:latest

RUN /usr/bin/boot web -s doesnt/exist repl -e '(System/exit 0)' && rm -rf target



CMD ["prod-run"]

jethroksy 06:20:25
{ "AWSEBDockerrunVersion": "1", "Ports": [ { "ContainerPort": "8008" } ], "Volumes": [], "Logging": "/var/log/nginx" }

jethroksy 06:21:27

I thought the boot-clj image made the ENTRYPOINT /usr/bin/boot so the CMD ["prod-run"] would run /usr/bin/boot prod-run

micha 06:21:36

ah no

micha 06:21:45

well maybe

micha 06:21:57

i forget now

jethroksy 06:22:00

but building it locally gives no such task: (prod-run)

micha 06:22:18

i usually set the ENTRYPOINT in my dockerfile

jethroksy 06:22:47

so would you do ENTRYPOINT ["/usr/bin/boot", "prod-run"]

jethroksy 06:23:25

if it were ENTRYPOINT ["/usr/bin/boot", "repl"]

jethroksy 06:23:45

would CMD ["(go)"] run (go) in the repl for example?

micha 06:25:04

no, i don't see how it would do that

jethroksy 06:25:18

hmm alright

micha 06:25:21

i don't really understand the relationship between ENTRYPOINT and CMD

micha 06:25:32

it used to be that they were interchangeable

jethroksy 06:25:42

CMD provides the default params for ENTRYPOINT

jethroksy 06:25:48

if ENTRYPOINT is set

micha 06:26:28

where are the parens coming from?

micha 06:26:36

no such task: (prod-run)

micha 06:27:13

there is an option to the repl task btw

jethroksy 06:27:30

i have no idea

micha 06:27:31

boot repl -e '(go)' will work

micha 06:27:48

if go is referred into your build.boot namespace

jethroksy 06:29:05

changed Dockerfile to ENTRYPOINT ["/usr/bin/boot", "prod-run"]

jethroksy 06:29:24

still get that
clojure.lang.ExceptionInfo: java.lang.IllegalArgumentException: No such task (prod-run) data: {:file "/tmp/boot.user2351824110130883549.clj", :line 7}

micha 06:30:02

ah ok

micha 06:30:07

don't worry about the parens

micha 06:30:37

$ boot asdfasdf clojure.lang.ExceptionInfo: java.lang.IllegalArgumentException: No such task (asdfasdf)

jethroksy 06:30:54

so i would need to do all the ADD build.boot ... stuff

micha 06:31:24

i suppose so

micha 06:31:38

i have i think ADD . usually

alandipert 06:36:28

something looks amiss with show of late:
[email protected]:~$ BOOT_VERSION=2.4.2 boot -d javax.servlet/servlet-api:2.5 uber -j show -f Adding uberjar entries... servlet-api-2.5.jar [email protected]:~$ BOOT_VERSION=2.5.5 boot -d javax.servlet/servlet-api:2.5 uber -j show -f Adding uberjar entries... 69ca51af4e9a67a1027a7f95b52c3e8f-servlet-api-2.5.jar

micha 06:37:41

maybe it's -d related

alandipert 06:38:05

mm, yeah

micha 06:38:19

wait what is the correct behavior?

micha 06:38:23

that looks ok

micha 06:38:45

i guess it should have dependencies or something?

alandipert 06:38:57

servlet-api-2.5.jar vs 69ca51af4e9a67a1027a7f95b52c3e8f-servlet-api-2.5.jar

micha 06:39:08

oh that's just the name

micha 06:39:18

to prevent collisions

micha 06:39:26

the md5sum should be the same

alandipert 06:39:47

oh this is an uber improvement i missed?

alandipert 06:40:07

and yeah i think this is pre--d update

micha 06:40:07

the first part is the md5sum of the jar itself

micha 06:40:39

because if you have a bunch of jars in WEB-INF/lib/ there might be two with the same name

micha 06:41:21

is adding the md5sum to the name interfering with something?

alandipert 06:41:39

no i just didn't expect to see it

alandipert 06:42:00

thought it might be a toString regression on tmpfile or something

micha 06:42:22

ah lol

alandipert 06:42:35

but now i abide it

alandipert 06:42:36

mystery solved

be9 09:56:20

hm, I tried to upgrade to boot-reload 0.4.3 and it flunks with:
clojure.lang.ExceptionInfo: Could not locate adzerk/boot_reload__init.class or adzerk/boot_reload.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name. Changing 0.4.3 back to 0.4.2 works.

juhoteperi 09:59:29

Sorry, bad release

be9 10:00:14

well, it happens :simple_smile:

michal 11:26:31

hi. i’m trying to figure out how to exclude boot/core and adzerk/bootlaces dependencies from POMs generated by build-jar (from bootlaces). no luck so far. any hints?

martinklepsch 11:28:58

@michal: is it important to you that they're not loaded as transitive deps or is it really about not leaving any trace in Pom.xml?

michal 11:30:40

well, the latter would be preferable, but if it’s a problem it would be enough just to not enforce downloading these deps

martinklepsch 11:32:27

I can't tell you how to do the latter right now but if you add :scope "test" to a dependencies vector it will not be registered as a transitive dependency

michal 11:34:03

good point. i forgot about scopes. thanks Martin.

magomimmo 11:42:27

does the need of keeping :source-paths and :resource-paths separated has to do with scenarios in which you don’t want your source code be included in the jar or there are other use cases in which keeping them separated is recommended?

michal 11:46:49

i would rather say that resource-paths are directories bundled to resulting jar from where you can read your files (resources) in runtime and source-paths are used by boot just to locate source files to compile

martinklepsch 11:49:51

Also always helpful to look at the fileset roles documentation in the wiki

magomimmo 11:51:01

@martinklepsch: and re-reading more times :simple_smile:

martinklepsch 11:51:12

@magomimmo: in a cljs project you might build a zip at the end in which you don't want to include your sources

magomimmo 11:52:21

@martinklepsch: yes I know. I was listing in my head all the different scenarios. and the one cited by you is one of them

alandipert 16:06:09

@ragge: out of curiousity do you have any opinion on nix vs guix?

ragge 16:54:27

@alandipert: I've never used guix and have only read briefly about it so can't say much

ragge 17:03:38

@alandipert: but nix is great :simple_smile:

onetom 17:20:00

@jethroksy: @micha: looks like there is a lot of problem w docker, no?

onetom 17:20:11

has anyone tried to run clojure apps using ?

micha 17:20:40

i think @alandipert has experimented with this?

alandipert 17:23:37

i haven't tried that

jethroksy 18:56:34

@onetom: might try that tomorrow, but i think only I get docker problems :weary:

alandipert 19:37:28

hi @cloudroutine welcome :wave:

cloudroutine 19:38:31

i'm an interloper here to lurk and steal ideas :wink:

cloudroutine 19:41:46

I found out about boot for the first time today. I've been tasked to create a new build system for F#, so I'm surveying other languages to see what might be useful

martinklepsch 19:42:12

look no further hahaha

martinklepsch 19:42:23

& welcome :simple_smile: :wink:

cloudroutine 19:44:10

middleware-factories are a bit :confused:

dm3 19:49:28

should set-env! :dependencies be enough to pull the dependencies from the repl?

dm3 19:50:19

or is another action required?

martinklepsch 19:52:45

@dm3: should be enough. merge-env! might be better if you don't want to list all existing dependencies as well

martinklepsch 19:55:32

@cloudroutine: maybe middleware factories doesn't sound like much fun but middleware factories is not something users/devs think about much. I think it's just an attempt at describing what tasks are. You could also say they're higher order functions :simple_smile:

alandipert 19:56:25

@cloudroutine: middleware factories are a key part of how boot can be efficient up against Make-style dependency-directed things

alandipert 19:57:05

they provide a closure in which instances of a task can store mutable state - primarily, a cache

alandipert 19:57:36

although i can imagine other systems for providing instances of tasks places to store caches... the nice thing about generating a function is it (and the place it uses) are anonymous

cloudroutine 19:57:59

it seems like they're not particularly... well defined

micha 19:59:02

the contract is pretty simple

micha 19:59:12

everything else is left to the discretion of the user

micha 19:59:34

boot simply provides useful libraries

cloudroutine 19:59:37

haha yea "here's the part where who knows what'll happen" :grinning:

micha 19:59:39

but doesn't force you to use them

micha 19:59:54

that's exactly the point, in fact

micha 20:00:03

boot can't know what you will need in advance

micha 20:00:16

it gives you the means to program your build

cloudroutine 20:00:37

it's such a jargony name I wasn't sure if I was missing something about it

micha 20:00:41

the only contract is one of interop between tasks

micha 20:00:55

that's why middleware and fileset and so on

micha 20:01:11

to ensure that tasks can be composed uniformly

martinklepsch 20:01:35

@cloudroutine: would be curious what other interesting tools you stumble upon btw :simple_smile:

cloudroutine 20:01:50

do you know FAKE?

cloudroutine 20:03:41

it's not as strongly typed as i'd like

cloudroutine 20:04:50

I can kind of do what I need with it, but what I'm working now is going to end up being its sibling

alandipert 20:06:01

make and boot are definitely opposite ends of the spectrum.. but both the same in that they are systems for linearizing effects

alandipert 20:07:20

the boot way is, linearization happens like with any programming language - application via reducible expressions that can evaluate to a FileSet

alandipert 20:07:45

vs. make which is an algebra for describing the order things should happen to an implicit file system value

cloudroutine 20:08:28

in that sense FAKE is closer to boot than make

alandipert 20:08:37

in that case it sounds awesome, i'll check it out :simple_smile:

alandipert 20:08:52

thrown off by the name hehe

cloudroutine 20:09:06

what's currently holding it back is how strongly tied it is to the msbuild system

cloudroutine 20:09:15

so i'm tearing that out

cloudroutine 20:09:41

so people on osx and linux can finally get a decent non-ide experience with F#

micha 20:10:48

boot isn't tied to any build system

micha 20:10:53

boot isn't even really a build tool

martinklepsch 20:11:05

it's fairy dust

micha 20:11:27

it simply provides the bootstrapping necessary to run clojure on the jvm and install maven dependencies that that code needs

micha 20:11:54

and it provides libraries of its own that have useful functions for doing some common tasks with building clojure projects

micha 20:12:05

which you can use in your clojure program that boot will run

micha 20:12:15

your clojure program is the build tool

micha 20:13:55

this is all stuff provided by libraries, which you can use or not use

micha 20:14:13

and notice that it's just a process description

micha 20:14:21

there is nothing specific to building there

micha 20:14:41

that's a diagram of a sequential process

jaen 20:15:07

So boot is boot is just a monoid in category of build systems? ; d

cloudroutine 20:15:15

involving resource, source, and asset paths as a part of a virtual file system

micha 20:15:31

there is no virtual filesystem though

micha 20:15:45

there is an immutable fileset record type

micha 20:16:00

which is a description of the real filesystem basically

micha 20:16:12

but it is not a filesystem itself

micha 20:16:51

the resource, source, and asset paths is part of the bootstrapping process

micha 20:16:58

setting up the jvm classpath

cloudroutine 20:17:30

@jaen I guess it's just fancy plumbing :smile:

jaen 20:17:56

All programming is fancy plumbing to a certain degree ; d

micha 20:18:12

the real thing that boot does is get your code running, without an IDE or other tooling

micha 20:18:25

you can make a shebang script with boot as the interpreter for instance

micha 20:19:06

there is a lot of stuff that has to happen before clojure can run, especially around setting up the classpath

cloudroutine 20:19:12

> the real thing that boot does is get your code running, without an IDE or other tooling ^ this is what I think of when I think of build system, maybe we're thinking of different things

micha 20:19:27

well compare maven to boot, for example

micha 20:19:34

i have a page of clojure expressions

micha 20:19:38

i want to evaluate them

micha 20:19:45

they need dependencies to run

cloudroutine 20:19:48

I know zero about maven

micha 20:19:58

or any of them

micha 20:20:19

you can't do what boot does with make, for instance

micha 20:21:00

because your program might have dependencies that are not statically known

jaen 20:21:52

I guess one way to look at it

jaen 20:22:03

Is that boot is to build tools what xmonad is to tiling window managers.

cloudroutine 20:22:12

I haven't come across anything in boot so far that I couldn't implement in F#

jaen 20:22:17

Not a specific implementation, but a library that lets you build your own.

micha 20:23:03

there is nothing complicated about boot, i would be surprised if there was anything that couldn't be done in f#

micha 20:23:29

i mean other than some things we need to do with the classpath

micha 20:23:46

which is JVM and Clojure specific type of problems

cloudroutine 20:24:49

i'm not sure if I want to do something like the pods or not

cloudroutine 20:27:51

it might be useful to have that kind of isolation mechanism, but I don't think it'd need to be a strickly enforced since F# package manager is pretty good at resolving dependencies

micha 20:28:23

the issue pods solve is when you have conflicts that can't be resolved

micha 20:28:51

like when you actually need a different version of a dependency in one part of the program and a different one in the other

micha 20:29:01

this is very common with build tasks, for example

cloudroutine 20:30:17

I haven't programmed in java for over 10 years, it has binding redirects right?

micha 20:31:31

not sure what that is

micha 20:31:41

i don't think java has them :simple_smile:

cloudroutine 20:32:15

> when you actually need a different version of a dependency in one part of the program and a different one in the other ^ when this happens you say 'no I want you to use the other one instead'

micha 20:32:44

and you are then going to have to fix all the code that is now broken in any dependencies that need the other version

micha 20:33:01

which is impractical because it may be some huge project like apache commons

micha 20:33:05

or guava or whatever

micha 20:33:09

thousands of classes

cloudroutine 20:34:00

hmm this seems like a much more of a java specific issue

micha 20:34:18

this is a common problem in clojure, where you have dependencies that are only needed at build time, but not at runtime, like the cljs compiler for example, which depends on some rally huge google project, which depends on a huge apache project, which depends on an old version of some http client

micha 20:34:37

in your actual application you also need a http client

micha 20:34:43

of an incompatible version

cloudroutine 20:34:49

and there isn't a great way to do transitive dependency resolution?

micha 20:34:54

no there is

micha 20:35:01

but it's not a problem that can be solved that way

micha 20:35:12

the google thing needs version 0.1 for example

micha 20:35:18

and your application needs version 5.7

micha 20:35:24

and the two are not compatible

micha 20:35:30

so you can't just"pick the right one"

micha 20:35:47

because if you do then you will break either one or the other

micha 20:36:02

this is extremely common with build tasks

micha 20:36:20

so in boot if you make a task, you're expected to load all your dependencies into a pod

cloudroutine 20:36:20

yea so they're in separate dependency chains

micha 20:36:39

so your dependencies are isolated from the rest of the environment

micha 20:36:54

boot tasks have no transitive dependencies

micha 20:37:05

they pull their deps in at runtime and install them in a pod

cloudroutine 20:37:21

you couldn't load both 0.1 and 5.7 into the same domain?

micha 20:37:42

no, how could you?

cloudroutine 20:37:54

you can do that in .net

micha 20:38:09

if i do new Foo();, how does it know which version of Foo to use?

cloudroutine 20:38:29

you extern alias it

micha 20:38:47

what about code that you don't control?

micha 20:38:54

like this dependency is already compiled

micha 20:38:59

and i can't extern alias anything

micha 20:39:12

that's the real problem

micha 20:39:16

not your own code

micha 20:40:09

also manually managing transitive dependencies is not what i want

micha 20:40:27

pods allow the simplest, most naive way to work reliably

micha 20:40:52

don't think about how to merge conflicting dependency graphs, just isolate them in pods

micha 20:40:55

job done

micha 20:41:56

it's extremely rare in boot to see issues with build task transitive deps

cloudroutine 20:44:44

which seems like a nice thing about pods, I'm wondering if I could do something similar with compilation units for a more modular approach to assembly construction

cloudroutine 20:47:47

which i guess would fall somewhere in between the boot and cargo approach

juhoteperi 20:47:52

What is the package manager for f#? Paket?

juhoteperi 20:48:50

From readme I understand that it works like Maven, it always selects a single version of dependency to load if there are multiple dependencies to it

juhoteperi 20:49:06

> Even more importantly: If two packages reference conflicting versions of a package, NuGet will silently take the latest version (read more). You have no control over this process.

> Paket on the other hand maintains this information on a consistent and stable basis within the paket.lock file in the solution root. This file, together with the paket.dependencies file enables you to determine exactly what's happening with your dependencies.

juhoteperi 20:50:43

Groups look maybe a bit like Maven scopes

juhoteperi 20:52:08

At least in a sense that they can be used to separate build and test deps

cloudroutine 20:52:41

and dependencies that often aren't involved in the compilation process at all

cloudroutine 20:53:07

like FSharp.Formatting and FAKE

juhoteperi 20:55:25

So two groups can have different versions of a dependency, but I'm not sure when or how groups are used. Can one use both versions in one program?

juhoteperi 20:55:58

Or well, that's probably not necessary anyway.

cloudroutine 20:58:36

there's no way to fully escape from a project style system in F# since the compiler needs that to do proper type resolution and constraint analysis

juhoteperi 20:59:36

In JVM it's not possible to remove stuff from classpath once they have been added there, so Boot tasks don't usually depend on anything and instead load their dependencies into pods. This way task dependencies don't leak into project classpath.

juhoteperi 20:59:54

Looks like groups allow having separate dependency graph for build dependencies so there is no the same problem with Paket.

cloudroutine 21:00:51

yea i had no idea this was such an issue in jvm land

cloudroutine 21:01:46

rust takes the total opposite approach, just give us all the source and we'll recompile everything

cloudroutine 21:02:18

which doesn't seem sustainable long term

juhoteperi 21:03:25

Well all Clojure and ClojureScript libraries are distributed in sourcecode

cloudroutine 21:04:07

can't escape those .jars though :smile:

juhoteperi 21:04:59

But that doesn't help at all if one library has breaking changes and some parts require the new version and some old

juhoteperi 21:05:52

But at least it prevents Scala like dependency hell where libs have to compiled to every Scala version

micha 21:06:13

i never have dependency hell problems in jvmland

cloudroutine 21:06:19

ugh Scala.... X_X

micha 21:06:27

because we at least have a stable, immutable dependency graph

micha 21:06:53

but with nodejs and ruby i'm always getting broken builds when some new version of a transitive dep comes out

cloudroutine 21:07:17

it's miserable

juhoteperi 21:07:37

The Scala's problems are not caused by JVM.

cloudroutine 21:08:27

they're primarily of it's own making

cloudroutine 21:09:20

it's an odd type system

juhoteperi 21:09:21

When 2.10 came out we had to wait like 4 months before Slick was updated for it :smile:

juhoteperi 21:10:04

And Slick library is maintained by Typesafe.

cloudroutine 21:10:49

it's hard to put a lot of faith in them based on prior decisions

cloudroutine 21:10:59

but at least they seem to be improving

jaen 21:13:30

Well, they want to unify subtyping with parametric polymorphism, which IIRC is ugly even from the theoretical standpoint, so not surprising they have problems : V

cloudroutine 21:14:12

as Simon Peyton Jones likes to put it, they're stuck in the swamp

jaen 21:14:55

Yeah, most of my knowledge regarding that comes from P ;

jaen 21:18:28

That's dependently typed, right?

cloudroutine 21:18:51

but with a lot less fussing than idris

jaen 21:19:49

I'm always like "whoa you can type quicksort such that it will verify it sorts" but then I'm like "that's way over my head" and I just kinda made a stop at Clojure on my road to Haskell and beyond ; d

cloudroutine 21:23:38

i wish ClojureCLR wasn't so terrible :disappointed:

alandipert 21:26:28

what's bad about it?

cloudroutine 21:26:54

slow, buggy, and not well supported

alandipert 21:28:29

sounds full of potential

cloudroutine 21:31:42

it'd actually be a lot simpler to implement the clojure compiler in F# than the C# approach they took using the Dynamic Language Runtime

cloudroutine 21:34:57

it's my 2nd favorite LISP after sweet-racket

jaen 21:46:35

Oooh, that looks pretty nice

cloudroutine 21:48:31

homoiconic without the cruft :wink:

donmullen 21:57:26

@cloudroutine: as you are looking at build tools - I have never heard of this until today : - Facebook’s tool - supports multiple languages / ios / android. One of the cljs + native mobile guys is looking at using it.

donmullen 21:58:20

Some potentially interesting ideas there for boot - but assume all you #boot devs have seen it before.

cloudroutine 21:59:11

which ideas do you find the most interesting?

donmullen 22:03:06

They have worked hard on speed - don’t like that it is declarative - where boot embraces code. Lots of caching - first order dependencies. Some sophisticated stuff for mobile like Android Dex merging. Haven’t looked in depth yet - but some mobile devs are looking closer.

donmullen 22:04:08

Seems like a boot-buck task would be interesting add for mobile dev.

micha 22:04:37

facebook knows which buttons to press when releasing open source software

micha 22:04:56

facebook rule #1: must have perf announcement

micha 22:05:18

it's the problem you didn't even know you had, solved!

micha 22:06:16

imagine how much more perf we'd have if we added anouther 10x of boilerplate and spaghetti code!

micha 22:07:28

it's so fast your baseball cap turns backwards

donmullen 22:07:49

Yeah - well we are using gradle a good bit @ LGS - VERY SLOW. This blog indicates much faster builds :

donmullen 22:08:19

Especially for native - where there is not as much active live reload going on - makes a big difference.

micha 22:08:38

boot does extensive caching of immutable things

micha 22:08:49

like uberjar stuff etc

donmullen 22:08:57

Absolutely not thinking buck would replace boot - to be clear.

micha 22:09:01

so you can build a massive uberjar in < 2s

micha 22:09:46

i guess they just push my buttons, those facebook guys :simple_smile:

donmullen 22:10:06

:rage: :smiling_imp:

micha 22:11:02


micha 22:11:23