Fork me on GitHub
#beginners
<
2016-03-14
>
urbanslug07:03:05

I have read https://github.com/clojure/clojurescript/wiki/Using-cljc but I still can’t understand why we need cljc

urbanslug07:03:16

cljs clj and now cljc? What’s cljc for?

noisesmith16:03:12

urbanslug: here's an example of where I use cljc - I have a custom URL generator/parser that saves state we consider "bookmarkable" in the fragment, so that when a client bookmarks the view of the SPA, they get a recreation of view state.

noisesmith16:03:44

urbanslug: we want to be able to redirect clients from the backend to a specific view state, for which we need to be able to generate a specific encoded URL

noisesmith16:03:09

at the same time, we also need to be able to decode and encode the URL from the frontend, in order to maintain bookmarkability of state

noisesmith16:03:38

this is easy to handle with a namespace for URL manipulation and parsing in cljc code. Much better than keeping a clj and a cljs namespace in sync.

urbanslug16:03:12

noisesmith: wow thanks

urbanslug16:03:31

That’s a really good explanation.

noisesmith16:03:09

np, glad I could help

urbanslug16:03:12

@noisesmith: What’s an SPA though

noisesmith16:03:19

sorry, "single page app"

noisesmith16:03:52

which means that when you click a link in-app, it doesn't actually send a new GET request to the backend, it just does some transforms with the data it already has in browser

noisesmith16:03:58

gmail is an SPA for example

noisesmith16:03:46

there are also websocket and ajax requests to get new data from the backend, but those are decomplected from page changes - they happen when you need new data, which may or may not be on an href click event

noisesmith16:03:36

and all this is why we want to put relevant view state in the fragment of the page - so that parts of the app are still bookmarkable

noisesmith16:03:11

brb, meeting

urbanslug16:03:18

@noisesmith: Same thing happens with linking different parts of code or a github readme?

urbanslug16:03:37

Okay, I’m also not going to take too long

roberto16:03:33

does force always cast everything to a string?

noisesmith17:03:41

@urbanslug: yeah, similar in the github app

mss20:03:11

hey all, super basic thing I’m struggling with that I’d love to get some help on. I’m sure there’s a simple answer, I just can’t find it from perusing docs. trying to figure out how to import a Java library. declared the dep in my project.clj, it looks something like [com.someOrg/some-lib “1.0.0”]. leiningen pulled the library successfully when running lein deps. when attempting to use that library in my clojure project, however, I can’t seem to figure out the correct construction to import the library into my clojure file. would it be something like: (ns myproject.core (:import (some-lib))) or (ns myproject.core (:import [some-lib]))? as a followup, what is actually getting imported? let’s say the library itself exports a single public constructor for SomeObject. How do I instantiate an instance SomeObject in clojure? really appreciate any help anyone can provide.

bwstearns20:03:59

@mss: Maybe try:

(ns myapp.core
  (:require [some-lib :refer :all]))

mss20:03:09

@bwstearns: thanks for the suggestion. I was under the impression that it’s idiomatic to import Java things and only require when it’s clj(s) libs

bwstearns20:03:30

Oh, that might be the case.... I'm a beginner as well.

bwstearns20:03:42

I have the interop docs open right now lol

mss20:03:19

yeah I mean I can’t even seem to grab a reference that my repl recognizes to the publicly exported SomeObject constructor. which makes me think I’m just importing the library incorrectly

mss20:03:04

docs are pretty clear on what to do when it’s an already-included java library, not so much when it’s a third party java lib

mss20:03:13

maybe there’s not actually a difference and I’m just missing something

bwstearns20:03:57

Is it erroring [edit] when you try to require/import[/edit] or is instantiating SomeObject not working?

mss20:03:21

it’s instantiated, just not resolving the symbol when I’m actually trying to invoke it

mss20:03:38

getting the Unable to resolve symbol: SomeObject error

jonahbenton20:03:04

hey @mss- try (ns myproject.core (:import path.to.class))

mss20:03:13

where path.to.class is just the lein dep declaration correct?

alexmiller20:03:30

no, it's the full class name

jonahbenton20:03:32

no- the lein declaration is something different

alexmiller20:03:55

the dependencies declaration tells lein where to find the jar file containing the library

alexmiller21:03:11

the import tells Clojure where to find the class file you want to use (which is in the library)

alexmiller21:03:28

so something like (ns abc (:import java.lang.String))

alexmiller21:03:51

or to get a bunch of classes from the same package (ns abc (:import [java.lang String Object Integer]))

mss21:03:25

so what I think is tripping me up is – for a third party lib, where can I find out what the equivalent of java.lang in your example is for my installed third party lib

alexmiller21:03:31

however, you can always refer to Java classes with the full class name (even without import)

alexmiller21:03:39

well, that's a matter of looking at the lib's api

mss21:03:48

ah I see, doesn’t need any prefixing with the library?

alexmiller21:03:45

the only thing import does is let you refer to a class by it's short name (String) instead of it's full name (java.lang.String)

alexmiller21:03:11

which is helpful for readability (and your own sanity), but also somewhat for documentation purposes at the top of the file

alexmiller21:03:55

you can peek inside jar files pretty easily at the command line with jar tf the.jar (it's really just a zip file of classes)

mss21:03:11

that makes sense. so maybe this is my poor understanding of java showing through, but if this third-party lib exports a public class called SomeClass, all I would need to do is (ns my-project (:import SomeClass))?

alexmiller21:03:34

technically you don't even need to do that

alexmiller21:03:44

you can just refer to SomeClass in your code

alexmiller21:03:13

the only benefit of import is to let you use shorter class names (no package)

alexmiller21:03:47

like you can do (java.util.Date.) anywhere without importing it

mss21:03:54

wild, had no idea

mss21:03:00

and that holds for third party libs too?

alexmiller21:03:24

yes, there is no difference

alexmiller21:03:46

from Java/Clojure's perspective, there are just a giant tree of available classes

alexmiller21:03:56

when you need one, it will be loaded

alexmiller21:03:16

import is only about changing what names you can use to refer to those

alexmiller21:03:44

in the scope of a particular namespace

mss21:03:15

that makes a lot of sense. thanks for the clarification – must just be instantiating the thing incorrectly

alexmiller21:03:22

the best place to try stuff out is of course the repl :)

alexmiller21:03:04

the full name of a class should evaluate to its Class object - that can tell you if you have the right name or not

alexmiller21:03:48

user=> java.util.Date
java.util.Date

alexmiller21:03:59

user=> java.util.Dte   ;; oh no!
CompilerException java.lang.ClassNotFoundException: java.util.Dte

mss21:03:56

so that’s the tricky part to me. java.util.date obv resolves correctly, and prints out the class object. my third party SomeClass when I try to the send it to the repl throws an Unable to resolve symbol error back at me

mss21:03:12

and poking through the source of this library, the only public class is SomeClass, so I’m confused why it wouldn’t resolve correctly

alexmiller21:03:11

usually Java classes are in a package

mss21:03:44

hmm I’ll poke around and try and brush up on some java – clearly I don’t understand what’s happening under the hood well enough. thank you so much for the help, really appreciate it