[{"data":1,"prerenderedAt":1461},["ShallowReactive",2],{"\u002Ftlt-2015.07.26-exploring-clojure-in-the-repl":3},{"id":4,"title":5,"body":6,"createdAt":1448,"description":12,"draft":1449,"extension":1450,"image":1451,"mastodonThread":1451,"meta":1452,"navigation":1453,"path":1454,"seo":1455,"stem":1456,"tags":1457,"updatedAt":1459,"__hash__":1460},"content\u002FTLT - 2015.07.26 - Exploring Clojure in the REPL.md","TLT_-_2015.07.26_-_Exploring_Clojure_in_the_REPL",{"type":7,"value":8,"toc":1442},"minimark",[9,13,16,19,24,27,30,169,172,268,271,301,304,331,335,338,341,389,392,416,419,440,443,530,533,750,754,757,832,835,844,848,851,874,877,917,920,958,961,990,993,1015,1018,1061,1064,1435,1438],[10,11,12],"p",{},"Tags: Clojure, REPL",[10,14,15],{},"When I first learned Linux, my friend taught me a few commands. How to to list files, how to change directories and see your current directory, how to run things, how to ask a program what parameters it takes, and how to look at a file (ls, cd, pwd, .\u002Ffoo or \u002Fusr\u002Fbin\u002Ffoo or foo, foo --help, cat foo or more foo). After that I just... ran a lot of stuff. I eventually discovered 'man' -- but going through \u002Fbin and running ALL the commands was really educational.",[10,17,18],{},"Let's get some basic tools to do that with the Clojure REPL! The major things we want to do are find things (mostly functions), and then learn all about them individually.",[20,21,23],"h2",{"id":22},"finding-things","Finding Things",[10,25,26],{},"So Clojure has namespaces, which are kinda like directories, using \".\" as a way to indicate nesting. Vars (and thereby named functions) are kinda like files. So the full \"path\" to a var looks like \"clojure.string\u002Fsplit\" where \"clojure.string\" is the namespace and \"split\" is the function.",[10,28,29],{},"First let's get a list of all the loaded namespaces. The \"ns-all\" gives us this, but we want a nice sorted printout, so we'll add a bit of fancy.",[31,32,37],"pre",{"className":33,"code":34,"language":35,"meta":36,"style":36},"language-clojure shiki shiki-themes github-light github-dark monokai","user=> (doseq [n (sort (map ns-name (all-ns)))] (println n))\n; ... trimmed ...\nclojure.core\nclojure.core.protocols\nclojure.inspector\n; ... trimmed ...\nclojure.repl\nclojure.set\nclojure.stacktrace\nclojure.string\nclojure.template\nclojure.test\nclojure.tools.cli\nclojure.tools.nrepl\n; ... trimmed ...\nuser\n","clojure","",[38,39,40,80,87,93,99,105,110,116,122,128,134,140,146,152,158,163],"code",{"__ignoreMap":36},[41,42,45,49,53,56,59,62,65,68,71,74,77],"span",{"class":43,"line":44},"line",1,[41,46,48],{"class":47},"sMOD_","user=> (",[41,50,52],{"class":51},"srTi1","doseq",[41,54,55],{"class":47}," [n (",[41,57,58],{"class":51},"sort",[41,60,61],{"class":47}," (",[41,63,64],{"class":51},"map",[41,66,67],{"class":47}," ns-name (",[41,69,70],{"class":51},"all-ns",[41,72,73],{"class":47},")))] (",[41,75,76],{"class":51},"println",[41,78,79],{"class":47}," n))\n",[41,81,83],{"class":43,"line":82},2,[41,84,86],{"class":85},"s8-w5","; ... trimmed ...\n",[41,88,90],{"class":43,"line":89},3,[41,91,92],{"class":47},"clojure.core\n",[41,94,96],{"class":43,"line":95},4,[41,97,98],{"class":47},"clojure.core.protocols\n",[41,100,102],{"class":43,"line":101},5,[41,103,104],{"class":47},"clojure.inspector\n",[41,106,108],{"class":43,"line":107},6,[41,109,86],{"class":85},[41,111,113],{"class":43,"line":112},7,[41,114,115],{"class":47},"clojure.repl\n",[41,117,119],{"class":43,"line":118},8,[41,120,121],{"class":47},"clojure.set\n",[41,123,125],{"class":43,"line":124},9,[41,126,127],{"class":47},"clojure.stacktrace\n",[41,129,131],{"class":43,"line":130},10,[41,132,133],{"class":47},"clojure.string\n",[41,135,137],{"class":43,"line":136},11,[41,138,139],{"class":47},"clojure.template\n",[41,141,143],{"class":43,"line":142},12,[41,144,145],{"class":47},"clojure.test\n",[41,147,149],{"class":43,"line":148},13,[41,150,151],{"class":47},"clojure.tools.cli\n",[41,153,155],{"class":43,"line":154},14,[41,156,157],{"class":47},"clojure.tools.nrepl\n",[41,159,161],{"class":43,"line":160},15,[41,162,86],{"class":85},[41,164,166],{"class":43,"line":165},16,[41,167,168],{"class":47},"user\n",[10,170,171],{},"Use \"dir\" to look at all the exposed vars from a namespace",[31,173,175],{"className":33,"code":174,"language":35,"meta":36,"style":36},"user=> (dir clojure.string)\nblank?\ncapitalize\nescape\njoin\nlower-case\nre-quote-replacement\nreplace\nreplace-first\nreverse\nsplit\nsplit-lines\ntrim\ntrim-newline\ntriml\ntrimr\nupper-case\n",[38,176,177,187,192,197,202,207,212,217,222,227,232,237,242,247,252,257,262],{"__ignoreMap":36},[41,178,179,181,184],{"class":43,"line":44},[41,180,48],{"class":47},[41,182,183],{"class":51},"dir",[41,185,186],{"class":47}," clojure.string)\n",[41,188,189],{"class":43,"line":82},[41,190,191],{"class":47},"blank?\n",[41,193,194],{"class":43,"line":89},[41,195,196],{"class":47},"capitalize\n",[41,198,199],{"class":43,"line":95},[41,200,201],{"class":47},"escape\n",[41,203,204],{"class":43,"line":101},[41,205,206],{"class":47},"join\n",[41,208,209],{"class":43,"line":107},[41,210,211],{"class":47},"lower-case\n",[41,213,214],{"class":43,"line":112},[41,215,216],{"class":47},"re-quote-replacement\n",[41,218,219],{"class":43,"line":118},[41,220,221],{"class":47},"replace\n",[41,223,224],{"class":43,"line":124},[41,225,226],{"class":47},"replace-first\n",[41,228,229],{"class":43,"line":130},[41,230,231],{"class":47},"reverse\n",[41,233,234],{"class":43,"line":136},[41,235,236],{"class":47},"split\n",[41,238,239],{"class":43,"line":142},[41,240,241],{"class":47},"split-lines\n",[41,243,244],{"class":43,"line":148},[41,245,246],{"class":47},"trim\n",[41,248,249],{"class":43,"line":154},[41,250,251],{"class":47},"trim-newline\n",[41,253,254],{"class":43,"line":160},[41,255,256],{"class":47},"triml\n",[41,258,259],{"class":43,"line":165},[41,260,261],{"class":47},"trimr\n",[41,263,265],{"class":43,"line":264},17,[41,266,267],{"class":47},"upper-case\n",[10,269,270],{},"Search for functions with \"split\" in their name. There is also \"apropos\" but it doesn't show namespaces -- \"apropos-better\" does, and \"find-name\" is an alias of that, so is better.",[31,272,274],{"className":33,"code":273,"language":35,"meta":36,"style":36},"user=> (find-name \"split\")\n(split-at split-with clojure.string\u002Fsplit clojure.string\u002Fsplit-lines net.cgrand.parsley.grammar\u002Fsplit-empty-prods)\n",[38,275,276,290],{"__ignoreMap":36},[41,277,278,280,283,287],{"class":43,"line":44},[41,279,48],{"class":47},[41,281,282],{"class":51},"find-name",[41,284,286],{"class":285},"sstjo"," \"split\"",[41,288,289],{"class":47},")\n",[41,291,292,295,298],{"class":43,"line":82},[41,293,294],{"class":47},"(",[41,296,297],{"class":51},"split-at",[41,299,300],{"class":47}," split-with clojure.string\u002Fsplit clojure.string\u002Fsplit-lines net.cgrand.parsley.grammar\u002Fsplit-empty-prods)\n",[10,302,303],{},"You can also use a regex! Not sure how useful this is... but here we are getting all the functions that start with an \"s\" and in with a \"t\".",[31,305,307],{"className":33,"code":306,"language":35,"meta":36,"style":36},"user=> (find-name #\"^s.*t$\")\n(set short sort sorted-set spit split-at struct clojure.set\u002Fselect clojure.string\u002Fsplit clojure.test\u002Fset-test net.cgrand.sjacket\u002Fshift net.cgrand.sjacket\u002Fshift-right net.cgrand.sjacket\u002Fstr-pt net.cgrand.sjacket\u002Fsubedit)\n",[38,308,309,321],{"__ignoreMap":36},[41,310,311,313,315,319],{"class":43,"line":44},[41,312,48],{"class":47},[41,314,282],{"class":51},[41,316,318],{"class":317},"sFxd3"," #\"^s.*t$\"",[41,320,289],{"class":47},[41,322,323,325,328],{"class":43,"line":82},[41,324,294],{"class":47},[41,326,327],{"class":51},"set",[41,329,330],{"class":47}," short sort sorted-set spit split-at struct clojure.set\u002Fselect clojure.string\u002Fsplit clojure.test\u002Fset-test net.cgrand.sjacket\u002Fshift net.cgrand.sjacket\u002Fshift-right net.cgrand.sjacket\u002Fstr-pt net.cgrand.sjacket\u002Fsubedit)\n",[20,332,334],{"id":333},"learning-about-things","Learning About Things",[10,336,337],{},"Once you've found your function, you'll want to learn more about it and maybe give it a try.",[10,339,340],{},"\"doc\" can be used to get the documentation associated with a function. This is pretty cool! It shows the full name of the function, its signature, and it's documentation.",[31,342,344],{"className":33,"code":343,"language":35,"meta":36,"style":36},"user=> (doc print)\n-------------------------\nclojure.core\u002Fprint\n  Prints the object(s) to the output stream that is the current value\n  of *out*.  print and println produce output for human consumption.\n",[38,345,346,356,361,366,377],{"__ignoreMap":36},[41,347,348,350,353],{"class":43,"line":44},[41,349,48],{"class":47},[41,351,352],{"class":51},"doc",[41,354,355],{"class":47}," print)\n",[41,357,358],{"class":43,"line":82},[41,359,360],{"class":47},"-------------------------\n",[41,362,363],{"class":43,"line":89},[41,364,365],{"class":47},"clojure.core\u002Fprint\n",[41,367,368,371,374],{"class":43,"line":95},[41,369,370],{"class":47},"  Prints the object(",[41,372,373],{"class":51},"s",[41,375,376],{"class":47},") to the output stream that is the current value\n",[41,378,379,382,386],{"class":43,"line":101},[41,380,381],{"class":47},"  of *out*.  print and println produce output ",[41,383,385],{"class":384},"sC2Qs","for",[41,387,388],{"class":47}," human consumption.\n",[10,390,391],{},"Note that you can tab-complete",[31,393,395],{"className":33,"code":394,"language":35,"meta":36,"style":36},"user=> (doc print\u003Ctab>\nprint          print-ctor     print-dup      print-method   print-simple   print-str\nprintf         println        println-str\n",[38,396,397,406,411],{"__ignoreMap":36},[41,398,399,401,403],{"class":43,"line":44},[41,400,48],{"class":47},[41,402,352],{"class":51},[41,404,405],{"class":47}," print\u003Ctab>\n",[41,407,408],{"class":43,"line":82},[41,409,410],{"class":47},"print          print-ctor     print-dup      print-method   print-simple   print-str\n",[41,412,413],{"class":43,"line":89},[41,414,415],{"class":47},"printf         println        println-str\n",[10,417,418],{},"If you don't know what you're looking for, you can also try find-doc. This will search both the name and the documentation itself for your string or regex.",[31,420,422],{"className":33,"code":421,"language":35,"meta":36,"style":36},"user=> (find-doc \"split\")\n; ..... too long to include ;)\n",[38,423,424,435],{"__ignoreMap":36},[41,425,426,428,431,433],{"class":43,"line":44},[41,427,48],{"class":47},[41,429,430],{"class":51},"find-doc",[41,432,286],{"class":285},[41,434,289],{"class":47},[41,436,437],{"class":43,"line":82},[41,438,439],{"class":85},"; ..... too long to include ;)\n",[10,441,442],{},"THE ULTIMATE: Get the source for a function!",[31,444,446],{"className":33,"code":445,"language":35,"meta":36,"style":36},"user=> (source print)\n(defn print\n  \"Prints the object(s) to the output stream that is the current value\n  of *out*.  print and println produce output for human consumption.\"\n  {:added \"1.0\"\n   :static true}\n    (binding [*print-readably* nil]\n      (apply pr more)))\n",[38,447,448,457,468,473,478,490,502,519],{"__ignoreMap":36},[41,449,450,452,455],{"class":43,"line":44},[41,451,48],{"class":47},[41,453,454],{"class":51},"source",[41,456,355],{"class":47},[41,458,459,461,464],{"class":43,"line":82},[41,460,294],{"class":47},[41,462,463],{"class":384},"defn",[41,465,467],{"class":466},"s_OQ2"," print\n",[41,469,470],{"class":43,"line":89},[41,471,472],{"class":285},"  \"Prints the object(s) to the output stream that is the current value\n",[41,474,475],{"class":43,"line":95},[41,476,477],{"class":285},"  of *out*.  print and println produce output for human consumption.\"\n",[41,479,480,483,487],{"class":43,"line":101},[41,481,482],{"class":47},"  {",[41,484,486],{"class":485},"sXSQT",":added",[41,488,489],{"class":285}," \"1.0\"\n",[41,491,492,495,499],{"class":43,"line":107},[41,493,494],{"class":485},"   :static",[41,496,498],{"class":497},"s7F3e"," true",[41,500,501],{"class":47},"}\n",[41,503,504,507,510,513,516],{"class":43,"line":112},[41,505,506],{"class":47},"    (",[41,508,509],{"class":384},"binding",[41,511,512],{"class":47}," [*print-readably* ",[41,514,515],{"class":497},"nil",[41,517,518],{"class":47},"]\n",[41,520,521,524,527],{"class":43,"line":118},[41,522,523],{"class":47},"      (",[41,525,526],{"class":51},"apply",[41,528,529],{"class":47}," pr more)))\n",[10,531,532],{},"Not everything is a function. Heck, sometimes you might not know what sort of thing you're looking at. But we can find out.",[31,534,536],{"className":33,"code":535,"language":35,"meta":36,"style":36},"user=> (type 5)\njava.lang.Long\nuser=> (type 5.2)\njava.lang.Double\nuser=> (type \"hello\")\njava.lang.String\nuser=> (type 'hello)\nclojure.lang.Symbol\nuser=> (type {:a 5, :b 6})\nclojure.lang.PersistentArrayMap\nuser=> (type [1 2 3])\nclojure.lang.PersistentVector\nuser=> (type type)\nclojure.core$type\nuser=> (type dir)\nCompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl\u002Fdir, compiling:(\u002Ftmp\u002Fform-init5987247545872948247.clj:1:1) \nuser=> (type clojure.string\u002Fsplit)\nclojure.string$split\nuser=> (defn say-hi [] (println \"hi!\"))\n#'user\u002Fsay-hi\nuser=> (type say-hi)\nuser$say_hi\n",[38,537,538,550,555,566,571,582,587,596,601,627,632,653,658,667,672,681,692,701,707,728,734,744],{"__ignoreMap":36},[41,539,540,542,545,548],{"class":43,"line":44},[41,541,48],{"class":47},[41,543,544],{"class":51},"type",[41,546,547],{"class":497}," 5",[41,549,289],{"class":47},[41,551,552],{"class":43,"line":82},[41,553,554],{"class":47},"java.lang.Long\n",[41,556,557,559,561,564],{"class":43,"line":89},[41,558,48],{"class":47},[41,560,544],{"class":51},[41,562,563],{"class":497}," 5.2",[41,565,289],{"class":47},[41,567,568],{"class":43,"line":95},[41,569,570],{"class":47},"java.lang.Double\n",[41,572,573,575,577,580],{"class":43,"line":101},[41,574,48],{"class":47},[41,576,544],{"class":51},[41,578,579],{"class":285}," \"hello\"",[41,581,289],{"class":47},[41,583,584],{"class":43,"line":107},[41,585,586],{"class":47},"java.lang.String\n",[41,588,589,591,593],{"class":43,"line":112},[41,590,48],{"class":47},[41,592,544],{"class":51},[41,594,595],{"class":47}," 'hello)\n",[41,597,598],{"class":43,"line":118},[41,599,600],{"class":47},"clojure.lang.Symbol\n",[41,602,603,605,607,610,613,615,618,621,624],{"class":43,"line":124},[41,604,48],{"class":47},[41,606,544],{"class":51},[41,608,609],{"class":47}," {",[41,611,612],{"class":485},":a",[41,614,547],{"class":497},[41,616,617],{"class":47},", ",[41,619,620],{"class":485},":b",[41,622,623],{"class":497}," 6",[41,625,626],{"class":47},"})\n",[41,628,629],{"class":43,"line":130},[41,630,631],{"class":47},"clojure.lang.PersistentArrayMap\n",[41,633,634,636,638,641,644,647,650],{"class":43,"line":136},[41,635,48],{"class":47},[41,637,544],{"class":51},[41,639,640],{"class":47}," [",[41,642,643],{"class":497},"1",[41,645,646],{"class":497}," 2",[41,648,649],{"class":497}," 3",[41,651,652],{"class":47},"])\n",[41,654,655],{"class":43,"line":142},[41,656,657],{"class":47},"clojure.lang.PersistentVector\n",[41,659,660,662,664],{"class":43,"line":148},[41,661,48],{"class":47},[41,663,544],{"class":51},[41,665,666],{"class":47}," type)\n",[41,668,669],{"class":43,"line":154},[41,670,671],{"class":47},"clojure.core$type\n",[41,673,674,676,678],{"class":43,"line":160},[41,675,48],{"class":47},[41,677,544],{"class":51},[41,679,680],{"class":47}," dir)\n",[41,682,683,686,689],{"class":43,"line":165},[41,684,685],{"class":47},"CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl\u002Fdir, compiling:(",[41,687,688],{"class":51},"\u002Ftmp\u002Fform-init5987247545872948247.clj:1:1",[41,690,691],{"class":47},") \n",[41,693,694,696,698],{"class":43,"line":264},[41,695,48],{"class":47},[41,697,544],{"class":51},[41,699,700],{"class":47}," clojure.string\u002Fsplit)\n",[41,702,704],{"class":43,"line":703},18,[41,705,706],{"class":47},"clojure.string$split\n",[41,708,710,712,714,717,720,722,725],{"class":43,"line":709},19,[41,711,48],{"class":47},[41,713,463],{"class":384},[41,715,716],{"class":466}," say-hi",[41,718,719],{"class":47}," [] (",[41,721,76],{"class":51},[41,723,724],{"class":285}," \"hi!\"",[41,726,727],{"class":47},"))\n",[41,729,731],{"class":43,"line":730},20,[41,732,733],{"class":47},"#'user\u002Fsay-hi\n",[41,735,737,739,741],{"class":43,"line":736},21,[41,738,48],{"class":47},[41,740,544],{"class":51},[41,742,743],{"class":47}," say-hi)\n",[41,745,747],{"class":43,"line":746},22,[41,748,749],{"class":47},"user$say_hi\n",[20,751,753],{"id":752},"getting-gui","Getting GUI",[10,755,756],{},"Clojure comes with clojure.inspector, which gives some Swing GUI for exploring data structures.",[31,758,760],{"className":33,"code":759,"language":35,"meta":36,"style":36},"user=> (use 'clojure.inspector)\nuser=> (inspect-tree {:a 1 :b 2 :c [1 2 3 {:d 4 :e 5 :f [6 7 8]}]})\n",[38,761,762,772],{"__ignoreMap":36},[41,763,764,766,769],{"class":43,"line":44},[41,765,48],{"class":47},[41,767,768],{"class":384},"use",[41,770,771],{"class":47}," 'clojure.inspector)\n",[41,773,774,776,779,781,783,786,789,791,794,796,798,800,802,804,807,810,813,815,818,820,823,826,829],{"class":43,"line":82},[41,775,48],{"class":47},[41,777,778],{"class":51},"inspect-tree",[41,780,609],{"class":47},[41,782,612],{"class":485},[41,784,785],{"class":497}," 1",[41,787,788],{"class":485}," :b",[41,790,646],{"class":497},[41,792,793],{"class":485}," :c",[41,795,640],{"class":47},[41,797,643],{"class":497},[41,799,646],{"class":497},[41,801,649],{"class":497},[41,803,609],{"class":47},[41,805,806],{"class":485},":d",[41,808,809],{"class":497}," 4",[41,811,812],{"class":485}," :e",[41,814,547],{"class":497},[41,816,817],{"class":485}," :f",[41,819,640],{"class":47},[41,821,822],{"class":497},"6",[41,824,825],{"class":497}," 7",[41,827,828],{"class":497}," 8",[41,830,831],{"class":47},"]}]})\n",[10,833,834],{},"NOTE: I had to do this to get jdk-1.7 swing apps to display while using xmonad (and other tiling window managers I guess). I now dropped this in my ~\u002F.zshrc. Uhg.",[31,836,838],{"className":33,"code":837,"language":35,"meta":36,"style":36},"export _JAVA_AWT_WM_NONREPARENTING=1\n",[38,839,840],{"__ignoreMap":36},[41,841,842],{"class":43,"line":44},[41,843,837],{"class":47},[20,845,847],{"id":846},"doing-horrible-things","Doing Horrible Things",[10,849,850],{},"So let's have some fun. First, let's get all the string function names. \"dir-fn\" is like dir, but returns the results instead of printing them.",[31,852,854],{"className":33,"code":853,"language":35,"meta":36,"style":36},"user=> (def string-funcs (clojure.repl\u002Fdir-fn 'clojure.string))\n",[38,855,856],{"__ignoreMap":36},[41,857,858,860,863,866,868,871],{"class":43,"line":44},[41,859,48],{"class":47},[41,861,862],{"class":384},"def",[41,864,865],{"class":466}," string-funcs",[41,867,61],{"class":47},[41,869,870],{"class":51},"clojure.repl\u002Fdir-fn",[41,872,873],{"class":47}," 'clojure.string))\n",[10,875,876],{},"Let's turn them into their actual functions.",[31,878,880],{"className":33,"code":879,"language":35,"meta":36,"style":36},"user=> (def real-string-funcs (map #(resolve (symbol (str \"clojure.string\u002F\" %))) string-funcs))\n",[38,881,882],{"__ignoreMap":36},[41,883,884,886,888,891,893,895,898,901,903,906,908,911,914],{"class":43,"line":44},[41,885,48],{"class":47},[41,887,862],{"class":384},[41,889,890],{"class":466}," real-string-funcs",[41,892,61],{"class":47},[41,894,64],{"class":51},[41,896,897],{"class":47}," #(",[41,899,900],{"class":51},"resolve",[41,902,61],{"class":47},[41,904,905],{"class":51},"symbol",[41,907,61],{"class":47},[41,909,910],{"class":51},"str",[41,912,913],{"class":285}," \"clojure.string\u002F\"",[41,915,916],{"class":47}," %))) string-funcs))\n",[10,918,919],{},"Given a function, here is how to tell how many parameters it takes (well... it might take more or less than this, but this will tell us how many params for the first definition. Good enough).",[31,921,923],{"className":33,"code":922,"language":35,"meta":36,"style":36},"user=> (defn arg-count [f] (count (first (:arglists (meta f)))))\n",[38,924,925],{"__ignoreMap":36},[41,926,927,929,931,934,937,940,942,945,947,950,952,955],{"class":43,"line":44},[41,928,48],{"class":47},[41,930,463],{"class":384},[41,932,933],{"class":466}," arg-count",[41,935,936],{"class":47}," [f] (",[41,938,939],{"class":51},"count",[41,941,61],{"class":47},[41,943,944],{"class":51},"first",[41,946,61],{"class":47},[41,948,949],{"class":485},":arglists",[41,951,61],{"class":47},[41,953,954],{"class":51},"meta",[41,956,957],{"class":47}," f)))))\n",[10,959,960],{},"Here is a handy thing that tells us if the given function can deal with a single arg.",[31,962,964],{"className":33,"code":963,"language":35,"meta":36,"style":36},"user=> (defn single-arg? [f] (= 1 (arg-count f)))\n",[38,965,966],{"__ignoreMap":36},[41,967,968,970,972,975,977,980,982,984,987],{"class":43,"line":44},[41,969,48],{"class":47},[41,971,463],{"class":384},[41,973,974],{"class":466}," single-arg?",[41,976,936],{"class":47},[41,978,979],{"class":51},"=",[41,981,785],{"class":497},[41,983,61],{"class":47},[41,985,986],{"class":51},"arg-count",[41,988,989],{"class":47}," f)))\n",[10,991,992],{},"Now let's filter our string functions down to the ones that just take one argument.",[31,994,996],{"className":33,"code":995,"language":35,"meta":36,"style":36},"user=> (def one-arg-funcs (filter single-arg? real-string-funcs))\n",[38,997,998],{"__ignoreMap":36},[41,999,1000,1002,1004,1007,1009,1012],{"class":43,"line":44},[41,1001,48],{"class":47},[41,1003,862],{"class":384},[41,1005,1006],{"class":466}," one-arg-funcs",[41,1008,61],{"class":47},[41,1010,1011],{"class":51},"filter",[41,1013,1014],{"class":47}," single-arg? real-string-funcs))\n",[10,1016,1017],{},"So. We if have a one-argument function in the clojure.string namespace, let's assume it takes a string and pass in a string to it :) . The \"pr-str\" bit is so that we can pretty-print this with escaped newlines and such later.",[31,1019,1021],{"className":33,"code":1020,"language":35,"meta":36,"style":36},"user=> (defn one-arg-result [f] (pr-str (apply f [\"Hello\\nworld\\n\"])))\n",[38,1022,1023],{"__ignoreMap":36},[41,1024,1025,1027,1029,1032,1034,1037,1039,1041,1044,1047,1050,1053,1055,1058],{"class":43,"line":44},[41,1026,48],{"class":47},[41,1028,463],{"class":384},[41,1030,1031],{"class":466}," one-arg-result",[41,1033,936],{"class":47},[41,1035,1036],{"class":51},"pr-str",[41,1038,61],{"class":47},[41,1040,526],{"class":51},[41,1042,1043],{"class":47}," f [",[41,1045,1046],{"class":285},"\"Hello",[41,1048,1049],{"class":497},"\\n",[41,1051,1052],{"class":285},"world",[41,1054,1049],{"class":497},[41,1056,1057],{"class":285},"\"",[41,1059,1060],{"class":47},"])))\n",[10,1062,1063],{},"Now let's try this on all the one-argument string functions, printing out the function name and the result pretty like.",[31,1065,1067],{"className":33,"code":1066,"language":35,"meta":36,"style":36},"user=> (map #(println (:name (meta %))  \"\\\"Hello\\\\nworld\\\\n\\\" ->\" (one-arg-result %)) one-arg-funcs)\nblank? \"Hello\\nworld\\n\" -> false\ncapitalize \"Hello\\nworld\\n\" -> \"Hello\\nworld\\n\"\njoin \"Hello\\nworld\\n\" -> \"Hello\\nworld\\n\"\nlower-case \"Hello\\nworld\\n\" -> \"hello\\nworld\\n\"\nre-quote-replacement \"Hello\\nworld\\n\" -> \"Hello\\nworld\\n\"\nreverse \"Hello\\nworld\\n\" -> \"\\ndlrow\\nolleH\"\nsplit-lines \"Hello\\nworld\\n\" -> [\"Hello\" \"world\"]\ntrim \"Hello\\nworld\\n\" -> \"Hello\\nworld\"\ntrim-newline \"Hello\\nworld\\n\" -> \"Hello\\nworld\"\ntriml \"Hello\\nworld\\n\" -> \"Hello\\nworld\\n\"\ntrimr \"Hello\\nworld\\n\" -> \"Hello\\nworld\"\nupper-case \"Hello\\nworld\\n\" -> \"HELLO\\nWORLD\\n\"\n",[38,1068,1069,1123,1144,1172,1199,1227,1254,1283,1309,1333,1356,1383,1406],{"__ignoreMap":36},[41,1070,1071,1073,1075,1077,1079,1081,1084,1086,1088,1091,1093,1096,1099,1102,1105,1107,1110,1112,1115,1117,1120],{"class":43,"line":44},[41,1072,48],{"class":47},[41,1074,64],{"class":51},[41,1076,897],{"class":47},[41,1078,76],{"class":51},[41,1080,61],{"class":47},[41,1082,1083],{"class":485},":name",[41,1085,61],{"class":47},[41,1087,954],{"class":51},[41,1089,1090],{"class":47}," %))  ",[41,1092,1057],{"class":285},[41,1094,1095],{"class":497},"\\\"",[41,1097,1098],{"class":285},"Hello",[41,1100,1101],{"class":497},"\\\\",[41,1103,1104],{"class":285},"nworld",[41,1106,1101],{"class":497},[41,1108,1109],{"class":285},"n",[41,1111,1095],{"class":497},[41,1113,1114],{"class":285}," ->\"",[41,1116,61],{"class":47},[41,1118,1119],{"class":51},"one-arg-result",[41,1121,1122],{"class":47}," %)) one-arg-funcs)\n",[41,1124,1125,1128,1130,1132,1134,1136,1138,1141],{"class":43,"line":82},[41,1126,1127],{"class":47},"blank? ",[41,1129,1046],{"class":285},[41,1131,1049],{"class":497},[41,1133,1052],{"class":285},[41,1135,1049],{"class":497},[41,1137,1057],{"class":285},[41,1139,1140],{"class":47}," -> ",[41,1142,1143],{"class":497},"false\n",[41,1145,1146,1149,1151,1153,1155,1157,1159,1161,1163,1165,1167,1169],{"class":43,"line":89},[41,1147,1148],{"class":47},"capitalize ",[41,1150,1046],{"class":285},[41,1152,1049],{"class":497},[41,1154,1052],{"class":285},[41,1156,1049],{"class":497},[41,1158,1057],{"class":285},[41,1160,1140],{"class":47},[41,1162,1046],{"class":285},[41,1164,1049],{"class":497},[41,1166,1052],{"class":285},[41,1168,1049],{"class":497},[41,1170,1171],{"class":285},"\"\n",[41,1173,1174,1177,1179,1181,1183,1185,1187,1189,1191,1193,1195,1197],{"class":43,"line":95},[41,1175,1176],{"class":47},"join ",[41,1178,1046],{"class":285},[41,1180,1049],{"class":497},[41,1182,1052],{"class":285},[41,1184,1049],{"class":497},[41,1186,1057],{"class":285},[41,1188,1140],{"class":47},[41,1190,1046],{"class":285},[41,1192,1049],{"class":497},[41,1194,1052],{"class":285},[41,1196,1049],{"class":497},[41,1198,1171],{"class":285},[41,1200,1201,1204,1206,1208,1210,1212,1214,1216,1219,1221,1223,1225],{"class":43,"line":101},[41,1202,1203],{"class":47},"lower-case ",[41,1205,1046],{"class":285},[41,1207,1049],{"class":497},[41,1209,1052],{"class":285},[41,1211,1049],{"class":497},[41,1213,1057],{"class":285},[41,1215,1140],{"class":47},[41,1217,1218],{"class":285},"\"hello",[41,1220,1049],{"class":497},[41,1222,1052],{"class":285},[41,1224,1049],{"class":497},[41,1226,1171],{"class":285},[41,1228,1229,1232,1234,1236,1238,1240,1242,1244,1246,1248,1250,1252],{"class":43,"line":107},[41,1230,1231],{"class":47},"re-quote-replacement ",[41,1233,1046],{"class":285},[41,1235,1049],{"class":497},[41,1237,1052],{"class":285},[41,1239,1049],{"class":497},[41,1241,1057],{"class":285},[41,1243,1140],{"class":47},[41,1245,1046],{"class":285},[41,1247,1049],{"class":497},[41,1249,1052],{"class":285},[41,1251,1049],{"class":497},[41,1253,1171],{"class":285},[41,1255,1256,1259,1261,1263,1265,1267,1269,1271,1273,1275,1278,1280],{"class":43,"line":112},[41,1257,1258],{"class":47},"reverse ",[41,1260,1046],{"class":285},[41,1262,1049],{"class":497},[41,1264,1052],{"class":285},[41,1266,1049],{"class":497},[41,1268,1057],{"class":285},[41,1270,1140],{"class":47},[41,1272,1057],{"class":285},[41,1274,1049],{"class":497},[41,1276,1277],{"class":285},"dlrow",[41,1279,1049],{"class":497},[41,1281,1282],{"class":285},"olleH\"\n",[41,1284,1285,1288,1290,1292,1294,1296,1298,1301,1304,1307],{"class":43,"line":118},[41,1286,1287],{"class":47},"split-lines ",[41,1289,1046],{"class":285},[41,1291,1049],{"class":497},[41,1293,1052],{"class":285},[41,1295,1049],{"class":497},[41,1297,1057],{"class":285},[41,1299,1300],{"class":47}," -> [",[41,1302,1303],{"class":285},"\"Hello\"",[41,1305,1306],{"class":285}," \"world\"",[41,1308,518],{"class":47},[41,1310,1311,1314,1316,1318,1320,1322,1324,1326,1328,1330],{"class":43,"line":124},[41,1312,1313],{"class":47},"trim ",[41,1315,1046],{"class":285},[41,1317,1049],{"class":497},[41,1319,1052],{"class":285},[41,1321,1049],{"class":497},[41,1323,1057],{"class":285},[41,1325,1140],{"class":47},[41,1327,1046],{"class":285},[41,1329,1049],{"class":497},[41,1331,1332],{"class":285},"world\"\n",[41,1334,1335,1338,1340,1342,1344,1346,1348,1350,1352,1354],{"class":43,"line":130},[41,1336,1337],{"class":47},"trim-newline ",[41,1339,1046],{"class":285},[41,1341,1049],{"class":497},[41,1343,1052],{"class":285},[41,1345,1049],{"class":497},[41,1347,1057],{"class":285},[41,1349,1140],{"class":47},[41,1351,1046],{"class":285},[41,1353,1049],{"class":497},[41,1355,1332],{"class":285},[41,1357,1358,1361,1363,1365,1367,1369,1371,1373,1375,1377,1379,1381],{"class":43,"line":136},[41,1359,1360],{"class":47},"triml ",[41,1362,1046],{"class":285},[41,1364,1049],{"class":497},[41,1366,1052],{"class":285},[41,1368,1049],{"class":497},[41,1370,1057],{"class":285},[41,1372,1140],{"class":47},[41,1374,1046],{"class":285},[41,1376,1049],{"class":497},[41,1378,1052],{"class":285},[41,1380,1049],{"class":497},[41,1382,1171],{"class":285},[41,1384,1385,1388,1390,1392,1394,1396,1398,1400,1402,1404],{"class":43,"line":142},[41,1386,1387],{"class":47},"trimr ",[41,1389,1046],{"class":285},[41,1391,1049],{"class":497},[41,1393,1052],{"class":285},[41,1395,1049],{"class":497},[41,1397,1057],{"class":285},[41,1399,1140],{"class":47},[41,1401,1046],{"class":285},[41,1403,1049],{"class":497},[41,1405,1332],{"class":285},[41,1407,1408,1411,1413,1415,1417,1419,1421,1423,1426,1428,1431,1433],{"class":43,"line":148},[41,1409,1410],{"class":47},"upper-case ",[41,1412,1046],{"class":285},[41,1414,1049],{"class":497},[41,1416,1052],{"class":285},[41,1418,1049],{"class":497},[41,1420,1057],{"class":285},[41,1422,1140],{"class":47},[41,1424,1425],{"class":285},"\"HELLO",[41,1427,1049],{"class":497},[41,1429,1430],{"class":285},"WORLD",[41,1432,1049],{"class":497},[41,1434,1171],{"class":285},[10,1436,1437],{},"Woo!",[1439,1440,1441],"style",{},"html pre.shiki code .sMOD_, html code.shiki .sMOD_{--shiki-default:#24292E;--shiki-dark:#E1E4E8;--shiki-sepia:#F8F8F2}html pre.shiki code .srTi1, html code.shiki .srTi1{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#A6E22E}html pre.shiki code .s8-w5, html code.shiki .s8-w5{--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-sepia:#88846F}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html.sepia .shiki span {color: var(--shiki-sepia);background: var(--shiki-sepia-bg);font-style: var(--shiki-sepia-font-style);font-weight: var(--shiki-sepia-font-weight);text-decoration: var(--shiki-sepia-text-decoration);}html pre.shiki code .sstjo, html code.shiki .sstjo{--shiki-default:#032F62;--shiki-dark:#9ECBFF;--shiki-sepia:#E6DB74}html pre.shiki code .sFxd3, html code.shiki .sFxd3{--shiki-default:#032F62;--shiki-dark:#DBEDFF;--shiki-sepia:#E6DB74}html pre.shiki code .sC2Qs, html code.shiki .sC2Qs{--shiki-default:#D73A49;--shiki-dark:#F97583;--shiki-sepia:#F92672}html pre.shiki code .s_OQ2, html code.shiki .s_OQ2{--shiki-default:#6F42C1;--shiki-dark:#B392F0;--shiki-sepia:#F8F8F2}html pre.shiki code .sXSQT, html code.shiki .sXSQT{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#F8F8F2}html pre.shiki code .s7F3e, html code.shiki .s7F3e{--shiki-default:#005CC5;--shiki-dark:#79B8FF;--shiki-sepia:#AE81FF}",{"title":36,"searchDepth":82,"depth":82,"links":1443},[1444,1445,1446,1447],{"id":22,"depth":82,"text":23},{"id":333,"depth":82,"text":334},{"id":752,"depth":82,"text":753},{"id":846,"depth":82,"text":847},"2015-07-26T14:42-04:00",false,"md",null,{},true,"\u002Ftlt-2015.07.26-exploring-clojure-in-the-repl",{"title":5,"description":12},"TLT - 2015.07.26 - Exploring Clojure in the REPL",[1458],"blog","2015-10-18T16:06-04:00","tTK_BrfKDe0WgQInjXcSgxYo5S1Sq23LzCHaxyyRUxM",1778988314495]