This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-17
Channels
- # bangalore-clj (2)
- # beginners (202)
- # boot (18)
- # cljs-dev (8)
- # cljsjs (7)
- # cljsrn (4)
- # clojars (2)
- # clojure (401)
- # clojure-boston (2)
- # clojure-dusseldorf (1)
- # clojure-gamedev (36)
- # clojure-greece (2)
- # clojure-italy (1)
- # clojure-russia (16)
- # clojure-spec (27)
- # clojure-uk (7)
- # clojurescript (68)
- # core-async (16)
- # cursive (25)
- # datascript (1)
- # datomic (34)
- # funcool (1)
- # hoplon (1)
- # interop (1)
- # klipse (1)
- # leiningen (2)
- # lumo (75)
- # off-topic (17)
- # om-next (2)
- # onyx (66)
- # re-frame (18)
- # reagent (2)
- # ring-swagger (11)
- # spacemacs (1)
- # specter (1)
- # timbre (3)
- # untangled (48)
- # yada (7)
Compiling with direct linking means an var invocation makes a static method call instead of derefing the var
So the var is not used at all in the compiled code
dynamic and redef vars are not direct linked
redef vars are not dynamic
Hard to help without a question
@alexmiller Right, I checked the source. So ^:redef redef just says keep the Var, but its a non dynamic var, and ^:dynamic says keep the Var, but later will make it a dynamic Var. So I assume you can have ^:dynamic and ^:redef together without issue.
Yes, although there's no reason to
So the symbol lookup will still happen with direct linking? So unmap and intern would still work?
If I understand your question correctly, no
The compiled code is a hard coded static method invocation
Oh, hum. I've been diving into the Clojure source. So I got it to understand that symbols are kept in a map. So I was assuming each function call in Clojure would first lookup that symbol in the map, and than deref the Var. And looking at the direct-linking code, it looked like it was just replacing the value of the map-entry of the symbol by the IFn itself. Which would mean that Clojure would still have to lookup in the map to find the function no?
Sorry I mean there is no lookup with direct linking
Hm, so if i had to ask one question, it would be about this: > And you can pull tools out like about right now and do this for yourselves, so the important thing to note is that the Clojure state model is available at the systems level. You do it this way, and the only thing you have to do is put names on your values. What’s a good name for a value? What does he mean by the Clojure state model being available at the systems level? Is he talking about how (for example) Datomic entities are versioned and immutable?
Okay, cool. So direct linking will be completely direct. Which, is great. Thanks. I guess I'll need to loo through the compiler code more so to understand how it does that.
@drewverlee in short, yes :)
I believe the general notion is that you need the ability to have values with names, and the ability to safely apply a function that transforms the old value to a new value
And safely requires CAS, which you can get at the system level with something like Zookeeper, or DyanmoDB, or a db transaction
(All of which Datomic leverages for different storages)
there's only one real linter I know of, and it does no type checking
(that linter is eastwood) https://github.com/jonase/eastwood
what surprises me is that sexp is so simple, but the clojure analyzer output is so complex
there's also a typing extension for clojure https://github.com/clojure/core.typed
both use tools.analyzer.jvm https://github.com/clojure/tools.analyzer.jvm
@qqq writing a simple lisp is easy, writing a fast lisp is hard. Clojure does the latter but in turn leans more on the analyzer. And there's even more it could do, at the cost of compilation speed, and compiler complexity.
No, it was written later. ClojureScript uses it though
Is there a coverage reporting tool for clojure that reports branch coverage as well as line coverage? It looks like cloverage doesn’t try to understand branches, per se, but it does track which forms are evaluated and which are not.
is there a more idiomatic way of doing the following? (fairly new to FP and quite new to clojure):
feels very OO, guessing theres a better way
You wouldn't use the getters in Clojure...
set-price-per-item
would just be an assoc
operation.
In fact all those setters would just be assoc
calls in the client code.
Since data is immutable, all that get/set encapsulation is not considered necessary.
You'll hear people say "In Clojure, the data is the API."
I'd probably only have make-invoice
(rename of new-invoice
) and calculate-invoice-amount
(rename of get-invoice-amount
)...
ah wow that cleaned it up quite a bit already 🙂
Yep- the thing with Java, and OO in general, is that it leads to quite a lot of boilerplate.
I wouldn't have the setters -- sends the wrong message: you're not really "setting" anything... you're creating a new invoice data structure with one or more elements having different values.
This is the sort of thing that's the biggest mindset when you're coming from an OOP background.
The functional approach requires less code- you have less need for an interface to your data when it can't mutate.
@tagore you're right, all that boilerplate is one of the reasons ive been trying to make the shift to clojure in the first place 😅
@tbaldridge : (re complexity of clojure analyzer) -- I agree that writing a fast lisp is hard. But I don't see why that implies the syntactical analyser has to be complicated -- I could totally understand if the compiler / JVM bytecode emitter was complicated -- but the analyzer seems like a weird place to be complicated.
@seancorfield thank you for the tips, the setters def aren't necessary at all since they aren't even used
FP has an analogue to the uniform access principle, and in some cases a bit of boilerplate is worthwhile, either to delay binding, or to make access uniform, IMHO.
@tagore yeah i can see how that would be particularly applicable to code bases where the underlying implementation for a field (be it direct access or computation) is liable to change
Such change is much less common in the real world than a lot of people seem to think, IMO. 😐 Based on doing C++ and Java since '92 (before switching to Clojure around six years ago).
i see both forms frequently but don't personally deal with change often if at all, you're right
so much better!
You'll get used to writing a lot less code 🙂
Well, I'm known for my love of Perlisisms, and one of my favorites is "Functions delay binding; data structures induce binding. Moral: Structure data late in the programming process."
i'm fond of raymond hettinger's "there has to be a better way"
@qqq Clojure does quite a number of optimizations, such as inlining forms like clojure.core/+, and turning some calls like instance? into single-bytecode intrinsics. Add to that, that Clojure is statically-bound, and there's a large number of things that the analyzer can do to make code faster.
but @coltonoscopy there are reasons to put things behind abstraction barriers. One thing I'd really strongly recommend to anyone stating with a Lisp is going through at least the first two chapters of SICP.
Things have changed since it was written, and its style is not always what people would consider best these days, but it's woth understanding the approach it outlines.
am on page 22! 🙂
i think i see where youre coming from with the perlis quote
more flexibility that way
i'm gonna go out on a limb and say it's the list 😅
Another Perlisism: "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures."
that one ive heard recently
i like that one
The main data structure in Clojure for "objects" is the hash map. Followed by vectors for indexable data. Lists aren't used as much -- certainly not as much as other Lisps.
That's partly because Clojure focuses on a sequence abstraction, with concrete collections behind that.
i have noticed that, i haven't seen lists used much for programming besides in macros. coming from python and lua, hash maps as the workhorse makes sense to me
@seancorfield Yes- and as a practical matter that's a fine decision.
@didibus agreed, implemented in the latest change, thank you 🙂 @seancorfield recommended as much
What I've found, as I've continued to work with Clojure in production, is that I focus more and more on data design, rather than going in function-first.
We're using clojure.spec heavily at work and that fits very nicely with a data-first design approach.
@seancorfield +1 to that. And sadly, scheme has only one data structure, makes it hard to get the data design "right"
@seancorfield Yes, but... using clojure.spec is very far to the practical side of the continuum, I think.
@tagore not sure what you mean about clojure.spec?
I think it's also very useful to think about programming from a very impractical point.
first i've seen clojure.spec @seancorfield but i have it open in a new tab and will add it to my reading list, thanks 🙂
For instance SICP introduces almost nothing other than lists and functions in its first hundred pages.
@gerred No, not yet.
@tagore SICP is a great learning tool but not really a good basis for practical, production code.
The world has moved on a lot over those decades.
@seancorfield I agree, entirely.
I think Clojure's real "win" is that it's a very practical language.
@seancorfield That said, I think there are things tht can be learned from SICP that are very valuable even when writing production code.
Though I think it would probably be a mistake to try to compute with Church numerals in production 😉
I've found that the amount of cruft you have to wade through in SICP, kindof offsets the gains.
"production code" often means "how do I SQL?", "How do I generate HTML", and not 2 hours on recursive vs iterative algorithms.
I recommend the MIT video lecture series version of SICP as a way to learn about FP. The book is... an interesting piece of reference material.
We consider Clojure practical enough to have made it our primary language a few years ago (after it being our secondary language since 2011) and we have over 50K lines of Clojure in production these days.
im curious how many lines that would be in a language like java or C# 😅
My gut says Clojure is typically 2-4x less code than Java but can be up to 10x less in some cases.
my understanding is that is what javascript is
written to look like java 🙂
or at least, what the creator wanted it to be
obviously its not quite there
i just can't wait until ES6 is as adopted as ES5 was prior to 2015
@coltonoscopy Yes, but there's so much stuff in JS that you could use...
@coltonoscopy And as for es20xx there is always Babel, or other transpilers.
Or there's ClojureScript -- which gives a much better experience than any version of JS 🙂
true @seancorfield 🙂 i fear it will take a while to catch on though, so ES6 is at least a nice refinement of JS for the time being
@tagore indeed re: babel, but even that is a turn-off for some people
I dislike JS enough to avoid it at all costs.
@seancorfield Indeed- I would far prefer clojurescript to JS.
when we get full browser compatibility and people don't need to futz with transpilation, it'll be a nice day
@seancorfield yeah JS at least in its ES5 incarnation isnt the greatest lang
ES6 is def a step up imo though 🙂
@coltonoscopy That's really not a big concerne, IMHO. Compiling to JS is easy enough.
@tagore it's not a concern for you (or to me) but for many people it is 🙂
That's a bit like saying "Scala is a better Java" so you should be OK using it... instead of just going straight to Clojure 🙂
(sorry Scala!)
oh im not saying you should start using it, just that its an improvement and having to deal with it if the situation arises is less painful 🙂
im around it all the time
@seancorfield I agree- if it were up to me we'd use Clojurescript, and not JS, where I work.
not necessarily by choice
(and, yes, I have used Scala in production so I feel justified in criticizing it)
@seancorfield But it's not the browser support bit that matters. That's easy to fix by compiling.
its easy to fix by transpiling but i can speak from experience when i say people are turned off by the fact that you have to go through a transpilation bit vs just loading the code into the browser via a script tag like you would do with ES5 🙂
when i say i speak from experience, i mean i work with plenty of people (mainly more experienced with ES5) who arent a fan
@coltonoscopy Hmm- has been along time since I used a script tag directly 😉.
Oh, I'm sure folks who use JS today wouldn't see the value in using a better transpiled language... blub... 🙂
This is probably getting all a bit off-topic for #clojure tho' so we should probably move to #other-languages or #off-topic at this point!
it may just be the work bubble i'm in
@seancorfield I completely agree with you- I wish we'd just use clojurescript at my place of business, but... it would be a hard sell
react and redux are big now and from what i understand thats a nice functional paradigm shift
dont have a lot of firsthand exp with em though
FWIW, at World Singles we went with JS and React.js rather than ClojureScript because it was easier to build a team to do that on the timeline we had last year.
But our front end team like the look of ClojureScript so who knows what our future may hold.
Yeah, Redux is.. well honestly I think the whole concept was lifted from re-frame without attribution, but...
(we did a ClojureScript p.o.c. a few years back but the tooling was so rough we struggled to get a good workflow going, so we set it aside for a while)
@tagore Redux predates re-frame I believe...
The thing is, no matter how clever your framework, js is still the underlying language, and it has problems.
Javascript functions can't distinguish between being called with no arguments and being passed undefined as a single argument.
yeah thats a weird design decision
JS, where adding {}
and []
produces... c'mon... who knows without trying it out?
lolol yeah the "what the javascript" vid was great
and wat man 😄
Yep- the first rule of JS is "be very defensive." The second rule is "you weren't defensive enough."
after all these years, I'm finally starting to get how to use spec / :pre in the body of a function, we do certain things to an argument xyz ; and in doing so, we assume that xyz has certain structure well, the spec should encode this structure, thus assuring that if the arg passes the given spec, the function won't throw exception due to this particular arg
I did mention Eiffel earlier, but there may have been more than one person that mentioend Eiffel earlier.
So unless clojure code is easier to analyze than Idris code, I don't see how Spectrum can be practically useful right now.
Also, specs are probably going to allow you to catch some of the bugs dependant types would, while requiring less effort from the programmer.
You wouldn't be able to fully prove 100% the for all case like in proof languages, that's the trade off
Spectrum can never be as good as Idris, unless Clojure forces everything to be speced, even all Java code.
But in terms of being practical, spectrum can already catch errors that even haskell would not, at compile time
And of course the biggest source of software defects is that... your clients aren't very good at telling you what they want (and largely don't even know what they want,) and you're not very good at finding out what they want.
@tagore: you're changing the argument, I want to see @didibus 's example of spectrum beating haskell 🙂
With spectrum in Clojure
(let [a 0
b 10
c (/ b a)]
(println c))
will be caught at compile time if you spec this properlyLiquidHaskell which does dependant type would also be able to catch it at compile time
Anyways, spec can do this because at compile time it can validate literals and specs. So for literals, it'll check if they are valid to the specs they are used in. And it'll validate specs against other specs
Not sure how it does the latter, that's where I think it would be hard to show that one spec is incompatible with another
But in my example, it just associates that a is 0, and when it conforms it with the spec of /
which says #(not= 0 secondarg) that fails to conform
So, obviously depending how you spec /
, how restricted you make it, it could not catch it. But dependent types suffer from this same problem as far as I know, so it's possible to have false positives with dependent types.
Or, it might be better to say refinement types. I don't know enough about Idris and true dependent types. But I think Spectrum could in theory equal LiquidHaskell, given a fully specced clojure code base, and enough work going in spectrum
qqq: I think it's not ready for practical use yet. It's not covering all specs, and I've seen it crash when running on some code base. It's still in alpha. But when it works, it's pretty magical. I'll definitly use it once it has addressed those issues. I think it could be better to think of it as a very good static analyzer, simply because of the nature of Clojure, not everything will be specced. When things are specced though, it has the potential of catching quite a lot of issues, some that even Hakell would miss.
I'd recommend trying it out though, it's pretty simple to use, just one require and you run spectrum/check, done.
@U050SC7SV: thanks! I keep on forgeting about coll-of :kind arg
https://clojure.org/reference/special_forms#def says "Creates and interns or locates a global var with the name of symbol and a namespace of the value of the current namespace (ns)." i don't get the "global" part.
fossifoo: Global means that the var can be accessed globally from everywhere that requires it. It will always be inside a namespace, and there can only be one namespace/symbol pair, so if you intern that same pair again, it would replace the old Var.
I think you're getting confused with the fact that when inside a namespace, Clojure lets you refer to symbols without using a namespace. That's just convenience, under the good, it'll just use the current namespace. There is always a namespace. Even in a repl, it'll take the user namespace if none is specified.
Also, global does not mean can be referred to without having to require it. In the same namespace you don't, they get interned automatically. But in another namespace you could still access that global by simply requiring it: (:require [namespace :refer [symbol]]
. You can not do that with a local or a function argument.
does "global" in this context mean that there is only ever one var with the location "namespace/symbol"?
@tagore @seancorfield re-frame predated Redux by about half a year. But Redux's principle influence was the Elm Architecture. As i remember it, the idea for Redux middleware came indirectly from re-frame.
@mikethompson thanks for the correction Mike. I thought that when my team had first tried building stuff with Om and then Reagent, that re-frame hadn't yet appeared (maybe early 2015?) but that Redux existed. So I'm misremembering some parts of that.
@mikethompson before redux there were many flux inspired libraries in JS. I think it’s difficult to sort out who inspired who after the fact
I think Mike might know what he was inspired by
hey guys, I'm trying to create a logger component, when i try to fetch the component instance inside the logger's helper functions it's empty, http://dpaste.com/070EMAF
@jonas Yes, indeed there was a Cambrian explosion of Flux derivatives. And, because of David Nolen's OM, the idea of immutability was also thrust into the JS zeitgeist. But, from memory. the Redux authors did credit the Elm Architecture for a lot of their inspiration particularly around Action -> Model -> Model
(foldp). I was just trying to set the record stright on two points: (1) re-frame was released well before Redux and (2) despite that I'm not sure that re-frame was much of an influence on Redux other than to suggest using middleware to wrap event handlers. At least that's how I remember it.
argh, trying to write this relational db in clojure, without type checking, is killing me
Oh, and actually, you could also use core.typed. It'll type check your code no problem. It'll be easier to use then spec I think, because specs tend to define more than what normal type systems require.
@qqq why write yet another relational db? anyway is a type checked language not a natural fit for that?
of course you could verify types in clojure too, e.g. satisfies?
back to tonight's internals discussion for a sec: just making sure: are volatile
and static
concepts ingrained/implemented at the JVM and the bytecode specification level? clojure docs sporadically mention them as vehicles for its underlying implementation and as an optional way to hinge values in a namespace, respectively. Most docs about them are from the Java world, so it is a little hard to trace how the concepts trace back or rely on the Java implementation of these concepts v.s. clojure accessing that functionality directly from the JVM, v.s. some other interpretation.
Does anyone have the exact story on that?
So, yes, volatile is a feature of the JVM, not something custom implemented by Clojure or Java.
But Clojure being implemented in Java, it accesses volatile by using Java. The volatile! function is an interop call to Java
@didbus the docs for Vars (or Refs) just say they use a JVM or Java static, that's all, IIRC
btw, in general, you can usually expect clojure to directly use the jvm feature for something, with a thin wrapper if additional functionality is needed, but as I can recall currently never actually hiding the underlying things
this is in contrast to scala, which has a bunch of language constructs that are not reified on a vm level
@noisesmith thanks for these comments, good to learn.
@qqq not sure I follow. In-memory and relational do not need to go together. There's already in-memory relational db's. so I wonder what is the motivation?
@matan: with all due respect, unless you understand that paper and want the system it proposes, what I'm doing makes no sense
a cool feature is clojure.repl/apropos - clojure.repl will usually be in scope by default in a new repl (in your initial namespace at least)
justin@S: ~$ rlwrap java -jar ~/bin/clojure-1.9.0-alpha15.jar
Clojure 1.9.0-alpha15
(ins)user=> (apropos #"^\*.*\*$") ; find things that are earmuffed
(clojure.core/*agent* clojure.core/*allow-unresolved-vars* clojure.core/*assert* clojure.core/*clojure-version* clojure.core/*command-line-args* clojure.core/*compile-files* clojure.core/*compile-path* clojure.core/*compiler-options* clojure.core/*data-readers* clojure.core/*default-data-reader-fn* clojure.core/*err* clojure.core/*file* clojure.core/*flush-on-newline* clojure.core/*fn-loader* clojure.core/*in* clojure.core/*math-context* clojure.core/*ns* clojure.core/*out* clojure.core/*print-dup* clojure.core/*print-length* clojure.core/*print-level* clojure.core/*print-meta* clojure.core/*print-namespace-maps* clojure.core/*print-readably* clojure.core/*read-eval* clojure.core/*source-path* clojure.core/*suppress-read* clojure.core/*unchecked-math* clojure.core/*use-context-classloader* clojure.core/*verbose-defrecords* clojure.core/*warn-on-reflection* clojure.core.server/*session* clojure.java.browse/*open-url-script* clojure.java.javadoc/*core-java-api* clojure.java.javadoc/*feeling-lucky* clojure.java.javadoc/*feeling-lucky-url* clojure.java.javadoc/*local-javadocs* clojure.java.javadoc/*remote-javadocs* clojure.java.shell/*sh-dir* clojure.java.shell/*sh-env* clojure.pprint/*print-base* clojure.pprint/*print-miser-width* clojure.pprint/*print-pprint-dispatch* clojure.pprint/*print-pretty* clojure.pprint/*print-radix* clojure.pprint/*print-right-margin* clojure.pprint/*print-suppress-namespaces* clojure.spec/*coll-check-limit* clojure.spec/*coll-error-limit* clojure.spec/*compile-asserts* clojure.spec/*explain-out* clojure.spec/*fspec-iterations* clojure.spec/*recursion-limit*)
user=>
granted, some are not configs that are for controlling thread-local behaviors, but all the thread-local configs should be in that list
what is the advantage of transduce
over normal function with ->>
? Why use it? Do you use it? When? My first impression is: it makes easy things harder without additional advantages, but maybe i miss something.
faster performance when you have multiple operations chained together in your ->>
dysfun answered my question on irc:
(filter #(re-find #"^\*.+\*$" (str %)) (keys (ns-publics 'clojure.core)))
so transduce
is faster then ->>
? How much faster? Who use it in practice and when? Just i am asking to make a decision it is worth to try implement it in solutions or not really.
qqq: They're equivalent, but s/cat will let you name each element, so it can be conformed into a key/value map, and can help provide more documentation to others.
@qqq did you look on examples https://clojure.org/guides/spec ?
i would say in practice i don’t use it (probably because i work with different type of data)
but from this doc explanation for s/tuple
Designed for fixed size with known positional "fields"
and s/cat
Conforms to map with named keys based on the cat tags
BTW first time when i read this doc i miss multi-spec
in some way… this one could be very important
@kwladyka perhaps https://clojure.org/guides/faq#transducers_vs_seqs will help
@alexmiller thx, i am going to read it
@doglooksgood - Quartzite is good: http://clojurequartz.info/articles/getting_started.html#using_cron_expression_schedules
I've just tried quartzite, however I can't find a way to set concurrent
execution to false
.
There is also http://docs.caudate.me/hara/hara-io-scheduler.html, which is simpler.
😂 I was using http://hara.io before I tried quartzite, I found it a little buggy, I have both web server and scheduler running, once a http request happen, the scheduler will stop, very strange. but it looks have a upgrade version, I'll have a try
That is strange, considering that the scheduler runs on it's own thread (or did when I tried it a couple of years ago)
I've just updated version, the problem still exists, looks like it's not stable:disappointed: or I'm using it in a wrong way.
hi all, looking for some hints on the fastest possible way to read a file into a byte array. Current attempt (using clj-mmap):
(defn file-to-byte-array ^bytes [file-name]
(with-open [mapped-file (mmap/get-mmap file-name)]
(mmap/get-bytes mapped-file 0 (.size mapped-file))))
which for some reason still takes longer than it should (40ms from a hot state for my 40MB sample file. A memory mapped file, if things works as they should, should be more or less instantaneous)not sure if OSX is playing games with me here, I seem to recollect this was very fast on linux
also, using the above method as in:
(defn some-fn [file-name]
(let [data (file-to-byte-array file-name)
...
produces the following java code (decompiled):
Object data = var10000.invoke(var10001);
I thought declaring the return type as ^bytes
should be enough for the compiler to figure out we are dealing with a byte array, not Object
?mbjarland: you can set warn-on-reflection to true to have clojure tells you where it is needing to use reflection
still learning to pay attention to the newfangled thread thingmajiggies in slack, thanks for the pointers. I have seen those settings documented, but failed to apply them to reality. Will give it a whirl. I would have still thought that defining a return value type hint would be enough, but we'll see what the warnings give me
ok so the following code:
(ns clojure-license-plates.typing
(:require [clj-mmap :as mmap])
(:gen-class)
(:import (clj_mmap Mmap)))
(set! *unchecked-math* :warn-on-boxed)
(set! *warn-on-reflection* true)
(defn file-to-byte-array ^bytes [file-name]
(with-open [mapped-file (^Mmap mmap/get-mmap file-name)]
(mmap/get-bytes mapped-file 0 (.size mapped-file))))
(defn test-type-warning [file-name]
(let [data (file-to-byte-array file-name)]
"foo"))
produces no warnings and still outputs the following decompiled java code for the test-type-warning
function:
public static Object invokeStatic(Object file_name) {
IFn var10000 = (IFn)const__0.getRawRoot();
Object var10001 = file_name;
file_name = null;
Object data = var10000.invoke(var10001);
return "foo";
}
it still compiles to Object data = ...
, and it does so even if I change the let to let [^bytes data (file...
seems very strange to me, if neither the function return type hint or a direct type hint on the let local binding works, then how do we produce a primitive byte array without actually calling byte-array
?
@mbjarland There's no reflection though
I don't think having data declared as Object is a problem, it would be later when you used that return value. Try having something use the return and see if that has to resort to reflection.
on the upside this is part serious and part a competition between a few languages (mainly c++, kotlin, F#, clojure) with a number of my more ocd friends on solving the following problem (https://gist.github.com/mrange/ea0b2ab04238509dc4fdccf422c76c7a), and so far clojure (with one call-out to java…which is ok, we are on the JVM for a reason) is neck on neck with the fastest solution in c++, have to take into account things like cpu cache locality etc
talking with myself here : ) just verified, loading the same file on ubuntu with mmap takes 10ms vs 40ms on OSX with comparable cpu, disk, etc
@mbjarland check this http://clojure.wladyka.eu/posts-output/2015-08-24-how-to-improve-algorithm-speed.html - let me know if it is useful for you
Asked this in #leiningen but got crickets. Hopefully people won't mind me asking in here. Has anybody adopted 's advice about ditching semantic versioning yet? Is there an emerging standard for cutting a release with a date string for the version id? Maybe something like "#date-fmt yyMMddHHmmss" in the project.clj which could be replaced at "release time" by running it through the java SimpleDateFormatter?
It was in the talk he gave at the conj this year: https://www.youtube.com/watch?v=oyLBGkS5ICk
I don’t think anyone has figured out the right approach yet in response to that.
Part of what he was advocating was never breaking an API across versions — only adding to it. If you want to break the API, you need to change the artifact name instead.
So changing from “semantic versions” to dates doesn’t really address anything (beyond just creating a monotonically increasing version number).
I like the minor/patch part of semantic versioning. I think that’s still relevant. The major version also seems nice for indicating a “large” change, even if it’s not breaking.
I also wrote https://github.com/weavejester/lein-version-script some years ago for versioning based off commit number.
I agree. There are a lot of expectations around version numbers these days so I don’t think they are inherently “bad” in any way. I agree somewhat with on not breaking APIs, given that we can’t have more than one version of the same artifact in our projects… but changing the artifact name to reflect breaking API “versions” seems a bit hacky so I don’t know what we can do better there.
Except maybe think more about our API in the first place and never actually break it 🙂
The alternative he proposed was to just have a new namespace for wholesale changes. Don't necessarily need a new artifact
The elm package manager enforces semantic versioning by checking compatibility, perhaps clojure could do something similar with specs across different major/minor versions.
Ah but lein-version-script looks like it would satisfy my requirement. Thanks @weavejester!
Hello all, I have a question about defmulti
(defmulti update-ticket (fn[url user password ticket-info] ???))
(defmethod update-ticket "Incident" [url user password ticket-info] (update-incident url user password ticket-info))
(defmethod update-ticket "Request" [url user password ticket-info] (update-request url user password ticket-info))
and ticket-info has {"ticket-type" "Incident" ...} {"ticket-type" "Request" ...} ?Does anyone have any suggestions on working with unsigned bytes in Clojure (and Java)? I’m trying to do some crypto exercises, and keep butting into issues with a) Clojure defaulting to Longs and b) Java having only signed bytes. I looked at ztellman byte-streams lib, but that’s more about conversion and less about working with the results.
@kingmob the useful thing is that if you force unchecked math the basic arithmetic operators and bitwise operations still do the right things
that is, java interprets the bits differently, but the bits have the right contents
@noisesmith The issue is less with things like bit-xor, but that, when a negative num gets converted to Long, the sign bit changes location
(goes from bit 8 to bit 64…)
right, you need to do an unchecked bitwise or with (long 0)
I used to know the resources describing precisely how to do this, searching and seeing if I can refresh my memory right now…
bit-xor already does the right thing. I guess what I’m asking is, what’s the ideal format to represent my data?
use bytes
use (bit-and b 0xff) to get a long
E.g., if I use byte[], the bits are ideal, but I lose out on a lot of Clojure’s seq fns, have to use amap and areduce
(if you need the unsigned value for math
@kingmob there’s vector-of which can hold unboxed bytes
> (doc vector-of)
-------------------------
clojure.core/vector-of
([t] [t & elements])
Creates a new vector of a single primitive type t, where t is one
of :int :long :float :double :byte :short :char or :boolean. The
resulting vector complies with the interface of vectors in general,
but stores the values unboxed internally.
Optionally takes one or more elements to populate the vector.
nil
Ahhh, maybe that’s what I want
np - it’s too bad this stuff has to be so complicated on the jvm
Even back in 1995, I remember wondering why Java lacked unsigned types…
also, you mentioned byte-streams from ztellman before, I think it really will help now that you are thinking about what format you want it to be in
also, you can call map / filter / reduce etc. on a native array, clojure knows how to make a seq out of them implicitly
just be aware you’ll probably get a seq back (and might need to nudge it into another container after that)
I looked it over very carefully, and it seems to be more about converting between different Java types, less about Java <-> Clojure conversion
Maybe with a custom transformer…
Um, any thoughts on Plumatic’s hiphip?
It looked nice, but doesn’t support byte, only int/long/double/float
System/console doesn't seem to exist from the repl in cider; any other ways to prompt for a password properly in that context?
@noisesmith I know map/reduce can operate on Java native arrays, but if I’m not careful, I’ll get Longs back. Unchecked math will only ignore overflows, right? It’s not the same unsigned math, yes?
(hope that’s not a non-sequitor)
maybe make a unit test, try a few usages of unchecked-byte followed by the kind of math you are using followed by unchecked-byte again and see what value you get back
I think it will work
Hmm, lemme test that
That might help, too. I’m not really doing any math at my level, just a lot of xor-ing
aha, in that case (into (vector-of :byte) (map unchecked-byte) coll)
should turn any of your results back into a reasonable shapre
=> (into (vector-of :byte) (map unchecked-byte) [1 2 3 4 254])
[1 2 3 4 -2]
Thx! Idiomatic question: is (into (vector-of:byte) …) preferable to (apply vector-of :byte) ?
into lets you use a transducer
otherwise you create a lazy-seq that nobody actually needs (via map)
you can throw other transducers in there too, if you find them handy
I am using the REPL to explore a Java SDK, and have started to make a few small namespaces with functions wrapping the Java interop stuff.
I've got a "connection" namespace that ultimately defs a connection instance, say conn-instance, that I intend to use. As I'm the only user of the SDK, and will only need a single connection, is this a reasonable approach?
I understand that in a larger system I should look at the component library, and I have the alternative of using dynamic vars, but as I'll only ever need the def'ed instance, am I right in thinking these are unnecessary for now?
"I will only need a single one of these" -- famous last words
I would avoid putting anything stateful in a def
Seriously though, it's very little extra work to just make a constructor function. I've always come to regret global singletons.
@tbaldridge I was thinking that as I was typing it 🙂
@noisesmith, what would the easiest alternative be? I'm trying to be fairly nimble in this particular work and not had any experience of dynamic vars nor component (though I've been reading bits and bobs on the latter).
I think he already addressed this, but if possible use arguments to functions. Out of top level defs, an atom inside a def, a thread-local dynamic var, or an injected dependency (the main alternatives here), a regular argument to a function is the only one that is easily made into all the others. So it’s the most flexible, and if you stick to that options wherever possible, all the other options are just simple adaptations of it if needed.
@tbaldridge - so the constructor function, that would be a function wrapping the Java constructor, that I would then def a var for?
no, just do (defn connect [conn url] ...)
and then pass that result around like a normal value
I see, I think I'm probably just being idle and not wanting to type the whole function call when i use it. Thanks for your help 🙂
not qualified to give advice, since i'm new
but i much prefer the former
i prefer get-in
because it implies that that you are dealing with a map of maps. This condition is not necessarily true when you use the thread first macro
that's fair
get-in
allows for a default value when not found. Although you don't necessarily always use it, it means that the instances that do use it would look drastically different from instances that don't use it, leading to drastically different forms for similar behavior
ie, you prefer the threading macro but need to use a very orthogonal looking s-exp for similar results
@plins how are you doing async? via core.async or some other method?
what arey ou doing in the callbacks?
if you create promises, and deliver them in the callbacks, then (do @p1 @p2 @p3)
for example won’t return until all those promises have been delivered. But that’s just one approach.
or if your promises are a collection (run! deref promises)
won’t return until they are all delivered
oh - acually I forgot how that library works - in fact you could just start all the requests, and then run http/await on them in order
they will continue to run async in another thread, and await will return as each one completes
That's interesting. Thank you!