#clojure logs

2009-01-01

00:29Puzzler_clojure
00:38Chouserindeed
00:43hiredmanclojurebot: clojure?
00:43clojurebotclojure is a very attractive hammer with a nice heft to it
01:26inertia-what is the equivalent for clojure agents, in scheme?
02:26durka(set! *year* (inc 2008))
02:51durkacan clojure iterate over Enumerations?
04:13Lau_of_DKTop of the morning gents, and a happy new year
04:13craigmarshall9happy new year from England
04:16Lau_of_DKthanks :)
04:20hoeckhappy new year from germany
04:20craigmarshall9Guten tag! (that's all I speak)
04:21Lau_of_DKI know a little: Achtung! hoeck ist mein liebling
04:21Lau_of_DKauf berlin...
04:21hoeckhaha :)
04:22craigmarshall9"Attention, hoeck is my darling in Berlin" ?!
04:23Lau_of_DKClose, from berlin
04:24Lau_of_DKI really love it when Germens say "Achtung!", Ive experienced it in a swimming pool once on holiday, where a German woman wanted to claim some lanes and she swam around say "Achtung!" :)
04:33Puzzlerhappy new year
04:38Lau_of_DKyou too
07:35Lau_of_DK(defn x [] (.trim "bla bla ")) (defmacro y [] (.trim "bla bla ")), y will fail is .trim is not in the namespace from where I am calling, where x will succeed if its defined in a namespace that has .trim. Have can I have my macro remember where its coming from ?
08:50Chouser.trim is a Java method, so it's not "in" any namespace.
08:51Lau_of_DK.trim was just an example, it could have been anything
08:51Lau_of_DKIn the current example, its methods from java.sql
08:51Lau_of_DKMr. Chouser
08:51Lau_of_DK(happy newyears)
08:51Chouser:-) Happy new year to you.
08:52Lau_of_DKLooking forward to your 30 lines or less fireworks simulation on your blog
08:52Lau_of_DK:)
08:53ChouserMethod names are resolved very differently from other names, which is why it matters.
09:07Lau_of_DKChouser: You gotta fill me in tonight
10:25knapris it possible to add Hindley-Milner type inference to Clojure?
10:34RSchulzknapr: Deep thought for the early hours of a new year! Anyway, I don't think so, since Clojure currently has no static type system within which a type inference could operate.
10:36ChouserRSchulz: is that true? The Clojure compiler knows the Java class types of much the code it works with.
10:36Chouser...and uses that info to produce non-reflective bytecode.
10:36RSchulzI knows only whether methods and fields named in Clojure code exist, right?
10:37RSchulzIt still has to use reflection at run-time to pick an overloaded method, e.g.
10:37knaprbut it could still parse a text-file and check the validity of the operations inside clojure right?
10:37knaprpartial hindley-milner or something
10:37RSchulzRich was talking a few days ago about possibly integrating another piece of software (whose name escapes me) that does type inference as a kind of orthogonal / adjuct type checker for Clojure programs.
10:38knaprwhere all java-methods are annotated as evil stuff
10:38RSchulzWhat sort of validity could it check? Or, more to the point, what sort of invalidity could it detect?
10:38ChouserI think he mentioned sequent notation, Qi-style.
10:38RSchulzYes. That was it.
10:41Lau_of_DKQi-style, sounds awful
10:41Lau_of_DKMr. Schulz, happy new years :)
10:42kotarakoptional type checking would be nice.
10:43RSchulzLau! Happy New Year to you and yours!
10:44RSchulzWhen you say "Qi=style sounds awful" do you mean you don't like the Qi concept, or that the words themselves are dysphonic to your ear?
10:44kotarakI think he left
10:46RSchulz"People come and go so quickly here!"
11:52ChouserI wonder if it'd be worth the effort to disallow non-keywords in the ns macro.
11:53kotarakyou mean (ns :foo.bar (:use :clojure.conrib.def))?
11:55RSchulzWhy?
12:20Chouserno, I mean disallow (ns foo.bar (import ...) (require ...))
12:21RSchulzI still don't see why you'd want to do that?
12:21Chouserbecause it works (sorta) but isn't supported. It's an easy mistake to make and it mostly works ok.
13:17kotarak(doc read-string)
13:17clojurebotReads one object from the string s; arglists ([s])
13:44Lau_of_DKGood evenings gents
14:28durkanow why would there by recursive symlinks in my classpath
14:36RSchulzdurka: Are you referring to /etc/alternatives?
14:36RSchulzOr actual cycles?
14:38durkacycles
14:39RSchulzDid you set them up yourself? Or did some installer or some other software create them?
14:39RSchulzI take it you're using Linux?
14:39RSchulzI'm pretty sure the Linux kernel will detect cycles and given an error when attempting to resolve them.
14:40lisppaste8durka pasted "classpath" at http://paste.lisp.org/display/72911
14:40durkai'm not sure who set those up
14:40durkabecause i'm not sure where i installed java from
14:41durkabut i would think making a symlink to the parent directory is a general bad idea
14:41durkaesp. when you expect something like a classloader to be walking this directory
14:42RSchulzI take it the symlinks are to directories, not indiviudal files, yes?
14:43RSchulzAnyway, just clean them up. I doubt anything will break if you get rid of cyclic symlinks.
14:43durkai hope not
14:45RSchulzActually, I guess that's kind of nonsensical. The cyclic links are not to anything real, just other links...
14:45durkawell, it's not a cyclic link per se
14:45durkait's a link to a directory
14:46durkain that directory are a few directories, one of which includes the link
14:46RSchulzOh. Well, there's nothing wrong with that. It's very common, actually.
14:46durka:( but it confuses my simple-minded recursive directory walker
14:46RSchulzWhy not use the "find" command?
14:48pdI've a struct 'board' that represents a sudoku grid, and I've written a board-to-str function to build a string representation
14:48pdBut I'd prefer being able to simply do (str some-board); is this feasible somehow?
14:49durkaRSchulz: you mean the unix find?
14:49durkaor is there a java/clj native one
14:49RSchulzYes.
14:49RSchulzIt's very fancy and completely symlink-aware, as are most Linux commands.
14:49durkai'd rather this program be portable to windows, though
14:50RSchulzI guess I don't understand what you're trying to do. Can't java.io.File distinguish symbolic links?
14:52RSchulzI guess not.
14:52RSchulzBut I think the getCanonical... methods will resolve symbolic links, if that helps.
14:53durkabasically i'm trying to walk the classpath looking for things
14:53RSchulzJust run them through java.io.File#getCanonicalPath first.
14:53durkabut that symlink is putting the code into an infinite recursion
14:53durkaso don't follow symlinks?
14:54RSchulzNo, so you don't _see_ the symlinks.
14:54RSchulzYou might need to also verify isReadable() first to filterout dangling symlinks.
14:55durkaoh, i see
14:55RSchulzIf the link structures are cyclic, the kernel will tell you that. Otherwise, sliding through the symlinks should work.
14:57durkaright, ok
14:58RSchulzAlso, I think Stuart's Programming In Clojure book has some sample file system traversal code you might want to look at as an example.
15:00durkai should buy that book
15:01RSchulzI'd certainly recommend it.
15:01RSchulzYou can choose the PDF-only, if you rpefer, though I like books I can hold.
15:02RSchulzBut if you get both or just the PDF, you can get the current betas as he writes new chapters.
15:02RSchulzOtherwise, naturally, you have to wait for the final press edition to see anything at all.
15:04durkaright
15:16soothStupid question: How do I add the jars in /usr/share/java to the classpath in slime? I've tried add the directory to swank-clojure-extra-classpaths but it doesn't seem to work. Do I need to add the jars individually/
15:16sooth?
15:21pdsooth: yes, I think so. Adding a directory to the java classpath doesn't mean it searches for jars within the directory (AFAIK).
15:22Chousukethere is some support for wildcards though.
15:22soothpd: java man page says it can be a directory, I must be doing something wrong.
15:23pdsooth: given a directory, it searches for .class files within it
15:23sooth(sun java 6)
15:23Chousukesooth: that means the *directory* not the .jar, is added to the classpath.
15:23soothpd: Ah, okay. Thanks
15:23soothChousuke: Thanks, I will use wildcards.
15:24ChousukeI can't remember if it was * or something else, though.
15:24soothChousuke: It's *
15:24soothwhich adds all the .jar or .JAR, according to the man page
15:29dreish,(#())
15:30clojurebotclojure.lang.PersistentList$EmptyList@85b670
15:30cmiles74Is there a function that will return true if a var has been set?
15:31Chousercmiles74: defined, bound, or non-nil?
15:31Chouser:-)
15:32ChouserI mean, you want to know if (def foo) has happened or not?
15:32Chouseror you know it has but you want to know if it has been re-def'ed to have a value?
15:32cmiles74I think I am testing to see if a var has been bound...
15:33cmiles74I'm imagining that someone might already have a logger instance (like a Log4J instance) in a var called *logger*...
15:33cmiles74If they don't, then I want to create a logger.
15:34cmiles74The nomenclature around this is always a problem for me. I think what I am askings is, "Is there a var called *logger* with a non-nil value?"
15:37Chousercmiles74: there's a defonce that either does what you want or provides example code that might be useful.
15:37cmiles74Okay, thank you Chouser. :) I will look at that right now.
15:38rhickeyClojure mailing list activity: http://chart.apis.google.com/chart?chs=500x200&cht=bvs&chtt=Clojure%20Mailing%20List%20Activity&chd=s:DBHGIROJQOSOjv9&chxl=0:|oct|nov|dec|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec|&chxt=x
15:39drewrYep, that pretty much tracks with my ability to keep up with it.
15:39rhickeyfrom: http://hughw.blogspot.com/2009/01/clojure-uptick.html
15:39Chouserdrewr: heh, no kidding.
15:40rhickeydrewr: you have an ever increasing ability to keep up with it?
15:40rhickey:)
15:40Lau_of_DKSeriously, you guys can keep up?
15:41drewrOK, "inversely tracks." :-)
15:53rhickeysvn 1193 - Added uniform metadata handling for atoms/refs/agents/vars/namespaces
15:55Chouserwow, giant diff.
15:55rhickeyrefactoring
15:56rhickeyso now all references and namespaces can have metadata
15:57rhickeynext up is uniform watches for references
15:57rhickeywill need to move from synchronous model to watch is agent+action
15:58rhickeychange will trigger (send-off agt action reference)
15:58Chouserah, I see atom moved to .java
15:59rhickeyyeah, I think I might want to be able to use it earlier in the bootstrap, difficult when a proxy
15:59Chouserexcellent news re: watches
16:00RSchulzWhat's the state of the abstract stream processing you worked on a while back. I see the classes in the diagram, but is there new API to go with it?
16:01rhickeyRSchulz: it's substantially done, but I'm quite reluctant to deploy it. There is so much potential for misuse, I don't want to compromise Clojure. So, still working on LFE alternatives
16:01RSchulzI know you already answered this one, but... LFE?
16:02Chouserleft fold enumerator
16:02RSchulzRight. Thanks. Again.
16:02rhickeyRSchulz: http://clojure-log.n01se.net/date/2008-11-06.html#20:41
16:03Chouserwhee
16:03rhickeywhat's nice is that the metadata updating is MT safe
16:05Chouserthe alter* and upate* functions are becoming quite natural to me to use.
16:06rhickeyIt's definitely a model, but not one you see often
16:06Chouseroh, I guess it's just update-in. Should that not be named alter-in?
16:06rhickeyI like it, plus something about it being relatively universal feels right
16:06Lau_of_DKWhat was the misuse concerns regarding ASP ?
16:07rhickeyChouser: all alters are destructive, update isn't
16:07ChouserLau_of_DK: ASP? LFE?
16:07Chouserrhickey: ah!
16:07Lau_of_DKChouser: The abstract stream processing which was almost done, but not yet deployed
16:07ChouserLau_of_DK: oh, ok.
16:08rhickeyLau_of_DK: streams are inherently stateful. It would take extraordinary discipline to avoid having them pollute a design
16:09Lau_of_DKoh I see
16:09rhickeyMost of Clojure removes the need for extraordinary discipline
16:09rhickeyAt least that's the goal
16:09Lau_of_DKDiscipline is good, just not very common :)
16:10Lau_of_DKBut yea, its nice when everything defaults to immutability
16:10Lau_of_DK(1 year ago I would have slapped somebody for saying what I just said)
16:11Chouser1 year ago I wouldn't have understood what you meant.
16:16ChouserI can't create an object with a custom toString without gen-interface or gen-class, can I?
16:20rhickey(str (proxy [Object] [] (toString [] "foo")))
16:23Chouseroh! I guess I should have specified map rather than object, which wouldn't survive any assoc or dissoc. ...but in this case I don't need to support either.
16:23Chouser...so it's perfect, thanks!
16:25rhickeysure
16:26Lau_of_DKGuys, is it possible/sensible, to build an object-model around concept of immutability, so as to include some type of OOP in Clojure?
16:28kotarakIn how far is this necessary? We have Java underneath...
16:28Lau_of_DKMaybe it's just my old habits popping up, but occasionally Im sitting with a design where it would just seem obvious to define a few objects.
16:29ChouserLau_of_DK: in a context where maps + fns (+ perhaps multimethods) is insufficient?
16:30Lau_of_DKNot insufficient, just not optimal. Do me the current usage of multimetods can seem a bit messy
16:30Chouserit seems to me a good way to support string (or at least print) overloading in clojure proper would be for print-method to check for metadata like :custom-print, and call that if present.
16:31kotarakI'm still struggling on what to dispatch.
16:31kotarakSo I end up with a :type tag in the map.
16:31kotarakIs there some better way?
16:31Chouserthat'd allow you to make struct-maps that by default print in some special way.
16:32Chouserkotarak: I'm no expert, but I think if they :type has a natural value for all the types you're working with, you're probably doing it right.
16:33rhickeythere's nothing wrong with a type tag. What's nice is that when you need another characterization, you're not limited to a hardwired single-type-per-object system
16:33Chouserkotarak: as a (weak) counter-example, consider vehicles. What is the vehicle's :type? is it car/truck/suv? or is it GM/Ford/Toyota?
16:35rhickeywatch/watcher/observer/listener/other?
16:35Chouserkotarak: so in that case, you'd have :make, :model, maybe :configuration (or some actually good name for car/truck/suv), :drive-wheels (2, 4, etc.) ...and for a given multimethod dispatch on the relevent one(s)
16:36rhickeyfor agent registered to be informed of a reference change
16:36kotarakChouser: the :type is Vehicle. Is has a manufacturer (GM/Ford/Toyota). And has a list of other properties, like car, truck, seven-seater... In my opinion (at the moment, that may change by the hour), that sticky notes put on a thing is a better way to categorise stuff than a tree.
16:37Chouserrhickey: only one such agent per reference?
16:38kotarakChouser: yes. that's the nice thing about multimethods: dispatch on whatever you need.
16:38rhickeyno, either a map of agent->action or set of [agent action]
16:38kotarakMaybe I just have a bad feeling, without reason. Just have to get used to it.
16:38rhickeyprobably the former
16:39Chouserkotarak: that's fine too, but in classic OOP, I'd expect Vehicle to be a class, and perhaps Truck to inherit from it. ..but if you have functionality attached to manufacturer, things get complicated quickly.
16:39rhickeyso no agent can be registered more than once
16:40Chouserrhickey: no more than once on the same reference. nice. though perhaps on more than one reference, perhaps with different actions.
16:40rhickeyChouser: oh yes, definitely one agent can watch many refs
16:41ChouserI think I like "watcher". The brevity of "watch" is nice, but it seems a bit innaccurate.
16:42Chouser"listener" is even longer with no obvious benefit, plus is already used in Java-land.
16:42rhickeyright, Java use invites confusion
16:46Chouserreactor? feeler?
16:50Chouserresponder?
16:51arbscht_potential request/response confusion
16:52Chouseryeah, responder has an innappropriate suggestion of the response going back to the thing that triggered it.
16:52Chouseroh, "trigger"
16:55rhickeytrigger is usually the cause, maybe reactor
16:56Chouseryeah, you might say the thing "is triggered" to be to say it "is a trigger" isn't quite right. Though RDBs seem to use it that way.
16:57rhickeyreagent has a chemistry connotation that doesn't quite fit
16:57arbscht_sensor?
16:58rhickeyreaction is kind of correct, as it is more than just an agent but agent+action
17:00Chousersensor's not bad at all.
17:01rhickeysensor makes me thing of something that detects change - here the change is detected by the reference itself, this is just an interested party
17:02Chouserreaction suggests to me one particular triggering of the thing.
17:03Chouserafter the agent has completed the action, that reaction is done. That agent and action might react again later.
17:04RSchulz"Custodian" (Latin for watcher, yes?)
17:04kotarakbeholder?
17:04RSchulzOr maybe "voyeur"...
17:05arbscht_another overused term: monitor
17:05kotarakhook?, but "hooker" .....
17:06drewrliaison
17:07Chouserfollower
17:07kotarakobserver
17:07Chouseralarm
17:07arbscht_spy
17:08rhickeyreactor best so far
17:08Chouserspecial-agent
17:09drewr:-)
17:12arbscht_reactor will take some getting used to. my first thought is of nuclear reactors and the like
17:13Chouserwatchdog
17:15Chousersubscriber
17:16kotarakwatchdog is something different. It checks that a given process still runs and takes appropriate measures otherwise
17:16arbscht_subscriber resonates
17:16rhickeysubscriber overlaps with message queues
17:18Chouserthese will be run via 'send' always, not 'send-off', I assume?
17:19rhickeysend-off
17:19Chouseroh
17:22ChouserI guess if I don't want to thrash the CPU too much I can just 'send' from inside my reactor agent.
17:23rhickeyChouser: all sends, even send-offs, to the same agent serialize
17:23rhickeyso topology can constrain things too
17:30ChouserI don't know what you mean by "agent serialize" or "topology" here, but I don't need to right now.
17:33rhickeyChouser: if you only have 4 watchers, you'll never use more than 4 threads, even with send-off
17:33soothDoes NO_SOURCE_FILE have any special significance in a ClassNotFoundException?
17:37Chouserrhickey: if the agents acting as watches themselves have watchers, couldn't the number of threads baloon?
17:39rhickeyChouser: yes, but that's where topology comes into play - you'll tend to have fewer watchers than watchees
17:40Chouserok. it's not worth associating a send vs. send-off preference with each action?
17:41rhickeyChouser: that's possible, people seem to be pretty confused about the difference
17:42rhickeyI've also been wondering, as I consider a la carte pools, whether an agent will ever need both send and send-off - that could become a property of its pool
17:43drewrsooth: Did you eval from the REPL?
17:44soothdrewr: slime-eval-buffer
17:46soothdrewr: It for a Java package. I added "/usr/share/java/*" (Java library path) to swank-clojure-extra-classpaths.
17:47ChouserSo far I've hardly ever used more than one action per agent, so it's a bit hard to say. But it seems like blocking vs. non-blocking has more to do with the action than the agent.
17:48rhickeyChouser: yes it does, and that's why it is the way it is, but in practice I think agents are either computational or I/O oriented.
17:49rhickeyas we get more cores, it might be useful for computational agents to work from pools restricted to a few cores
17:50rhickeyand everything else use variable queues
17:54drewrsooth: slime-eval-buffer is just going to send your code via swank to the REPL.
17:54soothdrewr: Okay so I guess my answer is "yes'
17:57soothI'm trying to run the third example at http://paste.lisp.org/display/70171 and getting the error for tagsoup (whose jar is installed in /usr/share/java/)
18:06RaynesHey guys, check this out if you haven't already.
18:06Rayneshttp://lambda-the-ultimate.org/node/3144
18:07Lau_of_DKCool
18:07RaynesA good few people repping clojure :>
18:08Lau_of_DKYea
18:08Lau_of_DKBut one guy says "C++" *giggle*
18:10rzezeskiAmazing how many people claim Java is about to "die." So much hate.
18:11RaynesJava will rule the buisness world for the next 10 years at least imo.
18:11RaynesThen languages like Clojure and Scala will begin to take over.
18:11rzezeskiWouldn't surprise me (java ruling for 10 years that is). I'm not saying I love Java, but people that claim it's "dead" confuse me.
18:12rzezeskiI guess they work in .Net shops :)
18:14RaynesI'd like to see Haskell gain popularity.
18:15rzezeskiI'd say it already has over the last couple of years. Especially now that RWH is out.
18:16rzezeskiIsn't F# heavily influenced by Haskell as well? It's type system at least?
18:16RaynesNo.
18:16RaynesF# is OCaml for the .NET pretty much.
18:16RaynesF# is a mess.
18:17rzezeskiOh, ok. Gotcha. I thought I remember Neil Mitchell comparing Haskell with F# recently
18:17rzezeskiHe seemed to give it a pretty decent review, but most of his commenters kinda ragged him for it if I remember correctly.
18:18RaynesAlmost any imperative programmer sees Haskells purity as damaging, they just don't understand it.
18:19RaynesBut the 577 people in #haskell would surely beg to differ :D
18:23rzezeskiDon't know if you mean Neil, but I'd say he's Haskell to the bone. I like Haskell's purity, but anytime I had to do IO with Haskell I failed miserably. My programs would turn into big long functions wrapped in the IO monad. So while I love the purity, I didn't apply it too well. I also didn't spend nearly enough time with it either. I think Haskell rocks, but I think I'm starting to like LIsp/Clojure more.
18:24RaynesWhen I think Clojure I think Revenge Of The LISP.
18:25rzezeskiThe first thing that really made me like Lisp was watching some of the SICP lectures and loving how simple and uniform Lisp syntax is. I didn't have to read a 500 page book like I did for Java to learn all the syntactical rules and pitfalls. It amazed me.
19:38chrisnstupid question disclaimer...
19:38chrisnFirst forces evaluation of head, correct?
19:39rhickeychrisn: yes
19:40chrisncool. Laziness combined with threads and opengl = bus error and end of repl session...
20:45replacaIs the idiomatic way to do (contains? aseq val) on a sequence (some #( = val %) aseq)? Or is there a more precise way?
20:46gnuvinceI've seen some people using (some #{val} aseq)
20:46replacaoh, that might be nice.
20:47replacaactually I'm doing it between a String and a seq (to trim whitespace)
20:47replacaso I might just turn aseq into a set and use that
20:47replacaI always forget about using maps and sets as func
22:00rhickeysvn 1194 - Added watcher support for agents/atoms/refs/vars
22:15chrisnRich, you language is fun as hell.
22:16chrisns/you/your
22:17rhickeychrisn: thanks, glad you're having fun!
22:23RaynesSlime wont compile files for me :|
22:25RaynesAs a matter of fact, clojure wont even compile files for me.
22:55falcon0is there a way to be notified if a new binding is created in the clojure environment?
23:06Chouserfalcon0: you can now be notified when a particular var is changed
23:08rhickeyChouser: yes, var watchers are triggered only by root binding changes, not thread-local set!s
23:08Chouserah, cool. that's the only one I tested.
23:09Chouserthe docs don't mention the extra arg to the watcher action
23:10Chouserand add-watcher docs have a type "afer" instead of "after"
23:12rhickeythey do mention additional arg, will fix afer
23:12Chouseroh. indeed. sorry. :-)
23:12rhickeyis it unclear?
23:12Chouserno, I'm just distracted.
23:14falcon0Chouser or rhickey, how can I be notified when I do something like (def xyz 123) ? (this is for a development environment I'd like to write)
23:14falcon0I mean, when I add a binding (def or defn) on the REPL, how can I be notified?
23:15rhickeyfalcon0: no way right now
23:15rhickeydocs fixed, thanks
23:16falcon0I guess I misunderstood Chouser's comment above...so if I want to watch a specfic variable, I can listen to its changes...but not the global environment as a whole?
23:17rhickeyfalcon0: right
23:17falcon0i see...you said "no way right now" ... does that mean you are adding this functionality?
23:18rhickeyfalcon0: not planned
23:19falcon0ok...i assumed that global variables would be inside a clojure data structure accessed through agents or refs...doesn't that mean I could listen to that global agent/ref
23:19falcon0and get the info I need?
23:20Chouserrefs are interned in namespace objects, which don't have watchers
23:20rhickeyfalcon0: no, there is no global data structure through which the environment is changed - each var and namespace are independent
23:21rhickeynamespaces could have watchers theoretically, but a redef wouldn't go through the namespace
23:22falcon0rhickey: i see, so I know you added watchers to agents, will they be added to other reference variables as well?
23:22Chouseryou'd have to use the namespace watcher to register the var watcher.
23:22rhickeyfalcon0: watchers now supported for agents/var/atoms/refs
23:24falcon0rhickey: cool, i think CELLs or FRP type implementations work work better atomicly, rather than in an async manner
23:24rhickeyfalcon0: well, the notifications are async - agent actions
23:25falcon0so if I am watching a ref...will i get notified of a change inside the transaction or after the transaction has 'comitted'?
23:26rhickeyfalcon0: after