Mercurial > lasercutter
diff src/clojure/contrib/io.clj @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/contrib/io.clj Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,564 @@ 1.4 +;;; io.clj -- duck-typed I/O streams for Clojure 1.5 + 1.6 +;; by Stuart Sierra, http://stuartsierra.com/ 1.7 +;; May 13, 2009 1.8 + 1.9 +;; Copyright (c) Stuart Sierra, 2009. All rights reserved. The use 1.10 +;; and distribution terms for this software are covered by the Eclipse 1.11 +;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 1.12 +;; which can be found in the file epl-v10.html at the root of this 1.13 +;; distribution. By using this software in any fashion, you are 1.14 +;; agreeing to be bound by the terms of this license. You must not 1.15 +;; remove this notice, or any other, from this software. 1.16 + 1.17 + 1.18 +;; This file defines "duck-typed" I/O utility functions for Clojure. 1.19 +;; The 'reader' and 'writer' functions will open and return an 1.20 +;; instance of java.io.BufferedReader and java.io.BufferedWriter, 1.21 +;; respectively, for a variety of argument types -- filenames as 1.22 +;; strings, URLs, java.io.File's, etc. 'reader' even works on http 1.23 +;; URLs. 1.24 +;; 1.25 +;; Note: this is not really "duck typing" as implemented in languages 1.26 +;; like Ruby. A better name would have been "do-what-I-mean-streams" 1.27 +;; or "just-give-me-a-stream", but ducks are funnier. 1.28 + 1.29 + 1.30 +;; CHANGE LOG 1.31 +;; 1.32 +;; July 23, 2010: Most functions here are deprecated. Use 1.33 +;; clojure.java.io 1.34 +;; 1.35 +;; May 13, 2009: added functions to open writers for appending 1.36 +;; 1.37 +;; May 3, 2009: renamed file to file-str, for compatibility with 1.38 +;; clojure.contrib.java. reader/writer no longer use this 1.39 +;; function. 1.40 +;; 1.41 +;; February 16, 2009: (lazy branch) fixed read-lines to work with lazy 1.42 +;; Clojure. 1.43 +;; 1.44 +;; January 10, 2009: added *default-encoding*, so streams are always 1.45 +;; opened as UTF-8. 1.46 +;; 1.47 +;; December 19, 2008: rewrote reader and writer as multimethods; added 1.48 +;; slurp*, file, and read-lines 1.49 +;; 1.50 +;; April 8, 2008: first version 1.51 + 1.52 + 1.53 + 1.54 +(ns 1.55 + ^{:author "Stuart Sierra", 1.56 + :doc "This file defines polymorphic I/O utility functions for Clojure. 1.57 + 1.58 + The Streams protocol defines reader, writer, input-stream and 1.59 + output-stream methods that return BufferedReader, BufferedWriter, 1.60 + BufferedInputStream and BufferedOutputStream instances (respectively), 1.61 + with default implementations extended to a variety of argument 1.62 + types: URLs or filenames as strings, java.io.File's, Sockets, etc."} 1.63 + clojure.contrib.io 1.64 + (:refer-clojure :exclude (spit)) 1.65 + (:import 1.66 + (java.io Reader InputStream InputStreamReader PushbackReader 1.67 + BufferedReader File OutputStream 1.68 + OutputStreamWriter BufferedWriter Writer 1.69 + FileInputStream FileOutputStream ByteArrayOutputStream 1.70 + StringReader ByteArrayInputStream 1.71 + BufferedInputStream BufferedOutputStream 1.72 + CharArrayReader) 1.73 + (java.net URI URL MalformedURLException Socket))) 1.74 + 1.75 + 1.76 +(def 1.77 + ^{:doc "Name of the default encoding to use when reading & writing. 1.78 + Default is UTF-8." 1.79 + :tag "java.lang.String"} 1.80 + *default-encoding* "UTF-8") 1.81 + 1.82 +(def 1.83 + ^{:doc "Size, in bytes or characters, of the buffer used when 1.84 + copying streams."} 1.85 + *buffer-size* 1024) 1.86 + 1.87 +(def 1.88 + ^{:doc "Type object for a Java primitive byte array."} 1.89 + *byte-array-type* (class (make-array Byte/TYPE 0))) 1.90 + 1.91 +(def 1.92 + ^{:doc "Type object for a Java primitive char array."} 1.93 + *char-array-type* (class (make-array Character/TYPE 0))) 1.94 + 1.95 + 1.96 +(defn ^File file-str 1.97 + "Concatenates args as strings and returns a java.io.File. Replaces 1.98 + all / and \\ with File/separatorChar. Replaces ~ at the start of 1.99 + the path with the user.home system property." 1.100 + [& args] 1.101 + (let [^String s (apply str args) 1.102 + s (.replace s \\ File/separatorChar) 1.103 + s (.replace s \/ File/separatorChar) 1.104 + s (if (.startsWith s "~") 1.105 + (str (System/getProperty "user.home") 1.106 + File/separator (subs s 1)) 1.107 + s)] 1.108 + (File. s))) 1.109 + 1.110 +(def 1.111 + ^{:doc "If true, writer, output-stream and spit will open files in append mode. 1.112 + Defaults to false. Instead of binding this var directly, use append-writer, 1.113 + append-output-stream or append-spit." 1.114 + :tag "java.lang.Boolean"} 1.115 + *append* false) 1.116 + 1.117 +(defn- assert-not-appending [] 1.118 + (when *append* 1.119 + (throw (Exception. "Cannot change an open stream to append mode.")))) 1.120 + 1.121 +;; @todo -- Both simple and elaborate methods for controlling buffering of 1.122 +;; in the Streams protocol were implemented, considered, and postponed 1.123 +;; see http://groups.google.com/group/clojure-dev/browse_frm/thread/3e39e9b3982f542b 1.124 +(defprotocol Streams 1.125 + (reader [x] 1.126 + "Attempts to coerce its argument into an open java.io.Reader. 1.127 + The default implementations of this protocol always return a 1.128 + java.io.BufferedReader. 1.129 + 1.130 + Default implementations are provided for Reader, BufferedReader, 1.131 + InputStream, File, URI, URL, Socket, byte arrays, character arrays, 1.132 + and String. 1.133 + 1.134 + If argument is a String, it tries to resolve it first as a URI, then 1.135 + as a local file name. URIs with a 'file' protocol are converted to 1.136 + local file names. If this fails, a final attempt is made to resolve 1.137 + the string as a resource on the CLASSPATH. 1.138 + 1.139 + Uses *default-encoding* as the text encoding. 1.140 + 1.141 + Should be used inside with-open to ensure the Reader is properly 1.142 + closed.") 1.143 + (writer [x] 1.144 + "Attempts to coerce its argument into an open java.io.Writer. 1.145 + The default implementations of this protocol always return a 1.146 + java.io.BufferedWriter. 1.147 + 1.148 + Default implementations are provided for Writer, BufferedWriter, 1.149 + OutputStream, File, URI, URL, Socket, and String. 1.150 + 1.151 + If the argument is a String, it tries to resolve it first as a URI, then 1.152 + as a local file name. URIs with a 'file' protocol are converted to 1.153 + local file names. 1.154 + 1.155 + Should be used inside with-open to ensure the Writer is properly 1.156 + closed.") 1.157 + (input-stream [x] 1.158 + "Attempts to coerce its argument into an open java.io.InputStream. 1.159 + The default implementations of this protocol always return a 1.160 + java.io.BufferedInputStream. 1.161 + 1.162 + Default implementations are defined for OutputStream, File, URI, URL, 1.163 + Socket, byte array, and String arguments. 1.164 + 1.165 + If the argument is a String, it tries to resolve it first as a URI, then 1.166 + as a local file name. URIs with a 'file' protocol are converted to 1.167 + local file names. 1.168 + 1.169 + Should be used inside with-open to ensure the InputStream is properly 1.170 + closed.") 1.171 + (output-stream [x] 1.172 + "Attempts to coerce its argument into an open java.io.OutputStream. 1.173 + The default implementations of this protocol always return a 1.174 + java.io.BufferedOutputStream. 1.175 + 1.176 + Default implementations are defined for OutputStream, File, URI, URL, 1.177 + Socket, and String arguments. 1.178 + 1.179 + If the argument is a String, it tries to resolve it first as a URI, then 1.180 + as a local file name. URIs with a 'file' protocol are converted to 1.181 + local file names. 1.182 + 1.183 + Should be used inside with-open to ensure the OutputStream is 1.184 + properly closed.")) 1.185 + 1.186 +(def default-streams-impl 1.187 + {:reader #(reader (input-stream %)) 1.188 + :writer #(writer (output-stream %)) 1.189 + :input-stream #(throw (Exception. (str "Cannot open <" (pr-str %) "> as an InputStream."))) 1.190 + :output-stream #(throw (Exception. (str "Cannot open <" (pr-str %) "> as an OutputStream.")))}) 1.191 + 1.192 +(extend File 1.193 + Streams 1.194 + (assoc default-streams-impl 1.195 + :input-stream #(input-stream (FileInputStream. ^File %)) 1.196 + :output-stream #(let [stream (FileOutputStream. ^File % *append*)] 1.197 + (binding [*append* false] 1.198 + (output-stream stream))))) 1.199 +(extend URL 1.200 + Streams 1.201 + (assoc default-streams-impl 1.202 + :input-stream (fn [^URL x] 1.203 + (input-stream (if (= "file" (.getProtocol x)) 1.204 + (FileInputStream. (.getPath x)) 1.205 + (.openStream x)))) 1.206 + :output-stream (fn [^URL x] 1.207 + (if (= "file" (.getProtocol x)) 1.208 + (output-stream (File. (.getPath x))) 1.209 + (throw (Exception. (str "Can not write to non-file URL <" x ">"))))))) 1.210 +(extend URI 1.211 + Streams 1.212 + (assoc default-streams-impl 1.213 + :input-stream #(input-stream (.toURL ^URI %)) 1.214 + :output-stream #(output-stream (.toURL ^URI %)))) 1.215 +(extend String 1.216 + Streams 1.217 + (assoc default-streams-impl 1.218 + :input-stream #(try 1.219 + (input-stream (URL. %)) 1.220 + (catch MalformedURLException e 1.221 + (input-stream (File. ^String %)))) 1.222 + :output-stream #(try 1.223 + (output-stream (URL. %)) 1.224 + (catch MalformedURLException err 1.225 + (output-stream (File. ^String %)))))) 1.226 +(extend Socket 1.227 + Streams 1.228 + (assoc default-streams-impl 1.229 + :input-stream #(.getInputStream ^Socket %) 1.230 + :output-stream #(output-stream (.getOutputStream ^Socket %)))) 1.231 +(extend *byte-array-type* 1.232 + Streams 1.233 + (assoc default-streams-impl :input-stream #(input-stream (ByteArrayInputStream. %)))) 1.234 +(extend *char-array-type* 1.235 + Streams 1.236 + (assoc default-streams-impl :reader #(reader (CharArrayReader. %)))) 1.237 +(extend Object 1.238 + Streams 1.239 + default-streams-impl) 1.240 + 1.241 +(extend Reader 1.242 + Streams 1.243 + (assoc default-streams-impl :reader #(BufferedReader. %))) 1.244 +(extend BufferedReader 1.245 + Streams 1.246 + (assoc default-streams-impl :reader identity)) 1.247 +(defn- inputstream->reader 1.248 + [^InputStream is] 1.249 + (reader (InputStreamReader. is *default-encoding*))) 1.250 +(extend InputStream 1.251 + Streams 1.252 + (assoc default-streams-impl :input-stream #(BufferedInputStream. %) 1.253 + :reader inputstream->reader)) 1.254 +(extend BufferedInputStream 1.255 + Streams 1.256 + (assoc default-streams-impl 1.257 + :input-stream identity 1.258 + :reader inputstream->reader)) 1.259 + 1.260 +(extend Writer 1.261 + Streams 1.262 + (assoc default-streams-impl :writer #(do (assert-not-appending) 1.263 + (BufferedWriter. %)))) 1.264 +(extend BufferedWriter 1.265 + Streams 1.266 + (assoc default-streams-impl :writer #(do (assert-not-appending) %))) 1.267 +(defn- outputstream->writer 1.268 + [^OutputStream os] 1.269 + (assert-not-appending) 1.270 + (writer (OutputStreamWriter. os *default-encoding*))) 1.271 +(extend OutputStream 1.272 + Streams 1.273 + (assoc default-streams-impl 1.274 + :output-stream #(do (assert-not-appending) 1.275 + (BufferedOutputStream. %)) 1.276 + :writer outputstream->writer)) 1.277 +(extend BufferedOutputStream 1.278 + Streams 1.279 + (assoc default-streams-impl 1.280 + :output-stream #(do (assert-not-appending) %) 1.281 + :writer outputstream->writer)) 1.282 + 1.283 +(defn append-output-stream 1.284 + "Like output-stream but opens file for appending. Does not work on streams 1.285 + that are already open." 1.286 + {:deprecated "1.2"} 1.287 + [x] 1.288 + (binding [*append* true] 1.289 + (output-stream x))) 1.290 + 1.291 +(defn append-writer 1.292 + "Like writer but opens file for appending. Does not work on streams 1.293 + that are already open." 1.294 + {:deprecated "1.2"} 1.295 + [x] 1.296 + (binding [*append* true] 1.297 + (writer x))) 1.298 + 1.299 +(defn write-lines 1.300 + "Writes lines (a seq) to f, separated by newlines. f is opened with 1.301 + writer, and automatically closed at the end of the sequence." 1.302 + [f lines] 1.303 + (with-open [^BufferedWriter writer (writer f)] 1.304 + (loop [lines lines] 1.305 + (when-let [line (first lines)] 1.306 + (.write writer (str line)) 1.307 + (.newLine writer) 1.308 + (recur (rest lines)))))) 1.309 + 1.310 +(defn read-lines 1.311 + "Like clojure.core/line-seq but opens f with reader. Automatically 1.312 + closes the reader AFTER YOU CONSUME THE ENTIRE SEQUENCE." 1.313 + [f] 1.314 + (let [read-line (fn this [^BufferedReader rdr] 1.315 + (lazy-seq 1.316 + (if-let [line (.readLine rdr)] 1.317 + (cons line (this rdr)) 1.318 + (.close rdr))))] 1.319 + (read-line (reader f)))) 1.320 + 1.321 +(defn ^String slurp* 1.322 + "Like clojure.core/slurp but opens f with reader." 1.323 + {:deprecated "1.2"} 1.324 + [f] 1.325 + (with-open [^BufferedReader r (reader f)] 1.326 + (let [sb (StringBuilder.)] 1.327 + (loop [c (.read r)] 1.328 + (if (neg? c) 1.329 + (str sb) 1.330 + (do (.append sb (char c)) 1.331 + (recur (.read r)))))))) 1.332 + 1.333 +(defn spit 1.334 + "Opposite of slurp. Opens f with writer, writes content, then 1.335 + closes f." 1.336 + {:deprecated "1.2"} 1.337 + [f content] 1.338 + (with-open [^Writer w (writer f)] 1.339 + (.write w content))) 1.340 + 1.341 +(defn append-spit 1.342 + "Like spit but appends to file." 1.343 + {:deprecated "1.2"} 1.344 + [f content] 1.345 + (with-open [^Writer w (append-writer f)] 1.346 + (.write w content))) 1.347 + 1.348 +(defn pwd 1.349 + "Returns current working directory as a String. (Like UNIX 'pwd'.) 1.350 + Note: In Java, you cannot change the current working directory." 1.351 + {:deprecated "1.2"} 1.352 + [] 1.353 + (System/getProperty "user.dir")) 1.354 + 1.355 +(defmacro with-out-writer 1.356 + "Opens a writer on f, binds it to *out*, and evalutes body. 1.357 + Anything printed within body will be written to f." 1.358 + [f & body] 1.359 + `(with-open [stream# (writer ~f)] 1.360 + (binding [*out* stream#] 1.361 + ~@body))) 1.362 + 1.363 +(defmacro with-out-append-writer 1.364 + "Like with-out-writer but appends to file." 1.365 + {:deprecated "1.2"} 1.366 + [f & body] 1.367 + `(with-open [stream# (append-writer ~f)] 1.368 + (binding [*out* stream#] 1.369 + ~@body))) 1.370 + 1.371 +(defmacro with-in-reader 1.372 + "Opens a PushbackReader on f, binds it to *in*, and evaluates body." 1.373 + [f & body] 1.374 + `(with-open [stream# (PushbackReader. (reader ~f))] 1.375 + (binding [*in* stream#] 1.376 + ~@body))) 1.377 + 1.378 +(defmulti 1.379 + ^{:deprecated "1.2" 1.380 + :doc "Copies input to output. Returns nil. 1.381 + Input may be an InputStream, Reader, File, byte[], or String. 1.382 + Output may be an OutputStream, Writer, or File. 1.383 + 1.384 + Does not close any streams except those it opens itself 1.385 + (on a File). 1.386 + 1.387 + Writing a File fails if the parent directory does not exist." 1.388 + :arglists '([input output])} 1.389 + copy 1.390 + (fn [input output] [(type input) (type output)])) 1.391 + 1.392 +(defmethod copy [InputStream OutputStream] [^InputStream input ^OutputStream output] 1.393 + (let [buffer (make-array Byte/TYPE *buffer-size*)] 1.394 + (loop [] 1.395 + (let [size (.read input buffer)] 1.396 + (when (pos? size) 1.397 + (do (.write output buffer 0 size) 1.398 + (recur))))))) 1.399 + 1.400 +(defmethod copy [InputStream Writer] [^InputStream input ^Writer output] 1.401 + (let [^"[B" buffer (make-array Byte/TYPE *buffer-size*)] 1.402 + (loop [] 1.403 + (let [size (.read input buffer)] 1.404 + (when (pos? size) 1.405 + (let [chars (.toCharArray (String. buffer 0 size *default-encoding*))] 1.406 + (do (.write output chars) 1.407 + (recur)))))))) 1.408 + 1.409 +(defmethod copy [InputStream File] [^InputStream input ^File output] 1.410 + (with-open [out (FileOutputStream. output)] 1.411 + (copy input out))) 1.412 + 1.413 +(defmethod copy [Reader OutputStream] [^Reader input ^OutputStream output] 1.414 + (let [^"[C" buffer (make-array Character/TYPE *buffer-size*)] 1.415 + (loop [] 1.416 + (let [size (.read input buffer)] 1.417 + (when (pos? size) 1.418 + (let [bytes (.getBytes (String. buffer 0 size) *default-encoding*)] 1.419 + (do (.write output bytes) 1.420 + (recur)))))))) 1.421 + 1.422 +(defmethod copy [Reader Writer] [^Reader input ^Writer output] 1.423 + (let [^"[C" buffer (make-array Character/TYPE *buffer-size*)] 1.424 + (loop [] 1.425 + (let [size (.read input buffer)] 1.426 + (when (pos? size) 1.427 + (do (.write output buffer 0 size) 1.428 + (recur))))))) 1.429 + 1.430 +(defmethod copy [Reader File] [^Reader input ^File output] 1.431 + (with-open [out (FileOutputStream. output)] 1.432 + (copy input out))) 1.433 + 1.434 +(defmethod copy [File OutputStream] [^File input ^OutputStream output] 1.435 + (with-open [in (FileInputStream. input)] 1.436 + (copy in output))) 1.437 + 1.438 +(defmethod copy [File Writer] [^File input ^Writer output] 1.439 + (with-open [in (FileInputStream. input)] 1.440 + (copy in output))) 1.441 + 1.442 +(defmethod copy [File File] [^File input ^File output] 1.443 + (with-open [in (FileInputStream. input) 1.444 + out (FileOutputStream. output)] 1.445 + (copy in out))) 1.446 + 1.447 +(defmethod copy [String OutputStream] [^String input ^OutputStream output] 1.448 + (copy (StringReader. input) output)) 1.449 + 1.450 +(defmethod copy [String Writer] [^String input ^Writer output] 1.451 + (copy (StringReader. input) output)) 1.452 + 1.453 +(defmethod copy [String File] [^String input ^File output] 1.454 + (copy (StringReader. input) output)) 1.455 + 1.456 +(defmethod copy [*char-array-type* OutputStream] [input ^OutputStream output] 1.457 + (copy (CharArrayReader. input) output)) 1.458 + 1.459 +(defmethod copy [*char-array-type* Writer] [input ^Writer output] 1.460 + (copy (CharArrayReader. input) output)) 1.461 + 1.462 +(defmethod copy [*char-array-type* File] [input ^File output] 1.463 + (copy (CharArrayReader. input) output)) 1.464 + 1.465 +(defmethod copy [*byte-array-type* OutputStream] [^"[B" input ^OutputStream output] 1.466 + (copy (ByteArrayInputStream. input) output)) 1.467 + 1.468 +(defmethod copy [*byte-array-type* Writer] [^"[B" input ^Writer output] 1.469 + (copy (ByteArrayInputStream. input) output)) 1.470 + 1.471 +(defmethod copy [*byte-array-type* File] [^"[B" input ^Writer output] 1.472 + (copy (ByteArrayInputStream. input) output)) 1.473 + 1.474 +(defn make-parents 1.475 + "Creates all parent directories of file." 1.476 + [^File file] 1.477 + (.mkdirs (.getParentFile file))) 1.478 + 1.479 +(defmulti 1.480 + ^{:doc "Converts argument into a Java byte array. Argument may be 1.481 + a String, File, InputStream, or Reader. If the argument is already 1.482 + a byte array, returns it." 1.483 + :arglists '([arg])} 1.484 + to-byte-array type) 1.485 + 1.486 +(defmethod to-byte-array *byte-array-type* [x] x) 1.487 + 1.488 +(defmethod to-byte-array String [^String x] 1.489 + (.getBytes x *default-encoding*)) 1.490 + 1.491 +(defmethod to-byte-array File [^File x] 1.492 + (with-open [input (FileInputStream. x) 1.493 + buffer (ByteArrayOutputStream.)] 1.494 + (copy input buffer) 1.495 + (.toByteArray buffer))) 1.496 + 1.497 +(defmethod to-byte-array InputStream [^InputStream x] 1.498 + (let [buffer (ByteArrayOutputStream.)] 1.499 + (copy x buffer) 1.500 + (.toByteArray buffer))) 1.501 + 1.502 +(defmethod to-byte-array Reader [^Reader x] 1.503 + (.getBytes (slurp* x) *default-encoding*)) 1.504 + 1.505 +(defmulti relative-path-string 1.506 + "Interpret a String or java.io.File as a relative path string. 1.507 + Building block for clojure.contrib.java/file." 1.508 + {:deprecated "1.2"} 1.509 + class) 1.510 + 1.511 +(defmethod relative-path-string String [^String s] 1.512 + (relative-path-string (File. s))) 1.513 + 1.514 +(defmethod relative-path-string File [^File f] 1.515 + (if (.isAbsolute f) 1.516 + (throw (IllegalArgumentException. (str f " is not a relative path"))) 1.517 + (.getPath f))) 1.518 + 1.519 +(defmulti ^File as-file 1.520 + "Interpret a String or a java.io.File as a File. Building block 1.521 + for clojure.contrib.java/file, which you should prefer 1.522 + in most cases." 1.523 + {:deprecated "1.2"} 1.524 + class) 1.525 +(defmethod as-file String [^String s] (File. s)) 1.526 +(defmethod as-file File [f] f) 1.527 + 1.528 +(defn ^File file 1.529 + "Returns a java.io.File from string or file args." 1.530 + {:deprecated "1.2"} 1.531 + ([arg] 1.532 + (as-file arg)) 1.533 + ([parent child] 1.534 + (File. ^File (as-file parent) ^String (relative-path-string child))) 1.535 + ([parent child & more] 1.536 + (reduce file (file parent child) more))) 1.537 + 1.538 +(defn delete-file 1.539 + "Delete file f. Raise an exception if it fails unless silently is true." 1.540 + [f & [silently]] 1.541 + (or (.delete (file f)) 1.542 + silently 1.543 + (throw (java.io.IOException. (str "Couldn't delete " f))))) 1.544 + 1.545 +(defn delete-file-recursively 1.546 + "Delete file f. If it's a directory, recursively delete all its contents. 1.547 +Raise an exception if any deletion fails unless silently is true." 1.548 + [f & [silently]] 1.549 + (let [f (file f)] 1.550 + (if (.isDirectory f) 1.551 + (doseq [child (.listFiles f)] 1.552 + (delete-file-recursively child silently))) 1.553 + (delete-file f silently))) 1.554 + 1.555 +(defmulti 1.556 + ^{:deprecated "1.2" 1.557 + :doc "Coerces argument (URL, URI, or String) to a java.net.URL." 1.558 + :arglists '([arg])} 1.559 + as-url type) 1.560 + 1.561 +(defmethod as-url URL [x] x) 1.562 + 1.563 +(defmethod as-url URI [^URI x] (.toURL x)) 1.564 + 1.565 +(defmethod as-url String [^String x] (URL. x)) 1.566 + 1.567 +(defmethod as-url File [^File x] (.toURL x))