clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
2021-01-24T01:29:52.242900Z

It has been a long time since I last looked at core.match's internals, but I believe it has some protocols you could extend to Pattern, but of course that runs afoul of the "don't extend protocols you don't own to types you don't own" advice. The other issue is I don't believe Pattern has a way to get a list of names. Chouser recently shared a macro in a tweet for binding named matches. He had to parse the names out of the pattern himself.

zendevil 2021-01-24T03:09:57.243900Z

It says This adds a file key to the :params map of the request where :tempfile is a http://java.io.File object that contains the uploaded data. But my request map doesn’t have the tempfile key in (-> req :params)

zendevil 2021-01-24T03:26:30.244200Z

furthermore, the multipart-params key contains the empty string in place of the file

2021-01-24T03:30:41.244500Z

https://github.com/alekcz/pcp

2021-01-24T03:31:09.244800Z

I don't think you can use it with shared hosting though, cause I don't think you can setup the scgi server on shared hosting.

2021-01-24T05:04:54.245300Z

@katox there's a short syntax:

#:foo {:bar 1, :baz 2}
;; is the same as:
{:foo/bar 1, :foo/baz 2}

2021-01-24T05:14:28.245600Z

@teodorlu A keyword namespace can have hierarchies in Clojure, but it is up to the application to decide of that scheme (if any) for itself. Clojure itself does not have the concept of hierarchies for keyword namespaces. What that means is that you do not find something by following the trail of . inside a keyword namespace, and you also do not find something by following the namespace somewhere to find the name of the keyword inside it.

(def m
  {:foo/bar {:biz/baz 2}
   :foo/baz 3})
Here you don't navigate the map using the keyword namespaces. For example, you don't do:
(-> m :foo :bar :biz :baz)
But if it was OO, you would, you'd have the Foo object which contains bar which contains the Biz object which contains baz. And you'd do:
m.bar.baz

1
2021-01-24T05:23:51.246200Z

What that means is that :foo/bar is not necessarily inside the :foo map, or any other thing, there is no concrete thing that is a :foo where :bar is found inside. You could not have had a namespace mechanism built in, but having one both instill good practice to people, and also means there's no conflict in parsing the namespace from the name for which you need to come up with a solution for clashes. There are reasons to want to use namespaces in your app. Key conflicts is one. But as an app developer, you can also leverage it for other useful things. Could be used for defining types, or context, and could even be used for hierarchy if you want.

2021-01-24T05:30:33.246400Z

Now namespaces (non keyword), so like *ns* are scoped in Clojure, but not hierarchical, though you can think of a scope as almost a hierarchy of one. Its just hierarchical generally implies nesting and sub-nesting. So you do use the namespace to look up the thing for the given symbol name from somewhere, the where being the namespace itself. But if you think of where those are, they are all flat:

{'foo.bar
 '<http://foo.biz|foo.biz>
 'foo
 'fizz.buzz
 'fizz.buzz.beer}
So even though those refer to a real place where the Var of the symbol will be found, they don't nest, so when you have fizz.buzz it is not the case that buzz is inside fizz. Its just a name for the space where the Vars of those symbols will be found, not a hierarchy of things nested in one another. So the symbols are like nested inside the namespace, but namespaces don't nest themselves inside others, they are flat, and not hierarchical once again. And finally symbol namespaces when the symbol is used as a value itself, like you'd use keywords, where that's exactly the same as for keywords.

2021-01-24T05:36:27.246700Z

Ok, last thing, maybe this seems like splitting hair. But actually, it makes most sense if you start from OO, how do you do this in OO?:

{:user/id 123
 :order/id 234}
Well, you can invent your own namespacing scheme and do:
Purchase {
  user_id;
  order_id;
}
new Purchase(user_id = 123, order_id = 234)
Which is just you re-inventing an ad-hoc namespacing mechanism. Or you use OO's hierarchies:
User {
  id;
}
Order {
  id;
}
Purchase {
  user;
  order;
}
user = new User(id = 123)
order = new Order(id = 234)
new Purchase(user = user, order = order)
But now you need to get the thing by navigating the hierarchy:
purchase.user.id

💯 1
2021-01-24T05:42:55.247600Z

Seems like some cgi support is offered but not sure if that applies here 😅

2021-01-24T05:45:16.247800Z

No, because bluehost would need to have Clojure installed, and their webserver should be setup to know how to call Clojure scripts

2021-01-24T05:46:49.248100Z

I’ve registered .clj to run as a cgi-script. Could I specify a shebang #!../bin/babashka to run a script through that?

2021-01-24T05:47:16.248300Z

Yes, if they installed babashka

2021-01-24T05:47:34.248500Z

Couldn’t I just upload the binary and point to it in the shebang?

2021-01-24T05:48:18.248700Z

Possibly... I think it might depend on their web server. Like if it specifically handles certain shebangs, or just delegates to the OS for it

2021-01-24T05:48:26.248900Z

You should try, that be sweet if it works

2021-01-24T05:56:14.249100Z

And let me know

2021-01-24T06:02:20.249300Z

Babashka just added hiccups too: https://github.com/babashka/babashka/commit/c4bb42df3e1a8ebcc27fee3a8886137d2f021b6e So that be a quick way to render html with it as a CGI script

2021-01-24T06:05:15.249500Z

Oooh giving it a shot now. Thanks!

2021-01-24T06:37:34.249700Z

$ ./bb
./bb: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./bb)
./bb: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ./bb)
Damn. I take it there’s no way to deal with that? Hypothetically what would I need to do?

2021-01-24T06:38:54.249900Z

Yes there is

2021-01-24T06:39:29.250100Z

Go here: https://github.com/babashka/babashka/releases and download the one that says: babashka-0.2.7-linux-static-amd64.zip

2021-01-24T06:40:16.250400Z

If you use the statically linked binary instead, it'll fix that error

2021-01-24T06:45:34.250600Z

Oh shittt! Thank you

2021-01-24T06:49:24.250800Z

Can run a repl with that on server so that’s progress.

2021-01-24T06:50:06.251Z

Getting a 500 error though when visiting my clj script or my perl test. I’ve never used a cgi-script so learning on the fly here 😆

2021-01-24T06:53:51.251200Z

Script runs locally via shell

2021-01-24T07:03:01.251500Z

Hum, the bluehost docs says that 500 error can be you have the path wrong

2021-01-24T07:03:49.251800Z

I looked at that too, but that can’t be the case given I can do ./cgi-bin/test.clj from shell and it works

2021-01-24T07:03:55.252Z

And the permissions are 755

2021-01-24T07:04:39.252200Z

Might just be what you return doesn't meet the CGI spec? Can you have the script spit some file somewhere? So you'd know if it ran, but returned something that didn't jive with the server?

2021-01-24T07:11:39.252400Z

I think you’re right, found a perl cgi-script example and that is working now. Only notable difference is that the return value was set to 1 or maybe it’s the exit code?

#!/usr/bin/perl

print "Content-type:text/html\r\n\r\n";
print '&lt;html&gt;';
print '&lt;head&gt;';
print '&lt;title&gt;Hello Word - First CGI Program&lt;/title&gt;';
print '&lt;/head&gt;';
print '&lt;body&gt;';
print '&lt;h2&gt;Hello Word! This is my first CGI program&lt;/h2&gt;';
print '&lt;/body&gt;';
print '&lt;/html&gt;';

1;

2021-01-24T07:14:02.252600Z

Nevermind it’s the content-type header

2021-01-24T07:14:39.252800Z

🤞

2021-01-24T07:14:54.253Z

This guide seems okay-ish: https://docstore.mik.ua/orelly/linux/cgi/ch03_03.htm

2021-01-24T07:15:21.253200Z

> Every CGI script must print a header line, which the server uses to build the full HTTP headers of its response. If your CGI script produces invalid headers or no headers, the web server will generate a valid response for the client -- generally a 500 Internal Server Error message.

2021-01-24T07:15:43.253400Z

http://cgi.jayzawrotny.com/cgi-bin/test.clj

👏 1
2021-01-24T07:15:54.253600Z

💥 it works 🚀 !!!!

2021-01-24T07:16:08.253800Z

Hurray!

2021-01-24T07:16:49.254100Z

Thanks very much for your help

2021-01-24T07:17:19.254300Z

Ok, that's pretty cool. Worthy of a blog post in my opinion. I think there's a lot of people learning and they can't afford a VPS, it be nice if they could mess with Clojure on a shared hosting like that.

2021-01-24T07:18:04.254500Z

What's the Clojure code for the script that worked?

2021-01-24T07:18:34.254700Z

#!/home1/&lt;username&gt;/public_html/clj-test/bb

(println "Content-type:text/html\r\n");
(println "&lt;h1&gt;Hello I'm running from Clojure&lt;/h1&gt;")

2021-01-24T07:19:06.254900Z

Cool, ya, pretty easy then, just like with Perl.

2021-01-24T07:19:24.255100Z

Should probably move the executable out of the public_html folder though, but yeah pretty simple really

2021-01-24T07:20:00.255300Z

Now bb does take up 22mb of your hosting though 😛

2021-01-24T07:24:34.255500Z

Not seemingly a problem here ¯\(ツ)

2021-01-24T07:24:42.255700Z

2021-01-24T07:27:08.256100Z

Ya, pretty neat. That approach is probably the easiest way to teach people how to make websites for sure haha

2021-01-24T07:30:38.256300Z

Agreed! The goal for tomorrow is to get it talking to a postgres db and if that works I definitely want to write an article.

1
borkdude 2021-01-24T10:58:24.257600Z

yeah, I think :guard with re-find/matches etc might be more reliable.