2017-02-22
| 11:06 | Ardx | what does the @ symbol mean in macros? |
| 11:11 | wink | that feeling when you read such a question and first have to check what language channel you're in. :P |
| 11:11 | mavbozo | @ is a shorthand for deref function |
| 11:12 | Ardx | how is it different from ~ |
| 11:12 | Ardx | ? |
| 11:12 | mavbozo | is the @ symbol you see has ~ in front of it? |
| 11:12 | mavbozo | like ~@ |
| 11:12 | Ardx | well I'm trying to use it |
| 11:13 | Ardx | ~@ seems to make it worse :D |
| 11:13 | clojurebot | Gabh mo leithscéal? |
| 11:13 | mavbozo | ~please listen clojurebot |
| 11:13 | clojurebot | Excuse me? |
| 11:14 | mavbozo | ,(def three-and-four (list 3 4)) |
| 11:14 | clojurebot | #error {\n :cause "SANBOX DENIED"\n :via\n [{:type java.lang.Exception\n :message "SANBOX DENIED"\n :at [clojure.core$eval3$fn__4$fn__17 invoke "NO_SOURCE_FILE" -1]}]\n :trace\n [[clojure.core$eval3$fn__4$fn__17 invoke "NO_SOURCE_FILE" -1]\n [clojure.core$eval3$fn__4 invoke "NO_SOURCE_FILE" 0]\n [clojure.core$eval3 invokeStatic "NO_SOURCE_FILE" 0]\n [clojure.core$eval3 invoke "NO_SOURCE_FIL... |
| 11:14 | mavbozo | ,(def a 1) |
| 11:14 | clojurebot | #error {\n :cause "SANBOX DENIED"\n :via\n [{:type java.lang.Exception\n :message "SANBOX DENIED"\n :at [clojure.core$eval29$fn__30$fn__43 invoke "NO_SOURCE_FILE" -1]}]\n :trace\n [[clojure.core$eval29$fn__30$fn__43 invoke "NO_SOURCE_FILE" -1]\n [clojure.core$eval29$fn__30 invoke "NO_SOURCE_FILE" 0]\n [clojure.core$eval29 invokeStatic "NO_SOURCE_FILE" 0]\n [clojure.core$eval29 invoke "NO_SO... |
| 11:14 | mavbozo | ~aaargh |
| 11:14 | clojurebot | Gabh mo leithscéal? |
| 11:16 | Ardx | mavbozo this is my code http://pastebin.com/tUKyrd8a |
| 11:16 | Ardx | see it produces nil a lot |
| 11:16 | mavbozo | ,(let [tf (list 3 4)] `(1 ~@tf)) |
| 11:16 | clojurebot | (1 3 4) |
| 11:17 | mavbozo | the ~@ unquote-splicing removes the parentheses from a list |
| 11:17 | mavbozo | ,(let [tf (list 3 4)] `(1 ~tf)) |
| 11:17 | clojurebot | (1 (3 4)) |
| 11:18 | Ardx | ah ok dont think that helps then |
| 11:25 | Ardx | Hmm are macros expanded before defs are initialised? |
| 11:25 | Ardx | that would explain why I get nil, as what I pass in is empty |
| 11:38 | Ardx | ,(= 2 3) |
| 11:38 | clojurebot | false |
| 11:38 | Ardx | hmm how do I actually set values in clojure |
| 11:46 | mavbozo | Ardx, in a namespace you can bind value to a var using def |
| 11:46 | mavbozo | ,(def x 1) |
| 11:46 | clojurebot | #error {\n :cause "SANBOX DENIED"\n :via\n [{:type java.lang.Exception\n :message "SANBOX DENIED"\n :at [clojure.core$eval31$fn__32$fn__45 invoke "NO_SOURCE_FILE" -1]}]\n :trace\n [[clojure.core$eval31$fn__32$fn__45 invoke "NO_SOURCE_FILE" -1]\n [clojure.core$eval31$fn__32 invoke "NO_SOURCE_FILE" 0]\n [clojure.core$eval31 invokeStatic "NO_SOURCE_FILE" 0]\n [clojure.core$eval31 invoke "NO_SO... |
| 11:46 | mavbozo | ~darn |
| 11:46 | clojurebot | No entiendo |
| 11:47 | Ardx | Yeah I may as well figure out the clojure fnctional way of doing it though |
| 11:48 | scriptor | Ardx: you use (let) for local bindings, but try to think in terms of transformations and flows of data |
| 11:48 | scriptor | rather than setting values at each step |
| 12:05 | osfabibisi | Ardx: do you need a macro? |
| 12:06 | osfabibisi | if you are both trying to single-step through because it's complicated *and* asking about the syntax, then you may be biting off more than you can chew? ;-P |
| 12:06 | osfabibisi | (I feel I can say this, because I was doing exactly the same thing a month ago...) |
| 12:15 | Ardx | Yeah I started clojure yesterday |
| 12:16 | Ardx | But I fixed the macro now |
| 12:17 | Ardx | Now I'm just wondering, if I have a tree structure of hashmap, and I update a leaf node, how do I then add that lea node back onto the tee? |
| 12:18 | Ardx | Because it's all immutable, I can't just update one value. I guess I have to go back up the chain and recrate every hashmap along the way |
| 12:18 | technomancy | you would use update-in |
| 12:19 | technomancy | ,(update-in {:a {:b [45 88 {:c 5}]}} [:a :b 2 :c] inc) |
| 12:20 | clojurebot | {:a {:b [45 88 {:c 6}]}} |
| 12:20 | Ardx | hmmm |
| 12:23 | Ardx | that would update any :a :b :c it finds though |
| 12:23 | technomancy | no, the second arg is a linear path to follow |
| 12:24 | Ardx | ahh |
| 12:24 | technomancy | ,(update-in {:a {:b [45 88 {:c 5}]}} [:b 2 :c] inc) |
| 12:24 | clojurebot | #error {\n :cause nil\n :via\n [{:type java.lang.NullPointerException\n :message nil\n :at [clojure.lang.Numbers ops "Numbers.java" 1013]}]\n :trace\n [[clojure.lang.Numbers ops "Numbers.java" 1013]\n [clojure.lang.Numbers inc "Numbers.java" 112]\n [clojure.core$inc invokeStatic "core.clj" 919]\n [clojure.core$inc invoke "core.clj" 914]\n [clojure.lang.AFn applyToHelper "AFn.java" 154]\n ... |
| 12:24 | osfabibisi | or you can use zippers |
| 12:24 | technomancy | osfabibisi: hush you; he's on his second day |
| 12:24 | osfabibisi | technomancy: then he shouldn't be playing with macros :D |
| 12:24 | technomancy | true |
| 12:24 | Ardx | \o/ |
| 12:25 | justin_smith | macros are for absolute beginners (so you know what they hell they are about) and for people of advanced expertise who are redefining the language in their code, in between you'll rarely need macros |
| 12:26 | osfabibisi | justin_smith: ooo, good point ;-) |
| 12:26 | justin_smith | I'm barely at the point where making my own macros is a good idea myself |
| 12:26 | technomancy | day 2 of learning clojure: write three macros, understand how they work, and throw them immediately away |
| 12:26 | justin_smith | right |
| 12:27 | justin_smith | there's an optional "make a semi useful lib and fill it with domain specific macros with a cute syntax" - just skip that idea and throw it away |
| 12:28 | osfabibisi | ;-) |
| 12:29 | osfabibisi | one day, there will be a `git diff` that isn't rendered crazy by the reordering of functions... |
| 12:29 | justin_smith | osfabibisi: it's possible to make diff plugins for git that are smarter about individual languages |
| 12:30 | osfabibisi | justin_smith: is there one for clojure that you can recommend? |
| 12:30 | justin_smith | it would be cool to make a diff plugin for clojure using planck (since it starts up fast and knows about clojure syntax...) |
| 12:30 | justin_smith | osfabibisi: not that I know of, but I think it would be an awesome idea |
| 12:30 | justin_smith | diffing by form/sexp rather than line... |
| 12:30 | osfabibisi | that said, diffing by sexp isn't my problem here |
| 12:31 | osfabibisi | it's 2 forms changing order e.g. (defn foo ......) (defn bar ......) getting swapped around |
| 12:31 | osfabibisi | which always results in one hunk being deleted from origin point and added to new point, because diff algos only work on things as sequences |
| 12:32 | justin_smith | osfabibisi: that's what I mean, if it was looking at balanced forms / subforms, it would know not to do weird splitting in the middle like that |
| 12:32 | justin_smith | it's diffing by line, which gives the weirdness |
| 12:32 | osfabibisi | no no, I've explained badly, sorry |
| 12:33 | osfabibisi | e.g. the definition of (defn foo ...) moves from line 15 to line 100 |
| 12:33 | justin_smith | osfabibisi: I think we just disagree about why git is misbehaving |
| 12:33 | justin_smith | I know the behavior |
| 12:33 | osfabibisi | the forms are still balanced |
| 12:33 | amalloy | i think osfabibisi is complaining about even more benign behavior than you're thinking of |
| 12:42 | osfabibisi | yes, I think I understand what justin_smith is talking about - when 2 forms share common features |
| 12:43 | osfabibisi | but in this case they're not incorrectly misidentified, they've just moved |
| 12:45 | amalloy | there's not really a lot you can do about that in the unix diff model, since it's line based. there are sexp-based diff tools out there, though i don't know how good they are or whether you can get them involved in git diff at all |
| 12:45 | Ardx | so if I have a tree, made of hash maps, and then I have a list [:area :top], is there a function that does something like (get-leaf root-map [:area :top]), and iterates that list and goes down through the tree? |
| 12:47 | amalloy | actually i bet you could configure diff.tool to point to a shell script that launches your sexp differ for .clj files and a standard diff otherwise |
| 12:47 | Ardx | or I could use a macro to turn it into "(-> :area :top)" I guess |
| 12:47 | amalloy | (doc get-in) |
| 12:47 | clojurebot | "([m ks] [m ks not-found]); Returns the value in a nested associative structure, where ks is a sequence of keys. Returns nil if the key is not present, or the not-found value if supplied." |
| 12:47 | osfabibisi | probably. but again if it's sequence-based that won't really help for this case |
| 12:47 | osfabibisi | instead, I'm just going to give colleagues a hard time about their commit being impossible to review :D |
| 12:47 | Ardx | amalloy cheers! |
| 13:04 | justin_smith | amalloy: yeah- a sexp based diff for sexp languages was kind of what I had in mind |
| 13:55 | osfameron | what's the minimum I need to do to set a classpath in a boot repl? |
| 13:55 | osfameron | e.g. I have a project template I know works, if I have src/project/foo.repl and a namespace project.foo |
| 13:56 | osfameron | and a boot.build and so on |
| 13:56 | osfameron | but if I just want to edit scratch.clj to play around then my editor complains " Could not locate scratch/scratch__init.class or scratch/s |
| 13:56 | osfameron | cratch.clj on classpath" |
| 14:05 | justin_smith | osfameron: for super basic stuff I just use load-file |
| 14:05 | justin_smith | eg. $ vim /tmp/scratch.clj then (load-file "/tmp/scratch.clj") |
| 14:05 | justin_smith | I leave require and such for things that are defined parts of my project |
| 14:06 | justin_smith | (I did find the annoying fact that I can't do macros in planck this way - it only allows macros via classpath... but that's the only hiccup I've had for this workflow) |
| 14:07 | osfameron | justin_smith: you mean from the repl itself? |
| 14:07 | osfameron | ah yes, that works |
| 14:08 | osfameron | and then fireplace stops complaining |
| 14:08 | osfameron | ta |
| 14:08 | justin_smith | osfameron: yes, I call load-file from the repl - though most editors with clojure integration have a simple keypress that invokes load-file |
| 14:09 | osfameron | fireplace has the odd thing that it's supposed to be namespace aware, but it can't seem to resolve the location of a file it actually has open... |
| 14:09 | osfameron | it all works with a properly set up project of course |
| 14:10 | justin_smith | aha - I use fireplace but only in a very rudimentary way - I think I just assumed that rando .clj file would not play nicely so I should use blunt tools like load-file |
| 14:10 | justin_smith | but that was based on hunches, not expertise |
| 14:11 | osfameron | if you open a project with a proper boot (or I imagine leiningen) setup, then everything Just Works |
| 14:11 | justin_smith | yeah, all my work since I started using fireplace is in a library that doesn't have its own repl / process, so I have not been so lucky |
| 14:12 | osfameron | and you can't use clojure's builtin repl? |
| 14:12 | justin_smith | osfameron: I have an app, the app runs from two repls, this library is used by each of the repl based apps |
| 14:12 | justin_smith | point being that the code I am editing is not on the classpath of either repl - they are using the version that was put in cache by lein install |
| 14:13 | osfameron | ah. sounds complicated |
| 14:13 | justin_smith | and I refuse to muck with the whole symlink nonsense |
| 14:13 | justin_smith | osfameron: it would be super complicated if I tried to have convenient tooling, but all I need is a repl plus load-file and things work |
| 14:14 | osfameron | :D |
| 14:14 | justin_smith | eg. there are two different repls that both want the new version of foo.clj - doing this via the editor would be silly |
| 14:16 | justin_smith | since editor tooling that allows multiple repls wants to map a file to a single repl in my experience |
| 14:22 | Ardx | ended up using assoc-in |
| 14:22 | Ardx | and an atom for the tree root :D |
| 14:23 | Ardx | and turned the macro into a function, so I could actually step throguh and debug the many problems the code had |
| 14:23 | Ardx | god dang are clojure errors cryptic though |
| 14:24 | justin_smith | Ardx: a good design strategy is to use a function for all your logic, and if you need a custom syntax, make a minimal macro where the function is doing the real work |
| 14:24 | justin_smith | I think you've learned already how much easier that is to debug (also if you need to build more functionality, a function is a much easier starting point than a macro usually) |
| 14:25 | machinewar | do you think clojure.spec would be good solution for masking data? pretty much need to restore data from one db to another, but obfuscate some of the data (but it needs to still resemble valid data) |
| 14:25 | machinewar | so I'm thinking you could for example describe the shape of a postal code, a first name, last name, etc |
| 14:25 | machinewar | and use it at runtime to generate fake data |
| 14:25 | justin_smith | that doesn't sound like what spec is for at all... |
| 14:25 | justin_smith | I mean I guess it plugs into generators for testing purposes... |
| 14:26 | machinewar | yea that's what I'm thinking |
| 14:26 | Ardx | justin_smith yeah keeping macros small sounds like a good plan |
| 14:27 | justin_smith | Ardx: of course there's special cases like core.match and core.async which build whole languages (very useful languages!) that can't just be summed up with a bunch of functions, but those are very special |
| 15:46 | justin_smith | why would a ref have a name? |
| 15:47 | dysfun | did you call name on it? |
| 15:47 | osfameron | hmm, maybe I don't mean refs then? "stuff that you've def'd" ? |
| 15:47 | dysfun | vars! |
| 15:47 | justin_smith | vars? |
| 15:47 | osfameron | dysfun: yes! |
| 15:47 | clojurebot | vars are a linking construct |
| 15:47 | dysfun | vars are not refs |
| 15:47 | osfameron | right, so vars then. |
| 15:47 | osfameron | they have names don't they? |
| 15:48 | justin_smith | ,(:name (meta #'+)) |
| 15:48 | clojurebot | + |
| 15:48 | osfameron | that doesn't seem to work for things I've def'd or defn'd myself though |
| 15:49 | justin_smith | def and defn both attach :name |
| 15:49 | justin_smith | (as a metadata) |
| 15:49 | osfameron | ah, I missed the #' bit... what does that do? |
| 15:50 | justin_smith | accesses the var |
| 15:50 | justin_smith | + points to the function pointed at by the var |
| 15:50 | osfameron | ah... instead of the value? |
| 15:50 | justin_smith | #'+ gets the var itself |
| 15:50 | osfameron | ok |
| 15:50 | amalloy | osfameron: imagine (def x 1) |
| 15:50 | amalloy | you want x to eval to 1, not to a var |
| 15:50 | justin_smith | ,#'+ |
| 15:50 | clojurebot | #'clojure.core/+ |
| 15:50 | justin_smith | err |
| 15:50 | justin_smith | ,'#'+ |
| 15:50 | clojurebot | (var +) |
| 15:50 | amalloy | but sometimes, you want to get at the var anyway, and that's what #'x does |
| 15:50 | osfameron | ok |
| 15:51 | justin_smith | #' is a reader macro, shorthand for (var ) |
| 15:51 | amalloy | the name can't be stored on the value 1, and is instead stored on the var |
| 15:51 | osfameron | so why doesn't (name #'+) work? |
| 15:51 | justin_smith | well that's a more controversial decision |
| 15:51 | amalloy | so, name is for getting the "name" part of a name+namespace pair thingy |
| 15:51 | justin_smith | but regardless of reasons, at least the :name key on the metadata will help |
| 15:51 | osfameron | true |
| 15:51 | osfameron | thanks! |
| 15:51 | amalloy | and a var is not one of those; it is a lot more things than just a name |
| 15:52 | osfameron | ah |
| 15:52 | dysfun | a var *has* a named thing, but it isn't one |
| 15:52 | amalloy | ,(keys (meta #'inc)) |
| 15:52 | clojurebot | (:arglists :doc :inline :added :line ...) |
| 15:53 | osfameron | well, that was all so exciting, I've now forgotten why I thought I wanted to call (name) on a var in the first place... |
| 15:56 | justin_smith | osfameron: my assumptions is shenanigans of some sort |
| 15:56 | justin_smith | osfameron: consider that given a symbol, you can get a var and a name from it |
| 15:56 | justin_smith | ,((juxt name resolve) '+) |
| 15:56 | clojurebot | ["+" #'clojure.core/+] |
| 15:56 | justin_smith | maybe that's what you wanted? resolve is good for shenanigans |
| 15:56 | amalloy | a symbol and a namespace |
| 15:57 | justin_smith | amalloy: well, symbols can be namespaced, and resolve will use your namespace's lookup rules to find a namespace |
| 15:57 | amalloy | yes, "your namespace" is the namespace here that you need |
| 15:58 | amalloy | calling resolve at runtime outside of a repl without specifying a namespace is going to give you trouble |
| 15:58 | justin_smith | right, because your thing likely isn't available by any shorthand in user |
| 15:58 | osfameron | justin_smith: ooo, thanks |
| 15:59 | amalloy | (because *ns* is bound to the current namespace while in a repl, but it's not when running an actual program via -main) |
| 15:59 | justin_smith | amalloy: in my experience it's always bound to user, unless someone made some effort to switch it |
| 15:59 | justin_smith | I've never seen it unbound |
| 16:00 | amalloy | what i mean is, it's not bound to any useful value that you might think of as "the current namespace" |
| 16:00 | justin_smith | fair |
| 16:01 | technomancy | doesn't resolve DTRT when passed a qualified symbol? |
| 16:01 | osfameron | if I want to go the other way - e.g. I have a map of {name function, ...} what's the best way to get those defn'd together? |
| 16:01 | justin_smith | technomancy: if it's fully qualified, yes |
| 16:01 | technomancy | oh justin said that already |
| 16:01 | justin_smith | osfameron: intern |
| 16:02 | justin_smith | osfameron: the tricky part is that intern doesn't add the nice metadata that def/defn do |
| 16:02 | justin_smith | in my experience intern is a good sign you are being too clever for your own good (moreso than resolve is even) |
| 16:03 | osfameron | yes, probably |
| 16:03 | osfameron | it's quite a common ask in e.g. Perl though |
| 16:03 | justin_smith | osfameron: consider that looking something up in a hashmap and calling it is perfectly acceptable |
| 16:03 | osfameron | where you can define exporters custom exporters for functions |
| 16:03 | justin_smith | sure, and perl is known for tricky business as a common programming style, right? |
| 16:04 | justin_smith | I'm not saying intern is never valid, just that it indicates you are likely adding complexity, which is a good moment to ask what you are getting in return for that cost |
| 16:04 | osfameron | well, that's part of doing hard work *behind the scenes* to get a nice API for the user of a library |
| 16:04 | osfameron | but yes, point taken, and I'll see if I can avoid it :D |
| 16:05 | justin_smith | osfameron: but clojure is a very introspective and reflective language, and libraries that make it hard to find definitions or map definitions back to some form are really annoying |
| 16:05 | osfameron | is that a problem if I set the metadata politely? |
| 16:05 | justin_smith | we have a lot of tools to find the code that generated a thing, but tricks like intern undermine them |
| 16:06 | justin_smith | osfameron: hmm, I wonder how hard it would be to set the right file/line metadata automatically... |
| 16:07 | osfameron | so the thing I'm thinking about is a logging library |
| 16:08 | osfameron | (info "hello") might write to stdout or it might send a message to a queue or whatever |
| 16:08 | osfameron | and I want to avoid a singleton global |
| 16:08 | osfameron | (info my-logger "hello") is ok, and doesn't need any cleverness |
| 16:09 | justin_smith | aside - (but don't most clients of logging libraries expect a global behavior?) |
| 16:11 | osfameron | hmm, maybe? |
| 16:11 | osfameron | I think dysfun mentioned that being something he didn't like about timbre |
| 16:12 | osfameron | and it chimed with whatever I was thinking |
| 16:12 | osfameron | anyway, you could always (info *global-logger* "hello") if you wanted it :D |
| 16:12 | justin_smith | I don't fully agree, but I've seen it argued that logging config should be global and static and hard to modify dynamically because security |
| 16:13 | osfameron | static sure, but why does global help there? |
| 16:14 | osfameron | I kinda understand why people want the dynamic behaviour, but I've found that confusing far more often than actually useful |
| 16:16 | justin_smith | I guess less complexity means less possibility for corner cases or unexpected combinations of behaviors |
| 16:16 | justin_smith | it wasn't my argument so I'm not sure :) |
| 16:17 | justin_smith | I mean, once someone can change a var in my clojure program, that machine is hosed, messing with logging is the least of it |
| 16:20 | jonathanj | Where do you get the logger from that you want to log to? |
| 16:23 | jonathanj | Is it okay if your library uses a different logger than the user calling your library? |
| 16:24 | jonathanj | It seems (but perhaps I don't fully understand) like it would be annoying if a library logged stuff somewhere else when I don't want it to. |
| 16:28 | justin_smith | jonathanj: I don't really get logging but/and I find "annoying" a good description for all my interactions with things related to logging |
| 16:29 | jonathanj | I'm probing because I'm on the brink of porting a logger library to Clojure and I'd like a nice API. |
| 16:30 | osfameron | yeah, logging tends to be overcomplicated, overengineered and badly documented |
| 16:30 | jonathanj | I thought of having something like `(with-logger a-logger some forms)` rebind `*logger*`. |
| 16:31 | dysfun | i hope you didn't want some async with that because dynamic bindings are thread local |
| 16:31 | jonathanj | I was wondering about that. |
| 16:32 | justin_smith | I've been briefly enticed with ideas of software friendly logging (eg. every log is a json record including level and namespace etc. and the one reading the logs uses a client to filter and format) |
| 16:32 | dysfun | (in fact i use them in my single threaded cljs refs implementation) |
| 16:32 | jonathanj | So if any of those forms are async then I guess you need to wrap the logger at another level. |
| 16:32 | technomancy | justin_smith: how about https://brandur.org/logfmt |
| 16:32 | dysfun | justin_smith: i think riemann is a good base for that sort of thing |
| 16:33 | jonathanj | justin_smith: the library I intend on porting is http://eliot.readthedocs.io/ which might be an inspirational read then |
| 16:33 | justin_smith | technomancy: I've never seen that, interesting |
| 16:33 | technomancy | justin_smith: we used it heavily at heroku and it was <3 |
| 16:34 | justin_smith | see, all these things are great, but they are improvements to a thing I find very unpleasant so my likelyhood of taking them on is lower |
| 16:35 | technomancy | the team I was on at heroku was literally the logging team =) |
| 16:36 | technomancy | it was an island of erlang in a sea of ruby/golang so I wasn't complaining |
| 16:36 | justin_smith | hah, nice |
| 16:36 | jonathanj | After having used Eiot for some complex logging, being able to visualise the hierarchy seems like a can't-go-back experience. |
| 16:36 | patchwork | justin_smith: I like your vision of logging. That is all it needs to be |
| 16:37 | dysfun | always fun to play with things like erlang |
| 16:37 | patchwork | (tears out swaths of logging code from project) |
| 16:37 | patchwork | technomancy: Are you anti-golang? Is golang the devil? I haven't tried it yet |
| 16:37 | patchwork | You used it in the same sentence as ruby so.... |
| 16:37 | technomancy | patchwork: it's ... not a good programming language |
| 16:38 | patchwork | I have a coworker who is an evangelist of golang right now |
| 16:38 | patchwork | since I don't have any experience with it I don't really have a good response for the guy |
| 16:38 | dysfun | technomancy: diplomacy, you has it. i would be less polite about it than that |
| 16:38 | technomancy | we use it some at work and the only reason I can live with it is that no one is evangelistic about it |
| 16:39 | patchwork | What are the issues? I thought the goal towards concurrency and minimalism coincides with why I love clojure |
| 16:39 | patchwork | Like I said though, haven't tried it |
| 16:39 | technomancy | patchwork: it's very clearly designed by someone who hasn't done their homework around type systems, to say the least |
| 16:40 | dysfun | or on many other areas critical to it, like garbage collection |
| 16:40 | patchwork | Ah okay.... after working in scala for the past year I am starting to resent heavy type systems ; ) |
| 16:40 | technomancy | like ... what's the most common type error by at least an order of magnitude? null references. so you would think then if you were designing a type system, handling null references would be the first thing you would encode into it? not in golang. =( |
| 16:40 | patchwork | but maybe that is just because of implicits |
| 16:41 | technomancy | scala at least has the interop excuse; golang has no excuse. |
| 16:41 | patchwork | Ah yes, null references |
| 16:41 | technomancy | "this is how we did it in the 1970s so it's probably the best way to do it" |
| 16:41 | patchwork | Something I have been very happy to do away with in scala |
| 16:41 | patchwork | haven't had one of those in a long time |
| 16:41 | patchwork | I see, funny! |
| 16:41 | dysfun | and whoever thought it was a good idea to make all the containers non-threadsafe in a highly concurrent language, well that's just a stroke of genius |
| 16:41 | l1x | golang is amazing i think interface{} is just a pretty nice way of saying go and fuck yourself and your types |
| 16:41 | patchwork | You think the google people would put someone more thoughtful on their signature language design team |
| 16:42 | technomancy | also "pass by value semantics" aka we are going to implicitly copy all values for every function call unless you opt out of it |
| 16:42 | dysfun | signature language? perhaps you mean dart? |
| 16:42 | technomancy | patchwork: famous is apparently an acceptable replacement for thoughtful |
| 16:42 | l1x | yeah that too |
| 16:42 | dysfun | technomancy: oh yes, it's *definitely* a replacement for C! |
| 16:42 | patchwork | Ah, I thought golang was their flagship |
| 16:42 | l1x | the lack of proper types bothers me more though |
| 16:43 | patchwork | Cool, so it is better than C |
| 16:43 | patchwork | Progress is good |
| 16:43 | l1x | like we did not have ocaml or any good languages with decent type systems |
| 16:43 | dysfun | patchwork: that was sarcasm |
| 16:43 | patchwork | Thanks for the summary! |
| 16:43 | l1x | patchwork: it is good for a single reason: CSP |
| 16:43 | technomancy | patchwork: my favorite way to describe golang's type system is it's like wearing a bulletproof vest with a big gaping hole over the heart. it's bulky and impedes your movement, but it doesn't actually protect your most vital organs. |
| 16:43 | l1x | :D |
| 16:44 | patchwork | dysfun: I don't know what sarcasm is anymore |
| 16:44 | dysfun | there isn't a hole to get into it because they don't support generic vests |
| 16:44 | l1x | well go is pretty good if you are a python programmer |
| 16:44 | l1x | hey look ma, i can ship a single binary! |
| 16:44 | dysfun | l1x: so one of my friends is currently writing cgo and FFIing from python... |
| 16:44 | l1x | there you go! :) |
| 16:45 | technomancy | l1x: it's funny how ruby and python people are so impressed by such a simple thing |
| 16:45 | dysfun | tbf it's a cool thing |
| 16:45 | dysfun | single artifact deployments are ace |
| 16:45 | osfameron | uberjars! |
| 16:45 | l1x | technomancy: yeah, they havent seen ocaml this is why |
| 16:45 | technomancy | dysfun: yeah but racket, ocaml, lua... this is not exactly a high bar |
| 16:46 | dysfun | sure |
| 16:46 | technomancy | it's just the jvm/python/ruby go out of their way to make things difficult |
| 16:46 | patchwork | It is for people who've never seen it before ; ) |
| 16:46 | l1x | do you want a single binary? or do you want byte code? do you want union types? do you have Some(x) or None? Please be my gues |
| 16:46 | osfameron | is Rust more interesting? |
| 16:46 | l1x | guest* |
| 16:46 | technomancy | osfameron: by a long shot |
| 16:46 | l1x | yeah |
| 16:47 | l1x | it has almost all the great features of ml languages |
| 16:47 | technomancy | osfameron: the original rust compiler was written in ocaml, so you know it's designed by someone who hasn't been ignoring the last couple decades of research |
| 16:47 | l1x | yep |
| 16:47 | patchwork | I mean, right now the heavyweight nature of the JVM is a pretty big strike against it |
| 16:48 | patchwork | I am shipping a 300MB uberjar.... it raises some eyebrows |
| 16:48 | l1x | sure |
| 16:48 | osfameron | for some applications yeah |
| 16:48 | patchwork | Mostly of code I did not write |
| 16:48 | l1x | this is because many of the Java devs are morons |
| 16:49 | technomancy | it's a great fit for server-side code but not a one-size-fits-all by any means |
| 16:49 | l1x | http://mail-archives.apache.org/mod_mbox/orc-user/201702.mbox/%3CCAB25XEXALvkPWcG1mf6VRS-C0ZXvfdZGww-Bf-mgYiFo%2BhObaw%40mail.gmail.com%3E |
| 16:49 | l1x | story of today |
| 16:50 | dysfun | but rust has some horriblenesses |
| 16:50 | dysfun | like a constant deprecation cycle |
| 16:51 | l1x | yeah, i am not going to use it before it turns 10 years old |
| 16:51 | l1x | that is the qualifier for a programming language |
| 16:51 | dysfun | and the libraries are way too immature. they're trying to get the type safety and doing it at the cost of the flexibility you need from a systems language |
| 16:51 | dysfun | like don't even get me started about things like raw files last time i tried |
| 16:51 | technomancy | wait a minute... |
| 16:51 | l1x | :D |
| 16:51 | dysfun | wasn't clojure 2006? |
| 16:52 | dxtr | It takes 30 seconds to start the jvm on my other laptop. Just food for thought :p |
| 16:52 | technomancy | dysfun: I guess it depends on if you're counting from first commit or first public commit |
| 16:52 | l1x | First appeared 2007; 10 years ago |
| 16:52 | dysfun | dxtr: over a minute on a shitty box i borrowed last year when i was down on my luck |
| 16:52 | l1x | what?! :D |
| 16:52 | dxtr | dysfun: :D |
| 16:52 | dysfun | technomancy: close enough then :) |
| 16:53 | l1x | dxtr: well it is slow but once it is up!! |
| 16:53 | dysfun | yes and no |
| 16:53 | dxtr | l1x: Once the help text shows it shows it lightning fast! |
| 16:53 | patchwork | Well luckily you don't ever need to modify your code |
| 16:53 | dysfun | i swear too many silicon valley people think we're all running supercomputers |
| 16:53 | dxtr | dysfun: Are we not? |
| 16:54 | dysfun | "i write my shell scripts in clojure" "i don't have a minute to wait for them to start" |
| 16:54 | l1x | hahaha |
| 16:54 | l1x | actually ocaml is much better for "shell scripts" |
| 16:54 | justin_smith | dysfun: did you meantion you were working on a lumo fork at some point? |
| 16:54 | dysfun | yeah, there are some good libs for that |
| 16:54 | l1x | dxtr: have you tried a neutered jvm? |
| 16:54 | technomancy | dysfun: my personal laptop is a core 2 duo |
| 16:54 | justin_smith | l1x: yeah - you can even compile ocaml to machine code from source, then run it, fast enough :) |
| 16:54 | dxtr | Remember that time when you parallelized some stuff in ocaml? |
| 16:55 | l1x | justin_smith: yep exactly that |
| 16:55 | patchwork | Just wrote a script in planck a few days ago.... that is my new paradigm |
| 16:55 | technomancy | have been enjoying mostly writing luajit on that |
| 16:55 | dysfun | justin_smith: no. i am working on a build tool that uses lumo |
| 16:55 | dxtr | l1x: I have not |
| 16:55 | justin_smith | aha, now I get it - that's smart |
| 16:55 | technomancy | dxtr: the best thing about ocaml is it's like the mirror world of the jvm. low memory usage, terrible at concurrency, no %$@& nils, spock has a beard, etc |
| 16:56 | patchwork | Ah sigh.... so 2017, we still don't have the perfect programming environment |
| 16:56 | dxtr | technomancy: It can do concurrency fine |
| 16:56 | patchwork | Someone told me we would have this down by now |
| 16:56 | dxtr | technomancy: Parallelism on the other hand :) |
| 16:56 | patchwork | dxtr: Oh yeah? Just by spawning a new process and communicating over sockets? |
| 16:56 | l1x | technomancy: hahaha this is a perfect explanation |
| 16:56 | technomancy | dxtr: well I mean literal concurrency |
| 16:56 | justin_smith | patchwork: we might not have the perfect programming language, or flying cars, but you can get "croc martens" boots |
| 16:56 | l1x | but hey, concurrency is coming! :) |
| 16:57 | patchwork | Based on the way most people I see drive, I am super glad we don't have flying cars yet |
| 16:57 | l1x | well self driving flying cars |
| 16:57 | technomancy | patchwork: maybe we could wait till decent type systems become a bit more widespread before coding self-driving flying cars |
| 16:58 | dxtr | patchwork: Either that or you could just use the async package, for example. |
| 16:58 | l1x | btw. clojure got really fast over the years, lein repl is much faster to start up, lein uberjar is also more performant |
| 16:58 | technomancy | you put wings on that sucker and it better be written in Ada or an ML spinoff |
| 16:58 | l1x | i remember when lein repl took a decent amount of time |
| 16:58 | technomancy | lein repl is fast now? cool! |
| 16:58 | l1x | maybe because of java 1.8 |
| 16:59 | l1x | technomancy: what do you use instead? |
| 16:59 | patchwork | Just started lein repl.... 5 seconds |
| 16:59 | l1x | since you wrote it, i bet you use lein :) |
| 16:59 | dysfun | 3s here, but this is a nice machine |
| 16:59 | technomancy | l1x: I use lein inside docker-compose where it takes like five minutes to bring up the whole cluster |
| 16:59 | l1x | nice |
| 17:00 | dysfun | boot repl took 20s! |
| 17:00 | dxtr | Also, I started with clojure las week! Yay me, or something |
| 17:00 | l1x | dxtr: \o/ |
| 17:00 | dxtr | I've been putting it off for years because jvm |
| 17:01 | l1x | dxtr: the best part is the community |
| 17:01 | l1x | like seriously |
| 17:01 | dysfun | dxtr: you learn to live with it. i was a massive java hater when i started with clojure |
| 17:01 | l1x | dxtr: the reason i started to use clojure because i could not even read java at the time |
| 17:01 | dxtr | dysfun: I have actually done Java professionally :p |
| 17:01 | l1x | dysfun: highfive |
| 17:01 | justin_smith | $ time java -jar ~/bin/clojure.jar -e '(System/exit 0)' => real 0m2.866s |
| 17:02 | dysfun | clojure is truly a breakthrough: it enables me to tolerate writing code that runs on the jvm |
| 17:02 | dxtr | I don't mind the jvm in itself. It's the bulkyness I dread |
| 17:02 | dysfun | i don't mind the jvm either, but the traditional way of programming it was java, which i do mind |
| 17:02 | l1x | dxtr: once in production this does not matter really |
| 17:03 | dysfun | even the java standard libraries aren't so bad driven with clojure |
| 17:03 | dxtr | What clojure needs is more templating, amirite? |
| 17:03 | l1x | most of our projects are 10-50MB uberjars where 95% is libraries not even needed but Java devs just add dependencies like trump outputs executive orders |
| 17:04 | l1x | dxtr: not sure |
| 17:04 | dxtr | :p |
| 17:04 | dysfun | (in particular i have to say AWT is a really nice API - transformation steps return new data rather than modifying in place) |
| 17:04 | l1x | i do not use too much templating |
| 17:04 | technomancy | if you can get over the horrid name http://docs.racket-lang.org/rackjure/index.html is a great way to write clojurey code without the huge jvm overhead |
| 17:04 | dxtr | l1x: I made a funny Java joke |
| 17:05 | dysfun | technomancy: they made ~> and ~>> more powerful than clojure's -> and ->> didn't they? |
| 17:05 | l1x | dxtr: no java jokes are funny :D |
| 17:05 | l1x | technomancy: racket does not have the libraries i need for my work |
| 17:05 | technomancy | dysfun: I hadn't heard that |
| 17:05 | dysfun | libraries are why i ended up sticking with clojure |
| 17:05 | l1x | this is why clojure is winning, there is a (shitty) java lib for everything |
| 17:06 | dxtr | l1x: Also, the worst part about Java stuff is the XML that surrounds it. I learned to hate a lot of things when I coded java at the job :p |
| 17:06 | l1x | dxtr: edn ftw |
| 17:06 | technomancy | l1x: well it's good to have options anyway |
| 17:06 | dxtr | Mainly XML and factory patterns |
| 17:06 | l1x | technomancy: true that |
| 17:06 | dysfun | i think most professional java devs know how to drive IDEs that generate boilerplate for them |
| 17:06 | l1x | how is CSP/concurrency in racket? |
| 17:07 | dxtr | dysfun: Which sucks when things break |
| 17:07 | technomancy | l1x: you get real threads, but the GC is stop-the-world. I would be surprised if there weren't a good CSP implementation but I don't know if it ships in the stdlib |
| 17:08 | l1x | i see |
| 17:08 | dxtr | well, Racket isn't really made to be performant, is it? |
| 17:08 | l1x | this is why i think lfe is a better direction |
| 17:08 | l1x | the erlang no global vm stop is just amazing |
| 17:08 | technomancy | dxtr: it's made serious strides in the past few years (especially on ARM) but nothing like the JVM |
| 17:09 | l1x | dxtr: last time i checked it was up in the same bracket with clojure in terms of http-hello-world-micro-benchmark-e-penis |
| 17:09 | technomancy | actually there was a brief window when racket could beat clojure on ARM performance |
| 17:09 | technomancy | when most of hotspot's jit smarts were x86-only |
| 17:09 | l1x | and it does not require a 160MB JVM |
| 17:10 | dysfun | l1x: i lost faith in lfe |
| 17:10 | dxtr | I just go with erlang |
| 17:10 | l1x | dysfun: how about joxa? :) |
| 17:10 | technomancy | joxa's design is great |
| 17:10 | l1x | dxtr: alright, erlang than! :) |
| 17:11 | dysfun | partially i think erlang is a nicer language, partially i'm not happy with some fundamental qualities of the erlang vm |
| 17:11 | l1x | i like erlang but i cannot find developers who i could work with |
| 17:11 | l1x | dysfun: like? |
| 17:11 | l1x | i really like beam |
| 17:11 | dysfun | for example the atom table |
| 17:11 | dysfun | we wrote some generative tests for lfe and it would exhaust the atom table and crash the BEAM |
| 17:12 | dysfun | and the fact that the builtins can't spawn processes and reliably recover if they close (they expect an EOF character!) |
| 17:12 | l1x | even when you configure it right? |
| 17:12 | dxtr | Well, to be fair, if you're generating that many atoms you should consider another data structure |
| 17:12 | dysfun | OS processes i mean, not erlang processes |
| 17:12 | dysfun | dxtr: hard to do generative tests involving atoms without generating lots of atoms |
| 17:13 | l1x | dysfun: these are sort of issues that either i dont care or if i had to care i could solve them |
| 17:13 | dxtr | dysfun: Just seems like a weird thing to do :p |
| 17:13 | dysfun | generative testing? yeah it is but it's great |
| 17:14 | l1x | By default, the maximum number of atoms is 1,048,576. This limit can be raised or lowered using the +t option. |
| 17:14 | l1x | there, easy to fix for a real world use case |
| 17:14 | dysfun | l1x: of course, but the solutions here involve reserving memory for a large atom table and shipping extra C |
| 17:15 | dxtr | Also, the vm is pretty slow |
| 17:15 | dysfun | compared to the jvm, sure |
| 17:15 | dxtr | Compared to most things? |
| 17:15 | dysfun | nah |
| 17:16 | l1x | dysfun: what is the usecase when 1,048,576 atoms are not enough? |
| 17:16 | dysfun | erlang compares favourably with dynamic langs |
| 17:16 | l1x | also erlang beats almost everything with template rendering |
| 17:17 | l1x | might not be true anymore |
| 17:21 | dysfun | templatewise, everyone uses erydtl |
| 17:26 | dysfun | technomancy: do you prefer racket or clojure? |
| 17:27 | technomancy | dysfun: depends on what I'm doing I guess. I wouldn't do server-side stuff in racket, and I wouldn't do guis and CLI tools in clojure (with the obvious exception of lein) |
| 17:28 | dysfun | i saw they're moving to chez scheme because it's faster |
| 17:28 | technomancy | dysfun: I feel like Racket has historically had the edge on "prevent flexibility from becoming an unmaintainable mess over time" but now that Racket contracts are becoming part of Clojure that advantage is likely to lessen. |
| 17:28 | technomancy | I'm one of the weird ones who has never cared about speed |
| 17:30 | justin_smith | technomancy: "slow code" - hammock developed artisinal quality algorithms |
| 17:30 | technomancy | apart from leiningen startup I have only once had to profile Clojure code because it was too slow |
| 17:30 | technomancy | justin_smith: on a thinkpad from 2008! |
| 17:30 | justin_smith | sounds like a pitch |
| 17:34 | technomancy | dysfun: just for the record when I was hanging out in the #racket channel I frequently brought up how silly it was that hash-tables aren't callable and how their "just get the latest version of that lib lol" dependency system worked was ill-advised, etc |
| 17:35 | technomancy | I bring it up here more to avoid the echo chamber effect than to convince people to stop using clojure =) |
| 17:35 | dysfun | heh |
| 17:35 | dysfun | we tend to be free with our criticism of clojure in here too |
| 17:36 | dysfun | racket ~> tries to fix that, btw |
| 17:37 | technomancy | dysfun: racket or rackjure? |
| 17:37 | dysfun | (~> foo 'a 'b) -> (dict-ref (dict-ref foo 'a) 'b) |
| 17:37 | dysfun | rackjure, sorry |
| 17:37 | technomancy | IIRC rackjure fixes callable hash tables in a way that is not related to ~> |
| 17:37 | dysfun | that also |
| 17:38 | dysfun | of course you pay a performance penalty for those checks |
| 17:39 | technomancy | which is why regexes still aren't IFn in clojure =( |
| 17:39 | l1x | i was profiling clojure several times and rewrote parts that were slow |
| 17:39 | dysfun | well, if we moved to protocols for everything like cljs did, we *could* |
| 17:39 | l1x | just to beat java devs like 100x |
| 17:40 | l1x | 10x was not good enough for me :) |
| 17:40 | l1x | threading is a bitch :( |
| 17:40 | dysfun | but that's not particularly likely, i think |
| 17:40 | technomancy | dysfun: how do you implement protocols if you can't define functions yet? |
| 17:41 | dysfun | fall back to Runnable |
| 17:42 | l1x | one guy was trying to convince our ceo that the bottleneck was our network (10G/s) and i was surprised to figure out he used a single thread to do network IO to a remote datacenter |
| 17:42 | technomancy | then you can't declare any protocol functions that take args though, right? |
| 17:42 | dysfun | okay, Callable then |
| 17:43 | technomancy | IIUC the only reason you don't have circularity issues on JS is that you can change your initial protocol implementation once you've bootstrapped enough of the language |
| 17:44 | dysfun | i haven't looked into it. i can see there are difficulties, but i think it's a bit moot because it would be a huge compatibility-breaking change at this point |
| 17:46 | technomancy | some day I'll be able to (filter #"correct horse battery staple" passwords) |
| 17:46 | dysfun | that would be pretty neat |
| 17:50 | justin_smith | technomancy: I knew someone once who called this "exampling" - where a concept is sound but someone takes an example of the concept's usage and follows literally, and remains ignorant of the concept itself |
| 17:51 | technomancy | justin_smith: sounds like a useful term but I'm not seeing the connection |
| 17:51 | justin_smith | technomancy: "here is how you can create a high entropy string that is straightforward to remember" |
| 17:51 | technomancy | oh haha right |
| 17:51 | justin_smith | "oh, OK, I will always remember that one high entropy string you used! |
| 17:51 | justin_smith | " |
| 17:52 | justin_smith | which is like, pathologically against the original point :) |
| 17:52 | technomancy | https://xkcd.com/221/ |
| 17:52 | justin_smith | that's another good example of exampling actually |
| 17:52 | clojurebot | I don't understand. |
| 17:52 | justin_smith | clojurebot: you wouldn't, dummy |
| 17:52 | clojurebot | Pardon? |
| 18:06 | fifi-v | how can I play sound in reagent? Need something equivalent to js `new Audio("...")' and `.play()' as demonstrated here http://stackoverflow.com/a/23395136 |
| 18:08 | justin_smith | fifi-v: that's not reagent specific is it? |
| 18:10 | justin_smith | fifi-v: (js/Audio. "data.....") |
| 18:10 | justin_smith | (.play ...) |
| 18:10 | justin_smith | fifi-v: this will all use standard interop syntax, it's pretty simple and well documented and worth learning |
| 18:14 | dxtr | Is korma a good choice for postgresql stuff? |
| 18:16 | dysfun | depends what you need |
| 18:16 | dysfun | it doesn't have json operator niceties |
| 18:16 | dysfun | it's very good for bread and butter traditional queries |
| 18:17 | amalloy | korma is more of a naan and curry thing than bread and butter |
| 18:18 | dysfun | har har |
| 18:18 | technomancy | did someone pick up the development of korma? I thought it was abandonware for some time |
| 18:19 | amalloy | abandonware doesn't have to be brokenware |
| 18:19 | dysfun | it still works. it hasn't seen much action, but it's not total abandonware i think |
| 18:19 | amalloy | (i have no opinion about korma personally, i just don't really go for the "x hasn't been committed to in two months, therefore it must be garbage" attitude i see sometimes) |
| 18:20 | technomancy | amalloy: I was thinking more like 4 years but sure |
| 18:20 | dysfun | korma is okay for the 90% |
| 18:20 | dysfun | the limitations it puts on the remaining 10% triggered me to start building something more powerful though |
| 18:24 | dxtr | technomancy: Last commit was 11 days go, apparently |
| 18:24 | technomancy | cool |
| 18:26 | dxtr | So what do other people use? |
| 18:27 | Ardx | what does ! mean in clojure? Like if I had (set! ) does it denote that it will execute immediately (not lazy), or that it is a macro? |
| 18:27 | dxtr | side effects, if I'm not mistaken |
| 18:28 | dysfun | not safe inside dosync |
| 18:28 | Ardx | oh |
| 18:28 | dxtr | I was mistaken |
| 18:28 | dysfun | but that's only clojure core and some functions do not have the ! when they're not safe (it's presumed e.g. println is obvious) |
| 18:33 | Ardx | ugh emacs keeps puttign all my comment lines in the middle of the screen when I press return |
| 18:34 | technomancy | Ardx: use two semicolons for beginning-of-line comments |
| 18:36 | Ardx | oh yeah |
| 18:36 | Ardx | nice |
| 18:48 | justin_smith | dxtr: well, most things not safe in dosync are not safe because of a side effect |
| 18:48 | justin_smith | dxtr: dosync retries on conflict, and your side-effecting functions could be called N times |
| 18:48 | justin_smith | so, bigger picture, still mostly right :) |
| 18:49 | dxtr | Well, you've gotta *really* make sure your sides are affected |
| 18:50 | technomancy | I get the feeling "let's mark side-effects with a !" was something that seemed like a good idea early on but eventually was considered too much |
| 18:51 | dysfun | is that like "let's sprinkle io! in our code"? |
| 18:55 | justin_smith | at night, when I should sleep, I am haunted by the visions of all the code I should have wrapped in io! |
| 18:56 | dysfun | i believe you. millions wouldn't. |
| 18:56 | technomancy | early on a lot of the buzz around clojure was due to its STM |
| 18:57 | technomancy | which is quite remarkably good, but it's just not that frequently used |
| 18:57 | justin_smith | indeed |
| 18:58 | dysfun | well most of us build webapps which talk to a database. we just don't have much call for it |
| 19:07 | fifi-v | justin_smith: thanks |
| 19:26 | dysfun | so i'm reading an olde english book and all the 's' are 'f'. it's surprisingly demanding to parse |
| 19:27 | justin_smith | it's a separate ss that looks like an f but it has a tail on the lower left that an f doesn't have |
| 19:27 | justin_smith | iirc |
| 19:27 | TimMc | technomancy: Come for the STM, stay for the PDSs. |
| 19:27 | dysfun | justin_smith: nope |
| 19:27 | dysfun | https://archive.org/details/firstsixbooksofe00eucl |
| 19:28 | dysfun | flick to the introduction |
| 19:29 | dysfun | there is a less pronounced horizontal bar to the 's' than the 'f', but they're not double s because 'ssciences' in the first sentence |
| 19:29 | justin_smith | dysfun: https://en.wikipedia.org/wiki/Long_s |
| 19:30 | justin_smith | it is used for doubles, including if the second s is in the middle of the word |
| 19:30 | justin_smith | yes, super weird rule |
| 19:31 | justin_smith | wait, not doubles - just any lower case s not at the end of the word |
| 19:32 | technomancy | I remember on classic Mac they used to use that as shorthand for "folder" |
| 19:32 | justin_smith | technomancy: solder - it's a secret message |
| 19:32 | dysfun | what, a long s? |
| 19:33 | justin_smith | ſſſſſſſ |
| 19:34 | dysfun | https://ia800204.us.archive.org/BookReader/BookReaderImages.php?zip=/14/items/firstsixbooksofe00eucl/firstsixbooksofe00eucl_jp2.zip&file=firstsixbooksofe00eucl_jp2/firstsixbooksofe00eucl_0015.jp2&scale=2&rotate=0 # look at how beautiful this book is though |
| 19:34 | dysfun | despite the long ssssssss |
| 19:35 | justin_smith | yes, very nice |
| 19:36 | justin_smith | ſyſtem took me a moment |
| 19:36 | dysfun | fquare just looks so wrong |
| 19:36 | justin_smith | ſupercallifragiliſticexpealidocious |
| 19:36 | dysfun | "Befides the fuperior fimplicity" |
| 19:38 | dysfun | "lefs" is a tedious one |
| 19:38 | justin_smith | for fucks ſake |
| 19:39 | dysfun | but yeah, it surprised me how much effort it was to parse |
| 19:40 | dysfun | i suspect "correcting" that probably involves OCRing it and then spellchecking the OCR results because the OCR doesn't speak long S |
| 19:52 | Ardx | hah so cool you can do "lein new play-clj hello-world" and it downloads play-clj |
| 19:53 | dysfun | did your last language not have that? |
| 19:54 | Ardx | I'm used to c# and viual studio where there is a GUI on everything. I'm used to command line things never working quite right :> |
| 19:54 | dysfun | heh |
| 19:55 | justin_smith | Ardx: btw you can use clojure with CLR - it's even up to date and everything |
| 19:55 | dysfun | yeah, i was really surprised to see how well they've kept up to date |
| 19:56 | Ardx | Yeah I know, meaning to try out at some point |
| 19:56 | justin_smith | it doesn't have a clojure-centric tool like leiningen though |
| 19:57 | dysfun | yeah, i should add clr support to my lumo build tool when i get more time to hack on it |
| 19:58 | justin_smith | that would be awesome |
| 19:58 | dysfun | well the idea for me was that it shouldn't just build cljs |
| 19:58 | dysfun | because that would be lame |
| 19:58 | justin_smith | and putting the build tool in something that starts up fast (eg. lumo) is a great idea |
| 19:58 | dysfun | i want it to build all sorts of things so i can take my build tool wherever i go |
| 19:59 | justin_smith | dysfun: in this room, 10 years from now "hey I want to try clojure, does it have a lumo build plugin?" |
| 22:58 | iannnn | hiiiiiii |