Fork me on GitHub
#beginners
<
2020-02-28
>
nebbionegiuseppe13: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.

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

me115915: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)
)

me115915: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

me115915: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)

hobosarefriends15:02:14

That's the ("Hello world")

me115915:02:33

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

hobosarefriends15:02:55

First item inside a paren is called as a function

hobosarefriends15:02:24

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

me115915:02:32

ok. let me try to fix that.

me115915:02:45

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

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

me115915: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

hobosarefriends15:02:29

That would return an anonymous function

hobosarefriends15:02:38

Try just returning a string

hobosarefriends15:02:04

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

hobosarefriends15:02:52

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

me115915:02:30

yea. same thing. no errors but no output.

hobosarefriends15:02:02

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

me115915: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

me115916: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

me115916: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

me115916: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

me115916:02:59

Thank you. Yea Im reading the docs on http://clojuredocs.org/clojure.core/symbol

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

me115916:02:38

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

me115916: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

me115916: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

me115916:02:48

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

jr0cket18: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

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

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

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?

sova22:02:05

super cool