beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Ben Sless 2020-12-16T04:23:56.305700Z

A possible optimization to consider is tokenizing the words to ints then use int-map https://github.com/clojure/data.int-map

2020-12-16T07:29:59.310100Z

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.

2020-12-16T18:25:28.361100Z

If you don't care about packaging or deploying code, I'd actually venture deps.edn might actually be better

2020-12-16T18:26:25.361500Z

I also need to correct you though, all build tools are fully viable, Lein, Maven, Clojurephant, Boot, Tools.Deps, etc.

2020-12-16T18:26:36.361700Z

There's someone somewhere using any of them in prod successfully

2020-12-16T18:27:55.362600Z

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.

2020-12-16T07:47:01.310900Z

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)

2020-12-16T07:47:47.311400Z

@anders152 they are dep management tools, many projects have configs to use both

2020-12-16T07:48:02.311900Z

:thumbsup: thanks!

2020-12-16T07:48:05.312Z

it's easy to switch if it comes to it

practicalli-john 2020-12-16T09:13:20.323400Z

@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/

🙌 2
2020-12-16T10:35:58.341300Z

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...

Sebastian 2020-12-16T11:46:31.342100Z

Check this course - https://purelyfunctional.tv/lesson/mobile-app-in-one-hour/

Sebastian 2020-12-16T11:47:18.342400Z

I have not taken the course myself. But it seems to be the closest thing to cover some of the things you mention

Sebastian 2020-12-16T11:47:48.342600Z

He also has some courses on clojure for web

2020-12-16T12:34:13.343100Z

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

2020-12-16T13:16:34.345600Z

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?

practicalli-john 2020-12-18T17:23:07.478Z

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.

2020-12-18T17:32:34.481800Z

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.

2020-12-18T17:35:31.484100Z

WRT performance, emacs occasionally hangs or pauses/blocks with high CPU. Normally tramp is very performant.

practicalli-john 2020-12-18T18:44:15.486500Z

Thanks for sharing, much appreciated. I've only recently started, so have found the constraints yet, so goo to know.

Renato Alencar 2020-12-16T13:21:44.345900Z

I guess you could probably use rsync for that

Renato Alencar 2020-12-16T13:28:11.346100Z

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.

2020-12-16T13:48:27.346300Z

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.

Renato Alencar 2020-12-16T13:53:18.346600Z

https://github.com/clj-commons/pomegranate

Renato Alencar 2020-12-16T13:53:32.346900Z

I think this could help you

Renato Alencar 2020-12-16T13:54:12.347100Z

It isn't the exactly thing you want to do, but I guess it could at least improve your productivity.

👍 1
2020-12-16T13:59:27.347600Z

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.

ichise.masashi 2020-12-16T14:00:59.348Z

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

2020-12-16T14:02:33.348700Z

Clojure "integers" are actually longs, maybe that's it?

2020-12-16T14:03:08.349100Z

(aset my-array 0 0 (int 100)) does not give an error

2020-12-16T14:03:33.349400Z

Also no error if you change it to an array of Long/TYPE

Renato Alencar 2020-12-16T14:03:33.349500Z

Great, the simpler the better.

ichise.masashi 2020-12-16T14:05:11.350200Z

Thank you, I got it ☺️

ichise.masashi 2020-12-16T14:06:11.350400Z

user=> (type 100) java.lang.Long

Chicão 2020-12-16T14:21:49.352300Z

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 ?

Sam Stowers 2020-12-16T17:30:40.357300Z

@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

2020-12-16T18:02:16.358100Z

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...

Renato Alencar 2020-12-16T18:03:57.358200Z

Values in a vector are not "indexed", so you can't actually check presence with O(1) complexity. But you iterate over the vector.

Renato Alencar 2020-12-16T18:04:16.358400Z

A simple way to do that would be using some, like this.

2020-12-16T18:04:34.358600Z

I just realised that this can be solved with a set, which makes a lot more sense...

Renato Alencar 2020-12-16T18:04:38.358800Z

(some (partial = value) my-vector)

🙌 1
Renato Alencar 2020-12-16T18:05:16.359Z

That's great

2020-12-16T18:05:21.359300Z

Thanks, that points me to the right way of thinking @renatoalencar.73!

Renato Alencar 2020-12-16T18:05:38.359500Z

Great!

2020-12-16T18:05:49.359700Z

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?

2020-12-16T18:06:45.360100Z

I know how this works in most languages (the answer being yes), but I just want to double check how it works in Clojure..

Renato Alencar 2020-12-16T18:07:36.360300Z

Probably not, since this is a complete literal value without any references in it.

Renato Alencar 2020-12-16T18:07:51.360500Z

But, let me check.

🙌 1
Renato Alencar 2020-12-16T18:24:43.360900Z

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);
    }
}

🙌 1
Renato Alencar 2020-12-16T18:25:32.361300Z

It turns out the set is created when the generated class for the function is loaded.

Renato Alencar 2020-12-16T18:26:54.362Z

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.

2020-12-16T18:27:13.362200Z

Nice! That's what I was hoping.

2020-12-16T18:27:24.362400Z

Thanks a lot for the digging.

2020-12-16T18:29:46.362800Z

No, the set is created at read time

2020-12-16T18:30:03.363Z

So it won't be created every time the function is called

2020-12-16T18:30:24.363200Z

That goes for every reader literal, those are always created at read time, thus only once when the namespace is loaded

Renato Alencar 2020-12-16T18:33:01.363400Z

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.

2020-12-16T18:36:52.363700Z

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

2020-12-16T18:39:32.364Z

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.

2020-12-16T18:40:30.364200Z

But reader literals will be at read time instead, if everything is resolvable at that time

2020-12-16T18:41:20.364400Z

Hope I'm making sense

Renato Alencar 2020-12-16T18:51:36.364800Z

It totally does

clyfe 2020-12-16T19:37:03.367Z

tip: sets are functions: called with 1 arg they return it if in set, nil if not

👀 1
clyfe 2020-12-16T19:37:31.367200Z

(#{1 2} 2) ;; => 2

2020-12-16T20:22:22.368800Z

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])

2020-12-16T20:23:30.369Z

Wow, great tip. I love how so many things can be used as functions in Clojure.

bronsa 2020-12-16T20:24:44.369400Z

user=> (partition 2 1 [1 2 3 4])
((1 2) (2 3) (3 4))

2020-12-16T20:25:17.369600Z

Oh, nice! Thanks a lot.

2020-12-16T20:52:11.369900Z

guys, I have a bizarre problem, probably with maven

2020-12-16T20:52:44.370200Z

ribelo@ribelo-xps ~ [1]> clj
Error: Could not find or load main class clojure.main
Caused by: java.lang.ClassNotFoundException: clojure.main

seancorfield 2020-12-16T20:53:42.371100Z

@huxley What does clj -Sforce do? Also clj -h and clj -Sdescribe just so we have a bit more detail.

seancorfield 2020-12-16T20:54:20.371700Z

(has clj been working for you before? If so, what did you change on your system between it working and it breaking?)

2020-12-16T20:54:59.371900Z

-Sforce helped.

seancorfield 2020-12-16T20:56:24.372800Z

Stale cached dependencies. Maybe you deleted something or updated something that broke the previously cached dependency information.

2020-12-16T20:56:36.373Z

From time to time I have a problem while working on a project. Dependencies seem to disappear.

2020-12-16T20:57:27.373300Z

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.

2020-12-16T20:58:23.373600Z

Removing $HOME/.m2 always solved the problem.

2020-12-16T20:59:32.374Z

However, today it has completely broken down clojure.

seancorfield 2020-12-16T21:23:14.374700Z

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.

seancorfield 2020-12-16T21:24:02.375300Z

Much better to leave ~/.m2 alone and just use -Sforce with clj / clojure if your dependencies seem to be broken.

clyfe 2020-12-16T21:30:49.378500Z

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?

clyfe 2020-12-16T21:36:55.379300Z

Also: multimethods have defaults and hierarchies, protocols don't; why?

2020-12-23T19:46:02.325300Z

Wow, is that a real thing?

2020-12-23T19:50:14.325900Z

It seems to maybe be ClojureScript only? I get Unable to resolve symbol: default in this context in Clojure

clyfe 2020-12-23T19:54:53.327200Z

Yes, cljs only, and is documented in extend-type's docstring (just cljs).

clyfe 2020-12-23T19:55:15.327400Z

I was looking for it in clj docstrings...

clyfe 2020-12-23T19:56:05.327600Z

seems cljs uses default/:default in a number of places, see channel chat linked from my comment there

2020-12-16T21:44:10.379400Z

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.

2020-12-16T21:46:02.379600Z

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.

phronmophobic 2020-12-16T21:47:10.380Z

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?

phronmophobic 2020-12-16T21:47:37.380200Z

what kind of refining do you need?

phronmophobic 2020-12-16T21:50:38.380500Z

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

clyfe 2020-12-16T22:06:07.381400Z

same implementation with 1 method different

clyfe 2020-12-16T22:07:26.381600Z

(refine SomeRecord AProtocol (changed-method [args] ...) ...)

clyfe 2020-12-16T22:08:33.381800Z

=> new record, no inheritance, some methods have different impl

phronmophobic 2020-12-16T22:26:27.382100Z

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

phronmophobic 2020-12-16T22:27:07.382300Z

I thought there was a cleaner way to extract a method body from a defrecord, but I can't seem to find it

2020-12-16T22:45:29.382700Z

Hum, seems you're doing OOP

2020-12-16T22:45:44.382900Z

And there's probably a Functional way to structure whatever you are doing instead

2020-12-16T22:47:10.383100Z

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

phronmophobic 2020-12-16T22:48:33.383300Z

I think the problem is that the functions that they want to reuse are from another library that already didn't do that

2020-12-16T22:49:34.383500Z

Oh, I see.

phronmophobic 2020-12-16T22:49:54.383700Z

yea, otherwise. 💯 agree

2020-12-16T22:52:30.384Z

Then I would probably use composition instead of inheritance in this case

2020-12-16T22:53:07.384200Z

But, I never thought how to do that with records hum... :thinking_face:

2020-12-16T22:55:17.384400Z

Might not be possible, or at least I can't think of a way

yunior 2020-12-16T23:22:54.384600Z

Hi. I was able to start a mobile app with clojurescript using tools.deps and https://github.com/bhauman/react-native-figwheel-bridge

yunior 2020-12-16T23:24:05.384900Z

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.

2020-12-16T23:25:03.385100Z

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)

2020-12-16T23:26:07.385300Z

clojure as implemented is pretty opinionated about extension via composition rather than inheritance