A possible optimization to consider is tokenizing the words to ints then use int-map https://github.com/clojure/data.int-map
As someone just learning Clojure, all the resources from the recent years make out Leiningen to be the only sensible choice, but lots of recent discussions are about deps.edn. Is there a change happening in the community? I get that lein does a lot more than handling deps and building, but as a beginner I care more about having a simple way to get going and not having to understand a big tool. Would it be foolish to focus on deps.edn initially? I currently have no interest in packaging up or deploying Clojure code.
If you don't care about packaging or deploying code, I'd actually venture deps.edn might actually be better
I also need to correct you though, all build tools are fully viable, Lein, Maven, Clojurephant, Boot, Tools.Deps, etc.
There's someone somewhere using any of them in prod successfully
But Lein will have the best tool support (like chance of it playing nice with your IDE and other tools), followed by Tools.Deps (which is slowly catching up to Lein in that realm), followed by Boot.
for your use, either should be about equal, go with what your book / tutorial uses and if not using one of those deps.edn is simpler (it does less)
@anders152 they are dep management tools, many projects have configs to use both
:thumbsup: thanks!
it's easy to switch if it comes to it
@anders152 using Leiningen or Clojure CLI tools (deps.edn) shouldn't make a difference to the Clojure code you write.
There are a few Leiningen plugins that provide code for you, e.g. lein-ring, but other than that you can largely swap between the two ways of running and building Clojure projects. Simply adding a deps.edn
file that contains {}
is enough for projects that only have Clojure as a dependency. Adding {:deps {,, ,,}}
when using additional libraries.
If you are interested in using Clojure CLI tools, take a look at https://practicalli.github.io/clojure/
Hi everyone!. I'm wondering if there is a "from the ground up" course or guide to start creating mobile apps for Web+Android+iOS using clojure or clojurescript (with one single codebase). I'm willing to pay. I'm currently about to start a big social network project for a client and I'm very tempted by what clojurescript has to offer since I love CommonLisp and like clojure. I've seen a lot of names floating around like "react-native" "reagent" "expo", etc.. but can't seem to find a guide that helps me make an app from the ground up. I've tied a couple of tutorials but all seem way to verbose and some outright don't work, they break. Is there an entry point you can recommend?. I don't need a full-stack clojure solution, which many tutorials I've seen asume. I want to create client side apps that can connect to my existing server using websockets (or REST if there is no websocket support available). Even if it's not really a "one code base solution" but as long as it's more or less the same technology stack, I'd be happy. Something like: • "Clojure/Script + A for Web" • "Clojure/Script + B for Android" • "Clojure/Script + C for iOS" If there is not ONE guide or tutorial but someone can point me to a list of resources or can share their learning material I would appreciate it a lot. If something close to a "one codebase solution" for my client side apps is feasible and someone can help me with it I'd be willing to pay for the help or pay for the course, etc...
Check this course - https://purelyfunctional.tv/lesson/mobile-app-in-one-hour/
I have not taken the course myself. But it seems to be the closest thing to cover some of the things you mention
He also has some courses on clojure for web
This seems very helpful, thanks. It only covers iOS though, so if anyone can provide more material for Android and Web I'd appreciate it. I'm currently going through a React-Native tutorial and it seems to work just fine. https://reactnative.dev/docs/environment-setup But when I try this clojurescript+re-natal tutorial, it breaks, I'm still trying to find out why. https://medium.com/mindorks/building-mobile-apps-ios-and-android-with-clojurescript-4600235f826c
I’m connected to a remote repo for development (raspberry pi project). I’ve been using Emacs tramp to edit the files remotely (and cider-connect) but would prefer to edit the files locally. It seems to me that the only way to do that is to have the source code repo at both locations. Seemingly, when I need to add a new library, I would remotely edit the project.clj and restart the REPL, all other files I would edit locally. Then I would need to git commit
both repos. Am I understanding this correctly?
Is editing files on the Raspbury Pi via Emacs Tramp slow? I've started using Emacs tramp with a remote server and havent had any issues. I ssh into the remote server via a terminal, create a project if required and start the REPL process. I start the repl with nrepl and cider libraries. Then I open the project files on the remote server via Emacs tramp (which was so easy). Then with the project files open in Emacs, I run cider-connect-clj If I need to restart the REPL project, then I just switch back to the terminal and do so there and use cider-connect when its back up. Details are here (sorry its a bit rough) https://practicalli.github.io/data-science/collaborative-coding/shared-server.html Would be interested to know whats different for Raspbury Pi. Thanks.
Doing similar with rpi and it’s fine. The issues are around complexity. For example, projectile works differently with tramp connections. Also, I have continually had performance problems with emacs and am looking to reduce the features in use to try to make it more reliable.
WRT performance, emacs occasionally hangs or pauses/blocks with high CPU. Normally tramp is very performant.
Thanks for sharing, much appreciated. I've only recently started, so have found the constraints yet, so goo to know.
I guess you could probably use rsync for that
Also, if you're connected to a nrepl session, you could just evaluate the buffer in order to "update" your code. But, if you need to reload a modified file you would need to update that on the server.
yeah, using nrepl. I have no issues with evaluating or loading the buffer for the code I’m developing (which is effectively local since it comes from my local emacs buffer). It’s just the idea of needing to restart the REPL in order for the dependencies to download. It seems confusing to be committing from two different machines.
I think this could help you
It isn't the exactly thing you want to do, but I guess it could at least improve your productivity.
Thanks for the suggestion. This is going down the road of switching from lein
to clojure tools: https://insideclojure.org/2018/05/04/add-lib/. I saw @seancorfield demo this last night and I was trying to take baby steps in the direction of simplifying my toolchain (by removing tramp) without committing entirely to tools.deps.alpha
, but that might be easiest at this point.
I got an error. What am I doing wrong?
user=> (def my-array (make-array Integer/TYPE 2 2))
#'user/my-array
user=> (aset my-array 0 0 100)
Execution error (IllegalArgumentException) at java.lang.reflect.Array/set (Array.java:-2).
argument type mismatch
Clojure "integers" are actually longs, maybe that's it?
(aset my-array 0 0 (int 100))
does not give an error
Also no error if you change it to an array of Long/TYPE
Great, the simpler the better.
Thank you, I got it ☺️
user=> (type 100) java.lang.Long
Hi, I want to create some kind of multiple auth to version my api with public routes and user routes and admin routes. May someone have some link explaining how auth-rule or any like that works on compojure ?
@el.silas I'm also a beginner, but my impression (as a React Native developer) is that there isn't great support for CLJS + React Native (or other compiling-to-native tools) right now. Browser apps are well supported with Reagent etc, but the mobile side lacks resources and active support. Given the pace of change with React Native alone (especially if you use Expo), TypeScript may be a better choice. Or Flutter
Hm, how do I check if a vector contains a specific value? I assumed contains?
but now learned that this checks for the presence of keys, and in the case of a vector thats the index...
Values in a vector are not "indexed", so you can't actually check presence with O(1) complexity. But you iterate over the vector.
A simple way to do that would be using some
, like this.
I just realised that this can be solved with a set, which makes a lot more sense...
(some (partial = value) my-vector)
That's great
Thanks, that points me to the right way of thinking @renatoalencar.73!
Great!
Speaking of which, if I have code that looks like this:
#(contains? #{"a" "b"} %)
Will the set be created every time the anonymous function is called?
I know how this works in most languages (the answer being yes), but I just want to double check how it works in Clojure..
Probably not, since this is a complete literal value without any references in it.
But, let me check.
I had to do a little bit of work but here it is. This is your anonymous function compiled.
import clojure.lang.IFn;
import clojure.lang.PersistentHashSet;
import clojure.lang.RT;
import clojure.lang.AFn;
import clojure.lang.Var;
import clojure.lang.AFunction;
//
// Decompiled by Procyon v0.5.36
//
public final class a$fn__38 extends AFunction
{
public static final Var const__0;
public static final AFn const__1;
static {
const__0 = RT.var("clojure.core", "contains?");
const__1 = (AFn)PersistentHashSet.create(new Object[] { "a", "b" });
}
public Object invoke(Object p1__37_SHARP_) {
final IFn fn = (IFn)a$fn__38.const__0.getRawRoot();
final AFn const__1 = a$fn__38.const__1;
final Object o = p1__37_SHARP_;
p1__37_SHARP_ = null;
return fn.invoke((Object)const__1, o);
}
}
It turns out the set is created when the generated class for the function is loaded.
That's because your set only has literal values, which can be used as a constant instead of recreating every time you invoke the function.
Nice! That's what I was hoping.
Thanks a lot for the digging.
No, the set is created at read time
So it won't be created every time the function is called
That goes for every reader literal, those are always created at read time, thus only once when the namespace is loaded
Oh, that's what I was missing. I was just considering projects using AOT compilation, which is not always the case. And sure, every literal value is evaluated and instantiated in read time.
Ya, but you're correct in that, if there is a variable in it, then it will be differed to runtime, since it can't create the set until there are actual values for all variables in it
The difference I'm pointing out is that, if instead of a reader literal, you used a function, like:
(fn [] (hash-set 1 2 3))
This will always create the set at runtime, every time the function is called a new set will be created with 1 2 3 in it.But reader literals will be at read time instead, if everything is resolvable at that time
Hope I'm making sense
It totally does
tip: sets are functions: called with 1 arg they return it if in set, nil if not
(#{1 2} 2) ;; => 2
Is there a seq function for creating a sequence of pairwise values from an input seq? E.g... (1 2 3 4)
should create ([1 2] [2 3] [3 4])
Wow, great tip. I love how so many things can be used as functions in Clojure.
user=> (partition 2 1 [1 2 3 4])
((1 2) (2 3) (3 4))
Oh, nice! Thanks a lot.
guys, I have a bizarre problem, probably with maven
ribelo@ribelo-xps ~ [1]> clj
Error: Could not find or load main class clojure.main
Caused by: java.lang.ClassNotFoundException: clojure.main
@huxley What does clj -Sforce
do? Also clj -h
and clj -Sdescribe
just so we have a bit more detail.
(has clj
been working for you before? If so, what did you change on your system between it working and it breaking?)
-Sforce
helped.
Stale cached dependencies. Maybe you deleted something or updated something that broke the previously cached dependency information.
From time to time I have a problem while working on a project. Dependencies seem to disappear.
Syntax error (FileNotFoundException) compiling at (clj_cli/core.clj:1:1).
Could not locate clojure/core/async__init.class, clojure/core/async.clj or clojure/core/async.cljc on classpath.
Removing $HOME/.m2
always solved the problem.
However, today it has completely broken down clojure.
Ah, yes, if you remove ~/.m2
you are going to break all of your cached dependencies because they're going to point to files you have deleted.
Much better to leave ~/.m2
alone and just use -Sforce
with clj
/ clojure
if your dependencies seem to be broken.
Some library has a protocol and a record implementing it; I want for myself a slightly bit different record implementing the same protocol. Lots of copy paste follows; because "Concrete derivation is bad" I get. Is there a construct to refine the first record and avoid all the copy paste?
Also: multimethods have defaults and hierarchies, protocols don't; why?
Wow, is that a real thing?
It seems to maybe be ClojureScript only? I get Unable to resolve symbol: default in this context
in Clojure
Yes, cljs only, and is documented in extend-type's docstring (just cljs).
I was looking for it in clj docstrings...
seems cljs uses default/:default in a number of places, see channel chat linked from my comment there
Minor word of warning: (#{false} false)
returns false
and (#{nil} nil)
returns nil
, which are logical false values in conditional expressions, e.g. if
, cond
, if-let
, etc. If you avoid those values when using that technique, you should be fine.
You can also delete ~/.m2
and then remember to use -Sforce
, not in one but in all projects on that same system, but yeah, that can be easy to forget. Deleting ~/.m2
is a pretty big hammer that shouldn't be needed very often.
there are ways to automatically construct new records that are slight modifications of old records. how would you like your record to be different compared to the first?
what kind of refining do you need?
from https://clojure.org/reference/protocols: > There are several motivations for protocols: > - Provide a high-performance, dynamic polymorphism construct as an alternative to interfaces > ... > - Support the 90% case of multimethods (single dispatch on type) while providing higher-level abstraction/organization I think the difference between multimethods and protocols is that protocols can leverage jvm bytecode instructions to improve performance where some of the flexibility provided by multimethods cannot leverage the same optimized bytecode instructions
same implementation with 1 method different
(refine SomeRecord AProtocol (changed-method [args] ...) ...)
=> new record, no inheritance, some methods have different impl
as long as you can convert SomeRecord to OldRecord, you could have refine
be a macro that expands to an extend-type
call that converts SomeRecord
to OldRecord
and calls the method on it for any method without a provided implementation required for AProtocol
I thought there was a cleaner way to extract a method body from a defrecord
, but I can't seem to find it
Hum, seems you're doing OOP
And there's probably a Functional way to structure whatever you are doing instead
But, to answer your question, what you do is have your protocol methods actually be functions. And when you extend a record to it, you just choose the set of functions you want for each protocol method
I think the problem is that the functions that they want to reuse are from another library that already didn't do that
Oh, I see.
yea, otherwise. 💯 agree
Then I would probably use composition instead of inheritance in this case
But, I never thought how to do that with records hum... :thinking_face:
Might not be possible, or at least I can't think of a way
Hi. I was able to start a mobile app with clojurescript using tools.deps and https://github.com/bhauman/react-native-figwheel-bridge
With that I can have the same base code for andoid and iOS. With some modifications to deps.edn I could cover Web as well.
if clojure implemented concrete inheritance for records this wouldn't be an issue, but clojure data objects don't support that, multimethods can implement a similar delegation (with :default etc.) but don't use vm object inheritance (and are not data objects)
clojure as implemented is pretty opinionated about extension via composition rather than inheritance