#clojure log - Apr 23 2011

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:16 joshua__: So I wrote a function I found cool because I heard about it being used in a different language. After writing it I realized that the Haskell implementation of the function was a thousand times shorter and I'm starting to feel a little bit ashamed. How can I shorten this up? Or just make it better? https://gist.github.com/938272

0:17 *was a thousand times shorter is an exaggeration.

0:17 amalloy: joshua__: don't unroll the variadics. that's a grossness in clojure.core for speed

0:17 clojurebot: clojure is not scheme

0:18 joshua__: amalloy, oh. I guess I won't use Alt-. for Clojure advice in the future o.0

0:18 amalloy: joshua__: take advice from any of the namespaces except clojure.core

0:22 joshua__: amalloy, can you do something like (apply f more) when more is what was in [& more] when more is empty?

0:22 amalloy: joshua__: if f is willing to accept 0 arguments

0:23 &(apply + [])

0:23 sexpbot: ⟹ 0

0:23 joshua__: (+)

0:23 &(+)

0:23 sexpbot: ⟹ 0

0:23 joshua__: Alright. Sweet.

0:33 Alright. So I think this is better. What do you guys think? https://gist.github.com/938272

0:34 Actually hold on I just had a better idea.

0:34 amalloy: joshua__: you're aware that this has been written a few times already, right? this is just an intellectual exercise?

0:35 joshua__: amalloy, This is just an exercise yes.

0:35 amalloy, although I wasn't aware it had already been written.

0:35 amalloy: joshua__: there are plans to include it in clojure 1.3 as

0:35 well

0:36 joshua__: amalloy, Ah! So I was onto something cool after all!

0:36 amalloy: yes. a lot of people want this

0:38 carllerche: So, a slightly silly question... what's a good way to indent letfn? No matter how i try, it feels weird to me :P

0:40 dnolen: carllerche: gist of how you're indenting now?

0:41 joshua__: Alright. So I think this is the readable version I like: https://gist.github.com/938272

0:41 Sorta fun. I got to write the performant unrolled variadic version and the concise version of the same function. First time I've done that in clj.

0:42 carllerche: dnolen: https://gist.github.com/4164c496b1efad098fe9

0:43 amalloy: carllerche: that's about the only way you can do it

0:43 you could move [x] and [y] to the same line as first-fn if you want

0:44 dnolen: carllerche: I'd do it like this, https://gist.github.com/1d7c2f86b42a6b13aef0

0:44 Scheme letrec style is reference here.

0:45 as well as the style you'll find in Clojure source itself.

0:46 carllerche: hmm, ok

0:48 dnolen: this typestate thing in Rust is kinda interesting ...

0:51 joshua__: Alright. So am I misunderstanding something or is currying a special case of partial application?

0:53 Nevermind. I was misunderstanding.

0:57 So currying is when you have to use say.. ((((foo a) b) c) d) but partial application could be ((foo a) b c d). So currying wouldn't be a special case, because it doesn't have the consume one arg until all are consumed requirement.

1:52 amalloy: anyone happen to know what css to apply, to make a link never show as visited?

1:52 having a terrible time searching for it

2:41 mids: amalloy: would applying the same style of a:link to a:visited work for you?

2:42 amalloy: mids: yeah, i figured it out. i just thought there was a builtin class for it so i didn't want to build it myself

2:46 peteriserins: are there clojure naming conventions like the ones for CL at http://www.cliki.net/naming%20conventions?

3:17 amalloy: peteriserins: we mostly borrow from scheme

3:17 foo!, foo?, names-with-hyphens

3:17 foo*

3:52 thorwil: hmm, how do i regex match a linebreak, except if it sits between </p> and <p>?

3:57 mids: thorwil: look into negative look-ahead (?!regex)

3:57 thorwil: #"[^(</p>)]\r\n[^(<p>)]" works almost, except that it eats one chaaracter before and after replacement

3:59 ah, #"(?!</p>)\r\n(?!<p>)"

3:59 thanks, mids

3:59 mids: might also want to inject a \s* or two

4:02 thorwil: normally yes, but these sequences are generated by my code, so no extraneous whitespace

6:24 matthias__: ugh, how do i access a member variable of a class in clojure? :|

6:27 thorwil: matthias__: look if the class has something like .getValue?

6:29 matthias__: what i'm trying to access is not a method

6:30 hmm, it does have a getter for it

10:41 i want to add a reference to a java class to the state of a class that im deriving from another javaclass. havint trouble finding out how to do that :|

10:42 acutally im translating a java tutorial for the jmonkeyengine into clojure and they use a protected field which is declared and then initialized in some method and updated in an update method

10:42 dont know how to do it in clojure

10:42 http://jmonkeyengine.org/wiki/doku.php/jme3:beginner:hello_main_event_loop there's the code

10:57 kzar: I'm setting up a project using appengine-magic and moustache, does anyone know how to serve static files and where to put them? Looking at tryclojure's source you can make a resources/public directory and put everything in there, but I'm missing a special route or something because the files aren't served. (Also ideally I would want "/css/example.css" instead of "/resources/public/example.css".)

10:59 mids: kzar: which version of appengine-magic?

10:59 kzar: mids: I'm using the latest one I think, 0.4.1

11:00 mids: iirc 0.3 was resources/, 0.4 is war/

11:01 kzar: mids: To be fair I've tried both, I originally had a problem loading templates with enlive until I put them in resources, (war didn't work).

11:01 mids: Do you need to add a route or should it work automatically?

11:01 mids: well, templates isnt static stuff

11:02 kzar: mids: Yea that's true

11:02 mids: for example I have my css under war/css/mysite.css

11:02 thorwil: kzar: templates under resources, static files under war

11:03 kzar: routing is explicit

11:03 kzar: Ah it's working

11:03 thorwil: though it might be easy enough to construct your own filename/path based routing

11:03 kzar: Sorry I don't know what I messed up first time when I tried putting them in the war directory

11:06 thorwil: the list of things that didn't work the first time i tried them, only to just work later after unknowingly removing some issue, is long :)

11:08 i wonder what would it take to build an interface allowing the javascript that i serve to call clojure functions on the server, without opening an attack vector

11:09 kzar: thorwil: Doesn't tryclojure do that?

11:09 mids: directly? or through some json / rest interface

11:11 thorwil: mids: the idea would be to minimize the amount of code on both sides, so whatever works in that light

11:13 kzar: hmm, security shouldn't come from limiting what can be called, but rather from differentiating between JS that was served, ws JS that has been shoved in by an attacker

11:38 pdk: is anyone here familiar with writing bots that take an event for when an email inbox receives a message then doing something with the message

11:39 basically i'm trying to jury rig something like hootsuite since hootsuite doesn't work for wp sites that are self hosted

11:39 rather between wp and constant contact for someone i'm helping to make a site for

11:40 matthias__: so, there's a bunch of ways to keep a reference to a mutable object. i dont know what to use. i need an instance of a java class that i can change and have it sotred inside another java class which is define with gen-class. it derives from a another java class. how do i do that?

11:50 markoman: is there a way to make keyword :author to function call without if else, switch case or condp structures? call would be similar from: (:author "Shakespeare, William") to: (Author. "Shakespeare, William")

11:52 hyperboreean: how can I expand in clojure ~/myfolder to /home/myuser/myfolder?

11:52 markoman: it could as well be a string transformed to function call (#"Author." "Shakes...") or something like that

11:59 hyperboreean: have you looked at "file system utilities for Clojure" ?

12:00 hyperboreean: markoman: googling for clojure (file|paths) gives me only links to people showing how to install clojure and nothing related to clojure libs

12:01 I'll try your suggestion, thanks

12:01 tufflax: matthias__: I don't know if this is what you meant but: atoms, refs and agents should *not* refer to mutable things. The only things that is mutablu is the references themselves. If you want mutable in the java sense then maybe you can do it with gen-class but i don't know... was that what you were asking? :p

12:02 matthias__: yes

12:02 i need a mutable object in my class

12:04 tufflax: is the object something that could be implemented as a clojure data structure?

12:06 matthias__: its already implemented as a java class in jmonkeyengine

12:06 trying to work with it using clojure

12:08 hyperboreean: markoman: ok, I found exactly what I needed: fs; sorry to bug you, but is there any way I can specify to lein from where it can get the dependencies? as far as I can see from the docs, that's not possible

12:09 matthias__: :repositories?

12:09 tufflax: well you don't need anything special to refer to mutable objects, just refer to them! the ref types in clojure is just a way to achieve mutability when the "things" themselves are not

12:10 matthias__: well, im trying to add it to the class as a member

12:10 hmm, or maybe i can just make it global

12:11 tufflax: i havent used gen-class much, so i don't see your problem, sorry

12:11 markoman: hyperboreaan: yes, fs seems to provide basic file system functionality. lein: so far i have just used inc and require within project src and jars. try what matthias told

12:12 hyperboreean: will do, thanks guys!

12:12 markoman: np :)

12:14 Chousuke: deftype supports mutability

12:15 markoman: to my own question. i found this ##(#=(symbol "println") "hello") is it going to give problems? I mean my functions are derived from java classes Author.

12:21 well it gave problems already. my initial was to use keywords for function names so assumed this would work:

12:21 .(#=(symbol (name :println)) "hello")

12:21 ,(#=(symbol (name :println)) "hello")

12:21 clojurebot: EvalReader not allowed when *read-eval* is false.

12:23 hyperboreean: doh, fs is in clojars, no need to get it from bitbucket ... noob!

12:27 matthias__: so if i want to declare a reference (the java kind of reference) and then later assign it so some object, how do i do that? i mean wahts the clojure equivalent of = ?

12:27 TimMc: markoman: ##((resolve 'println) "hello")

12:27 sexpbot: java.lang.SecurityException: You tripped the alarm! resolve is bad!

12:28 TimMc: matthias__: What do you mean "the java kind of reference"?

12:29 matthias__: well if i say Integer bla = null; in java, then bla is a "reference"

12:30 TimMc: You don't get those in Clojure.

12:30 Clojure has reference types, though.

12:31 matthias__: if i say (let [bla (new Integer 320409)]), what's bla?

12:31 TimMc: bla is the name that binds an instance of Integer

12:31 That instance is a *value*, not a reference.

12:32 matthias__: well, what i really want is to have a way to make some kinda reference to an object, but i want to actually make the object later

12:33 TimMc: matthias__: There are refs, vars, agents, atoms...

12:33 I would bet however that you don't even need one of those.

12:34 (I don't know what you are trying to accomplish in general, though.)

12:34 http://www.clojure.org/refs

12:35 matthias__: trying to translate this http://jmonkeyengine.org/wiki/doku.php/jme3:beginner:hello_main_event_loop to clojure

12:35 the player is what i dont know how to do

12:36 (it doesnt matter if it's actually a member of the class or not, since the class is only instantiated once)

12:39 TimMc: matthias__: For something like that, I would tend to have a ref holding the game state (which would be a map or record or other associative type), and have an updater function that takes old state -> new state.

12:41 matthias__: hmm, but then i'd have to remove the player every frame and make a new one. afaik, clojure does some things to make that functional style more efficient, but what if its just a java object? i'd have to do the same with everything in my game. i wanna kind of decouple all that functional stuff and only pass the values into jmonkeyengine at the end of every frame

14:02 im trying to use (declare player) and then later bind an object to it with (binding [player (new Geometry "blue cube", b)]). but it doesnt seem to work

14:04 pdk: (doc binding)

14:04 clojurebot: "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."

14:06 matthias__: yes i read that

14:07 is it supposed to make it obvious why what im tryign doesnt work? :p

14:07 TimMc: matthias__: I think you want def, not declare, if you're going to use binding.

14:10 matthias__: oh, binding only changes the vars for its own body

14:11 i dont understand the difference between (def x) and (declare x)

14:11 (doc def)

14:11 clojurebot: DENIED

14:11 matthias__: awww

14:11 (doc declare)

14:11 clojurebot: "([& names]); defs the supplied var names with no bindings, useful for making forward declarations."

14:13 matthias__: trying set! instead of binding now, but it doesnt work. says cant change root binding

14:15 cods: Hi. I can't find how to access an enum value declared within a class. I want to get "launchPermission" from this class: http://code.google.com/p/typica/source/browse/trunk/java/com/xerox/amazonws/ec2/ImageAttribute.java

14:15 once I import ImageAttribute, what is the syntax to get the enum value?

14:16 I tried various thing like ImageAttribute/ImageAttributeType/launchPermission, but it's wrong.

14:21 Any idea? I'm sure it's an obvious mistake, but even reading http://clojure.org/java_interop is not enough to figure what is wrong. (I know Java only a bit)

14:21 matthias__: (doc atom)

14:21 clojurebot: "([x] [x & options]); Creates and returns an Atom with an initial value of x and zero or more options (in any order): :meta metadata-map :validator validate-fn If metadata-map is supplied, it will be come the metadata on the atom. validate-fn must be nil or a side-effect-free fn of one argument, which will be passed the intended new state on any state change. If the new state is unacceptable, the validate-fn should return

14:25 matthias__: can i declare an "empty" atom and then put in a java object later with swap!?

14:26 TimMc: cods: The enum is an inner type.

14:26 cods: Import ImageAttribute$ImageAttributeType, then use ImageAttribute$ImageAttributeType/launchPermission

14:27 matthias__: You can make an atom containing nil.

14:28 cods: TimMc: ah ok. Thanks a lot!

14:28 TimMc: Tricky little bastard, innit?

14:28 Also, horribly verbose.

14:28 matthias__: "java.lang.ClassCastException: com.jme3.scene.Geometry cannot be cast to clojure.lang.IFn

14:28 "

14:29 (def player (atom nil)) ... later: (swap! player (new Geometry "blue cube", b))

14:29 TimMc: cods: On my personal wishlist is a renaming clause for import.

14:29 matthias__: that's what i tried

14:29 TimMc: matthias__: swap! takes a function from old state -> new state

14:29 matthias__: (doc swap!)

14:29 clojurebot: "([atom f] [atom f x] [atom f x y] [atom f x y & args]); Atomically swaps the value of atom to be: (apply f current-value-of-atom args). Note that f may be called multiple times, and thus should be free of side effects. Returns the value that was swapped in."

14:30 TimMc: matthias__: (constantly foo)

14:30 matthias__: (doc constantly)

14:30 clojurebot: "([x]); Returns a function that takes any number of arguments and returns x."

14:32 matthias__: ookay... now it seems to work, thanks. i'm more like "oO" than "aha" though ;)

14:34 devn: name that tune: the song that plays at the beginning and end of the sicp lectures

15:08 arohner: I have a vector, and I'd like to stick an element in it conditionally. I remember there's a trick using splicing, but I can't remember it

15:08 i.e. [1 2 (if (foo? x) x)]

15:08 but there was a way to use ~@ to make the list have two elements rather than 3 when the if is false

15:08 anyone know what I'm talking about?

15:09 oh

15:09 &&`[1 2 ~@(when true 3)]

15:09 sexpbot: java.lang.Exception: Unable to resolve symbol: & in this context

15:09 arohner: &`[1 2 ~@(when true 3)]

15:09 sexpbot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

15:10 danlarkin: that's probably the wrong path to take

15:11 are you working with a literal vector like that? or conjing up stuff

15:14 arohner: danlarkin: I'm working with a literal vector of hiccup html

15:15 danlarkin: ok, so depending on (foo? x) you want a literal vector of 1 & 2 and maybe x

15:15 arohner: right

15:16 danlarkin: so of course there's (if (foo? x) [1 2 x] [1 2])

15:16 is the vector so monstrous that that's ugly?

15:16 arohner: danlarkin: yeah

15:16 I want to do this with multiple values in the vector

15:17 there's always (filter identity [ 1 2 (when (foo? x) x)]), but I'm curious if there's anything better

15:17 danlarkin: perhaps this then: (let [v [1 2]] (if (foo? x) (conj v x) x))

15:18 I always prefer (remove nil? ..) to (filter identity ..)

15:18 but that's just preference

15:53 tufflax: #jasmin

15:54 sorry

16:00 amalloy: &`[1 2 ~@(when true [3])]?

16:00 sexpbot: ⟹ [1 2 3]

16:00 amalloy: arohner: ^

16:00 danlarkin: gross

16:01 amalloy: danlarkin: i don't think so

16:01 kzar: Probably a dumb question but where am I going wrong here? ,(sun.misc.BASE64Decoder. "ZXhhbXBsZQ==")

16:01 (balls I thought , would get the bot to eval it.)

16:01 amalloy: kzar: , and & only work at the start of a message

16:01 you can use ## mid-message

16:02 eg to see what sexpbot thinks of ##(sun.misc.BASE64Decoder. "ZXhhbXBsZQ==")

16:02 sexpbot: java.security.AccessControlException: access denied (java.lang.RuntimePermission accessClassInPackage.sun.misc)

16:02 kzar: amalloy: ah gotya, I'm sure you've told me that before I just got deja vu.. either that or there's a glitch in the matrix

16:02 amalloy: good. i was going to say, what you're doing wrong is using sun.misc :P

16:02 $google apache commons binary encoder decoder

16:02 sexpbot: First out of 8360 results is: Base64 (Commons Codec 1.5 API) - Apache Commons - Apache Commons

16:02 http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html

16:03 danlarkin: syntax-quoting there is all well and good when you're using numbers

16:03 but when you want to evaluate other things in the vector then you have to balance the unquotes and blah

16:03 ugly town

16:04 amalloy: danlarkin: yes. if arohner wants to refer to the same gensym in the normal part of the vector and the "maybe" part, he'll be sad

16:05 danlarkin: not quoting it seems cleaner to me

16:06 amalloy: danlarkin: ##(into `[1 2] (when true `[4]))?

16:06 sexpbot: ⟹ [1 2 4]

16:06 kzar: ,(apply str (map char (seq (org.apache.commons.codec.binary.Base64/decodeBase64 "ZXhhbXBsZQ=="))))

16:06 clojurebot: "example"

16:07 kzar: :) thanks guys

16:07 amalloy: whoa

16:07 i'm surprised clojurebot has apache commons on his classpath

16:08 danlarkin: amalloy: that's nice

16:08 but you don't need all that quoting

16:08 amalloy: danlarkin: not for numbers, obviously

16:08 but i get the impression that arohner will :P

16:08 danlarkin: oh, yeah, I don't know what hiccup html means

16:08 if it has to be quoted I guess yeah

16:09 arohner: danlarkin: http://github.com/weavejester/hiccup

16:10 amalloy: i haven't needed to quote any hiccup yet, but we'll see

16:10 kzar: What's wrong with having this in my namespace? (:use [org.apache.commons.codec.binary.Base64 :only [decodeBase64]])

16:10 amalloy: at least two things are wrong there

16:10 (1) apache stuff is java classes, not clojure namespaces. it wants an import

16:10 (2) you can't import just a method - you need to import a whole class

16:11 (3) you need to add a dependency on commons-codec in your project.clj to actually get that library from the net

16:13 Bronsa: why in clojure-1.3-alpha6 1 is a java.lang.Long and not a java.lang.Integer?

16:16 arohner: Bronsa: it has to do with primitive support in clojure fns

16:16 Bronsa: i.e. unboxed math. 1.3 can create fns that take unboxed Longs and Doubles

16:17 kzar: amalloy: whoop, got it working tah

16:18 arohner: the clojure fns have to implement an interface, clojure.lang.IFn, and rhickey didn't want the interface definition to explode with every permutation of taking a short, an int, a long, a float, etc

16:18 so if you want primitive fns, the fn can take longs or doubles, and all literal numbers are one of those two

16:18 Bronsa: ok

16:18 thanks

16:18 arohner: if you really need an int, you can still do (Integer. 5)

16:19 amalloy: arohner: ##(class (int 5))

16:19 sexpbot: ⟹ java.lang.Integer

16:19 arohner: oh, cool. That didn't work in an earlier alpha, so I got out of the habit

16:19 ##(class 5)

16:19 sexpbot: ⟹ java.lang.Integer

16:20 arohner: amalloy: sexbot doesn't appear to be running 1.3

16:20 amalloy: arohner: no

16:20 but i thought that (int foo) would cast fine?

16:20 Bronsa: well

16:20 amalloy: &(int (long 5))

16:20 sexpbot: ⟹ 5

16:20 Bronsa: user=> (class (int 4))

16:20 java.lang.Long

16:20 in clojure 1.3.0-alpha6

16:21 amalloy: hah, okay. well, silly me

16:24 kzar: $google apache commons hmac

16:24 sexpbot: First out of 872 results is: webhooks - javax.crypto.SecretKey implementation for encoding ...

16:24 http://code.google.com/p/webhooks/

18:27 kzar: If I've done [clojure.string :as str] how come I still see warnngs about replace and reverse already existing in the namespace? (I thought the ":as str" bit would fix that.)

18:28 Sorry I meant to type (:use [clojure.string :as str]) there

18:28 amalloy_: kzar: you want require, not use

18:30 kzar: amalloy: Ah right, that fixed it. How come?

18:30 amalloy: use imports the unqualified symbol into your namespace, period. it doesn't pay attention to an :as clause

18:31 kzar: ah gotya thanks

18:55 TimMc: amalloy: The silent failure on :as has caused me much consternation in the past.

19:25 devn: damnit kzar, come back! i have a link for you!

19:25 http://blog.8thlight.com/articles/2010/12/6/clojure-libs-and-namespaces-require-use-import-and-ns

20:49 chrissbx: Is there some overview over the clojure language? I'm repeatedly finding myself not finding what I need in the reference.

20:49 Like, how are exceptions to be raised?

20:49 Raynes: chrissbx: http://java.ociweb.com/mark/clojure/article.html Is precisely what you describe, methinks. It's good, if a little outdated.

20:50 dnolen: chrissbx: like how to throw one?

20:53 chrissbx: yes; I'm going to read that article

20:55 dnolen: chrissbx: http://clojuredocs.org/clojure_core/clojure.core/throw

20:57 rien: does closure have a hands-free .dmg install file for the mac?

20:57 I'm following the step by steps, setting up classpath variables, and nothing works

20:58 amalloy: $google leiningen clojure

20:58 sexpbot: First out of 2290 results is: Building Clojure Projects with Leiningen « I am Zef

20:58 http://zef.me/2470/building-clojure-projects-with-leiningen

20:59 znutar_: is load-string equivalent to (conj eval read-string) ?

20:59 amalloy: rien: get the lein script, run it, and it installs everything

20:59 znutar_: er, (comp eval read-string)

20:59 rien: amalloy: trying it right now, thanks

21:00 lol it's made by technomancy!

21:00 that's good, I trust his stuff

21:02 chrissbx: Thanks dnolen & Raynes

21:49 seancorfield: rien: if you get stuck with lein, just holler... i use it all the time for my projects on a mac!

22:59 technomancy: rien: heh; thanks. have I run into you before somewhere else on this wide inter net?

23:11 there's got to be a better way to say this: (into {} (for [[clause-type & parts] clauses] [clause-type parts]))

23:11 but it eludes me

23:12 amalloy: (into {} (map (juxt first rest) clauses))?

23:12 technomancy: amalloy: but of course!

23:12 thanks =)

23:12 amalloy: welcome

23:13 technomancy: hah; I had (merge {:a foo :b bar} (into {} [...]))

23:13 I don't know why I keep forgetting into can have a non-empty first arg.

23:25 seancorfield__: amalloy: you sure like juxt :)

23:26 amalloy: seancorfield__: you saw how well it solved that problem. it's the best for everything!

23:30 seancorfield__: it is a pretty slick solution in that case

23:36 i probably need to review my code and see if could help simplify anything.:)

23:36 amalloy: seancorfield__: i overused juxt recently

23:37 seancorfield__: did you hurt yourself? :D

23:37 amalloy: http://twitter.com/#!/alanmalloy/status/61897979136708608 (spoiler for 4clojure #53, so don't look if that bothers you)

23:38 i needed to turn [[0 1] [1 2] [2 3]] into [0 1 2 3], so i used (juxt ffirst (partial map second))

23:57 technomancy: there's no pprint-for-code, is there?

23:58 seancorfield: ,(distinct (apply concat [[0 1] [1 2] [2 3]]))

23:58 clojurebot: (0 1 2 3)

23:58 KirinDave: technomancy: Got a sec?

23:58 seancorfield: ah, not a vector :)

23:58 i have not actually looked at 4clojure yet so i don't even know what you're trying to solve

23:58 amalloy: seancorfield__: i actually was thinking i needed to account for non-distinct elements of the list, but i don't

23:59 technomancy: KirinDave: sure

23:59 KirinDave: technomancy: I'm writing a bunch of assignments for a jc programming class.

23:59 technomancy: I just finished the first assignment, was wondering if someone could check it out and tell me if it's a turrible plan

23:59 technomancy: https://gist.github.com/raw/ac64ad91fb52e0964a1b/954aa172f8ee08cb56e29816ee14508c89699b5f/project0.txt

Logging service provided by n01se.net