Fork me on GitHub
#beginners
<
2020-02-28
>
Giuseppe Nebbione13:02:07

hello all, i am reading "Living Clojure" and i found it quite clear, although there are things that i still don't understand and are not explained in the book... for example... why if clojure pushes for using basic native data types (such as lists/vectors/maps and so on) it has things like defrecord and stuff like that... i mean how and when should i use those? from what i understand defrecord and similar are used to define new type of data right?

manutter5113:02:18

Things like defrecord can be handy when you’re working with protocols or multimethods because you can dispatch on data type. You could achieve a similar effect by including a :type key in your map and dispatching on that, but using records can be a bit cleaner.

Crispin13:02:57

defrecord is faster for one. At some point when your code matures you find it slow you may replace some of the datastructs with records. records are more familiar to those wanting to strongly type their code. Also keep in mind that clojure is excellent at retaining backwards compatibility, so you will find some things in it that you may wonder why they are there. And they are kept there so old code that was written to use them continues to work. And example of this is defstruct.

manutter5113:02:34

There are also applications where you’re doing things with Java interop, and you need to keep track of Java types, so there’s support for that in Clojure too.

Chester ONeill15:02:45

Hey everyone. Im trying to write something just to get familiar with clojure so I wanted to write a really simple server. but I can't seem to figure out what exactly clojure wants in the :accept key of start-server

(ns clojure-noob.core
  (:require [clojure.core.server :as http])
  (:gen-class))

(defn mine
  []
  ("Hello World")
)

(defn -main
  [& args]
  (http/start-server {:port 4040 :accept clojure-noob.core/mine :name "localhost" :args []})
  (while 1)
)

Chester ONeill15:02:56

The error

Exception in thread "Clojure Connection localhost 1" java.lang.ClassCastException: class clojure_noob.core$mine cannot be cast to class clojure.lang.Named (clojure_noob.core$mine is in unnamed module of loader clojure.lang.DynamicClassLoader @4d4d8fcf; clojure.lang.Named is in unnamed module of loader 'app')
	at clojure.core$namespace.invokeStatic(core.clj:1597)
	at clojure.core.server$accept_connection.invokeStatic(server.clj:73)
	at clojure.core.server$start_server$fn__8864$fn__8865$fn__8867.invoke(server.clj:117)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.base/java.lang.Thread.run(Thread.java:830)

bfabry15:02:31

clojure-noob.core/mine is being resolved to the actual function that is defined under that var

bfabry15:02:29

start-server doesn't want a function, it wants a name that it can look up a function with

bfabry15:02:18

to send the name (symbol) clojure-noob.core/mine you can tell clojure not to resolve the symbol by quoting it. (quote clojure-noob.core/mine) or shorthand 'clojure-noob.core/mine

Chester ONeill15:02:48

Ok i sort of follow that. different error now who when I don't resolve the symbol and just quote it.

Exception in thread "Clojure Connection localhost 5" java.lang.ClassCastException: class java.lang.String cannot be cast to class clojure.lang.IFn (java.lang.String is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')
	at clojure_noob.core$mine.invokeStatic(core.clj:7)
	at clojure_noob.core$mine.invoke(core.clj:5)
	at clojure.lang.AFn.applyToHelper(AFn.java:152)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.lang.Var.applyTo(Var.java:705)
	at clojure.core$apply.invokeStatic(core.clj:665)
	at clojure.core.server$accept_connection.invokeStatic(server.clj:73)
	at clojure.core.server$start_server$fn__8864$fn__8865$fn__8867.invoke(server.clj:117)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.base/java.lang.Thread.run(Thread.java:830)

Mno15:02:14

That's the ("Hello world")

Chester ONeill15:02:33

I figured. dosen't want to call a string as a function or something?

Mno15:02:55

First item inside a paren is called as a function

Mno15:02:24

So you'd be doing "Hello world" () essentially

Chester ONeill15:02:32

ok. let me try to fix that.

Chester ONeill15:02:45

ok so Im not getting errors anymore but im also not getting a response. so I did this

(defn mine
  []
  #([] "Hello")
)

Chester ONeill15:02:08

Stupid question. would I be able to hit this on a browser at localhost:4040 and get a response or is that just not what this thing does at all

Mno15:02:29

That would return an anonymous function

Mno15:02:38

Try just returning a string

Mno15:02:04

Unfortunately I'm not at a computer or familiar with this library so I cant tell

Mno15:02:52

To return a string (defn mine [] "Hello")

Chester ONeill15:02:30

yea. same thing. no errors but no output.

Mno15:02:02

I'm not sure 😅 if I get to a compute I'll take a look

Chester ONeill15:02:08

cool thanks maybe ill try telnet or something. Im actually not sure how SocketServer works if itll respond to http. thanks for the help @hobosarefriends @bfabry

Chester ONeill16:02:45

that seems like at least it connects tho so thats cool

COMMAND   PID          USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    23812 xxxxx   12u  IPv6 0x2e93801b0a183315      0t0  TCP localhost:yo-main (LISTEN)
➜  prevention-point git:(master) ✗ nc localhost 4040 -v
nc: connectx to localhost port 4040 (tcp) failed: Connection refused
nc: connectx to localhost port 4040 (tcp) failed: Connection refused
found 0 associations
found 1 connections:
     1:	flags=82<CONNECTED,PREFERRED>
	outif lo0
	src 127.0.0.1 port 58002
	dst 127.0.0.1 port 4040
	rank info not available
	TCP aux info available

Connection to localhost port 4040 [tcp/yo-main] succeeded!

dpsutton16:02:59

from the doc string clojure.core.serve/start-server :accept Namespaced symbol of the accept function to invoke, required . Note that this is not a normal http server

Chester ONeill16:02:36

Yea it was the description of symbol that was confusing me. Im still not really sure what a symbol is. Is there something equivalent to an http server? ive seen https://github.com/ring-clojure/ring

Chester ONeill16:02:40

Right. I was looking to see if there was something built into clojure tho that was simple to stand up but thats fine. Any clarification you can give on the symbol definition?

dpsutton16:02:28

no web server built into clojure i don't believe. I'm looking for good documentation on symbols so i don't give you a handwavy explanation

bfabry16:02:17

there are java sockets, which are kind of "built in" to clojure. lot of work to get to a web server from there though

Chester ONeill16:02:38

actually the http://clojure.org/reference/reader gives a decent explanation

Chester ONeill16:02:54

@bfabry Yea I was mostly just curious to see how you really import and create stuff with the clojure libraires so really just trying to be able to read the docs, understand it and call something

Chester ONeill16:02:15

Having some working http server actually wasnt the goal in the end

bfabry16:02:17

http://clojure.org/reference is great documentation. reading it all would do anyone a world of good. fwiw this answer shows how to use clojure + java sockets to listen to a port and respond with a string from a repl https://stackoverflow.com/questions/60121687/how-can-i-get-clojure-to-write-a-response-to-a-socket/60122704#60122704

Chester ONeill16:02:48

yea I started with Clojure for the Brave and True but ive been flipping around the reference docs. Thanks again

practicalli-johnny18:02:26

@me1159 there is a relatively simple example of building a server-side web app here http://practicalli.github.io/clojure-webapps/ and I did some more recent videos walking through building a server-side web app and API https://www.youtube.com/watch?v=IoGWbM6Wqeg&amp;list=PLpr9V-R8ZxiCe9p9tFk24ChNSpGfanUbT

👍 4
seancorfield19:02:49

@me1159 You may also find this small example (of Ring, Compojure, Component, Selmer, and next.jdbc) helpful https://github.com/seancorfield/usermanager-example

Scott Starkey19:02:00

I’ve seen “Ring” mentioned a lot. What is that? (The new draft specs for it just came out.)

hiredman19:02:58

ring isn't an http server

hiredman19:02:26

ring is a specification for mapping http request/responses to function calls passing clojure data

andy.fingerhut19:02:28

Others who actually know can correct/refine this, but basically a de facto standard among Clojure libraries to pass data about HTTP requests/responses between functions.

👍 4
bfabry19:02:52

oh. interesting

hiredman19:02:54

similar to how java servlets are a specification for mapping http request/response to objects and method calls

hiredman19:02:00

one of the most commonly used ring implementations is ring-servlet which is an implementation of the ring spec on top of the servlet spec

seancorfield19:02:23

Ring has a "default" adapter which is an embedded Jetty server, which is suitable for production usage, but can be used with several other servers (we've run both Jetty and http-kit at work).

didibus19:02:59

Oh, is there a new ring spec in the works?