I'm writing unit tests with rackunit, like this:
(module+ test
. . .
(test-case ":edge"
(let ([g (make-graph '(:edge ((:node letter a) out)
((:node letter b) in)))])
(check-equal? (all-edges g) (set (set '(a out) '(b in))))))
(test-case ":edge betw refs"
(let ([g (make-graph 'a 'b '(:edge (a out) (b in)))])
(check-equal? (all-edges g) (set (set '(a out) '(b in))))))
. . .
)
When I run the source file in DrRacket and all the tests pass, it prints nothing. It only prints something if there is an error.
When I run raco test <source-file>, it prints:
49 tests passed
but not the number of assertions.
How can I get DrRacket and raco test to print both the number of test cases and the number of assertions?
I'd like to always see both the number of test cases and the number of assertions, because this is a good, quick confirmation of whether a test or assertion that I just added really got run: the number increases from the previous run.
It turns out that the word "test" is slightly overloaded here. To see this, try running the following code with raco test:
#lang racket
(require rackunit)
(define (f x) x)
(check-equal? (f 3) 3)
(check-equal? (f 3) 4)
Note that there are no uses of "test-case" in this code. However, running it at the
command-line produces the output:
raco test: "/tmp/gg.rkt"
--------------------
FAILURE
name: check-equal?
location: gg.rkt:8:0
actual: 3
expected: 4
--------------------
1/2 test failures
That is, in the absence of the test-case and test-suite forms, each use of check-equal? is considered to be a test. Indeed, I think I would claim that this lightweight usage is the more common one, and I should note that it is possible to associate messages with these uses of check-equal?.
This doesn't directly answer your question, but I think it explains why the feature you're looking for isn't (AFAICT) currently implemented. If you want something like this, I think your best bet is to implement it yourself. For a more authoritative answer, I would pose this question on the racket mailing list.
Related
I'm currently using Leiningen to learn Clojure and I'm confused about the requirement of doall for running this function:
;; take a function (for my purposes, println for output formatting) and repeat it n times
(defn repeat [f n] (for [i (range n)] (f)))
(repeat println 2) works just fine in an REPL session, but not when running with lein run unless I include the doall wrapper. (doall (repeat println 2)) works and I'm curious why. Without it, lein run doesn't show the two blank lines in the output.
I also have:
(defmacro newPrint1 [& args] `'(println ~args))
(defmacro newPrint2 [& args] `'(println ~#args))
The first function I thought of myself. The next two macros are examples from a tutorial video I'm following on Udemy. Even if I wrap the macro calls with doall, such as (doall (newPrint1 1 2 3)), lein run produces no output, but (newPrint1 1 2 3) in a terminal REPL session produces the desired output of (clojure.core/println (1 2 3)) as it does in the video tutorial. Why doesn't doall work here?
for creates a lazy sequence. This lazy sequence is returned. The P in REPL (read eval Print loop) prints the sequence, thus realizing it. For realizing, the code to produce each element is run.
If you do not use the sequence, it is not realized, so the code is never run. In non-interactive use, this is likely the case. As noted, doall forces realization.
If you want to do side-effects, doseq is often better suited than for.
I'm trying to write a procedure Huffman-leaves; the procedure returns a list of pairs from a created huffman tree.
Example on how it runs
(huffman-leaves sample-tree)
->((A . 8) (C . 5) (B . 1) (D . 1))
What I've comed up with but got writers block...
(define (huffman-leaves tree)
(define (huffman-get-pairs current-branch pairs)
(if (or (null? tree) (null? current-branch))
pairs
(let ((next-branch
(get-branch (car current-branch) current-branch)))
(not (member? next-branch pairs)
(if (leaf? next-branch)
(cons (append pairs next-branch)
(display pairs)
(huffman-get-pairs (cadr current-branch) pairs))
(huffman-get-pairs next-branch pairs))))))
(huffman-get-pairs tree '()))
(member? item 'list) #if item in list return #t else #false
I know that I'm doing something wrong but I can't see it.
How can I stop a search in a huffman-tree in scheme? Any tip that I should be doing different?
I recommend:
Write a data definition for Huffman Tree
Make example input huffman trees, encoded according to your data definition from step 1, and expected outputs (lists of leaves, in this case).
Follow the design recipe to build a basic template for the huffman-leaves function.
Fill in the ... in your template according to the examples you built from step 2.
Translate your examples from step 2. into tests, and test your code from step 4.
Sorry if the above seems vague, but it is the best advice I can give with the level of detail (or lack thereof) you have supplied in this question thus far. If you can provide answers for the steps above, and say explicitly which step you are blocked on, then we can help you get over your writers block in a more systematic way.
If you prefer real code, here is one direction you could go in to make a very generic solution for your problem:
;; make-visitor : (X -> Y) (X -> [Listof X]) (Y [Listof Z] -> Z) -> Z
;; Very generic descend+map+recombine routine
;; (note X, Y, Z are implicitly universally quantified above).
(define (make-visitor transform children combine)
(lambda (x)
(let rec ((x x)) ;; rec : X -> Z
(combine (transform x)
(map rec (children x))))))
;; ... the hard bit is coming up with the appropriate lambda
;; expressions for `transform`, `children`, and `combine` above.
(define leaves
(make-visitor (lambda (x) ...)
(lambda (x) ...)
(lambda (y zs) ...)))
I don't actually recommend trying to jump directly to a solution of this form; you will be better off if you try to follow the design recipe and make a direct solution to your problem. But once you have done that, it can be an educational exercise to see if you can retrofit your own solution onto the generic routine above.
I've been trying to get a simple reg-ex working in Clojure to test a string for some SQL reserved words (select, from, where etc.) but just can't get it to work:
(defn areserved? [c]
(re-find #"select|from|where|order by|group by" c))
(I split a string by spaces then go over all the words)
Help would be greatly appreciated,
Thanks!
EDIT: My first goal (after only reading some examples and basic Clojure materials) is to parse a string and return for each part of it (i.e. words) what "job" they have in the statement (a reserved word, a string etc.).
What I have so far:
(use '[clojure.string :only (join split)])
(defn isdigit? [c]
(re-find #"[0-9]" c))
(defn isletter? [c]
(re-find #"[a-zA-Z]" c))
(defn issymbol? [c]
(re-find #"[\(\)\[\]!\.+-><=\?*]" c))
(defn isstring? [c]
(re-find #"[\"']" c))
(defn areserved? [c]
(if (re-find #"select|from|where|order by|group by" c)
true
false))
(defn what-is [token]
(let [c (subs token 0 1)]
(cond
(isletter? c) :word
(areserved? c) :reserved
(isdigit? c) :number
(issymbol? c) :symbol
(isstring? c) :string)))
(defn checkr [token]
{:token token
:type (what-is token)})
(defn goparse [sql-str]
(map checkr (.split sql-str " ")))
Thanks for all the help guys! it's great to see so much support for such a relatively new language (at least for me :) )
I'm not entirely sure what you want exactly, but here's a couple of variations to coerce your first regex match to a boolean:
(defn areserved? [c]
(string?
(re-find #"select|from|where|order by|group by"c)))
(defn areserved? [c]
(if (re-find #"select|from|where|order by|group by"c)
true
false))
UPDATE in response to question edit:
Thanks for posting more code. Unfortunately there are a number of issues here that we could
try to address by patching your existing code in a simplistic and naïve fashion, but it will
only get you so far, before you hit the next problem with this single iteration approach.
#alex is correct, that your areserved? method will fail to match order by if you have already
split your string by white space. That said, a simple fix is to treat order and by as separate keywords (which they are, even though they always appear together).
The next issue is that the areserved? function will match keywords in a string, but you are dispatching it against a character in the what-is function. You nearly always get a match in your cond for isletter?, so you will everything is marked as a 'word'.
All in all, it looks like you are trying to do too much work in a single application of map.
I'm not sure if you are just doing this for fun to play with Clojure (which is admirable - keep going!), in which case, maybe it doesn't matter if you press on with this simple parsing approach... you'll definitely learn something; but if you would like to take it further and parse SQL more successfully, then I would suggest that you may find it helpful to to read a little on Lexing, Parsing and building Abstract Syntax Trees (AST).
Brian Carper has written about using the Java parser generator "ANTLR" from Clojure - it's a few years old, but might be worth looking at.
You also might be able to get some transferrable ideas from this chapter from the F# programming book on lexing and parsing SQL.
My code is a mess many long lines in this language like the following
(defn check-if-installed[x] (:exit(sh "sh" "-c" (str "command -v " x " >/dev/null 2>&1 || { echo >&2 \"\"; exit 1; }"))))
or
(def Open-Action (action :handler (fn [e] (choose-file :type :open :selection-mode :files-only :dir ListDir :success-fn (fn [fc file](setup-list file)))) :name "Open" :key "menu O" :tip "Open spelling list"))
which is terrible. I would like to format it like so
(if (= a something)
(if (= b otherthing)
(foo)))
How can I beautify the source code in a better way?
The real answer hinges on whether you're willing to insert the newlines yourself. Many systems
can indent the lines for you in an idiomatic way, once you've broken it up into lines.
If you don't want to insert them manually, Racket provides a "pretty-print" that does some of what you want:
#lang racket
(require racket/pretty)
(parameterize ([pretty-print-columns 20])
(pretty-print '(b aosentuh onethunoteh (nte huna) oehnatoe unathoe)))
==>
'(b
aosentuh
onethunoteh
(nte huna)
oehnatoe
unathoe)
... but I'd be the first to admit that inserting newlines in the right places is hard, because
the choice of line breaks has a lot to do with how you want people to read your code.
I use Clojure.pprint often for making generated code more palatable to humans.
it works well for reporting thought it is targeted at producing text. The formatting built into the clojure-mode emacs package produces very nicely formatted Clojure if you put the newlines in your self.
Now you can do it with Srefactor package.
Some demos:
Formatting whole buffer demo in Emacs Lisp (applicable in Common Lisp as well).
Transform between one line <--> Multiline demo
Available Commands:
srefactor-lisp-format-buffer: format whole buffer
srefactor-lisp-format-defun: format current defun cursor is in
srefactor-lisp-format-sexp: format the current sexp cursor is in.
srefactor-lisp-one-line: turn the current sexp of the same level into one line; with prefix argument, recursively turn all inner sexps into one line.
Scheme variants are not as polished as Emacs Lisp and Common Lisp yet but work for simple and small sexp. If there is any problem, please submit an issue report and I will be happy to fix it.
I recently started reading Paul Grahams 'On Lisp', and learning learning clojure along with it, so there's probably some really obvious error in here, but I can't see it: (its a project euler problem, obviously)
(ns net.projecteuler.problem31)
(def paths (ref #{}))
; apply fun to all elements of coll for which pred-fun returns true
(defn apply-if [pred-fun fun coll]
(apply fun (filter pred-fun coll)))
(defn make-combination-counter [coin-values]
(fn recurse
([sum] (recurse sum 0 '()))
([max-sum current-sum coin-path]
(if (= max-sum current-sum)
; if we've recursed to the bottom, add current path to paths
(dosync (ref-set paths (conj #paths (sort coin-path))))
; else go on recursing
(apply-if (fn [x] (<= (+ current-sum x) max-sum))
(fn [x] (recurse max-sum (+ x current-sum) (cons x coin-path)))
coin-values)))))
(def count-currency-combinations (make-combination-counter '(1 2 5 10 20 50 100 200)))
(count-currency-combinations 200)
When I run the last line in the REPL, i get the error:
<#CompilerException java.lang.IllegalArgumentException: Wrong number of args passed to: problem31$eval--25$make-combination-counter--27$recurse--29$fn (NO_SOURCE_FILE:0)>
Apart from the question where the error is, the more interesting question would be: How would one debug this? The error message isn't very helpful, and I haven't found a good way to single-step clojure code, and I can't really ask on stack overflow every time I have a problem.
Three tips that might make your life easier here:
Wrong number of args passed to: problem31$eval--25$make-combination-counter--27$recurse--29$fn (NO_SOURCE_FILE:0)>
Tells you roughly where the error occurred: $fn at the end there means anonymous function and it tells you it was declared inside recurse, which was declared inside make-combination-counter. There are two anonymous functions to choose from.
If you save your source-code in a file and execute it as a script it will give you a full stack trace with the line numbers in the file.
at net.projecteuler.problem31$apply_if__9.invoke(problem31.clj:7)
Note you can also examine the last exception and stack trace from within the REPL by examining *e eg: (.stackTrace *e) The stack trace is at first quite daunting because it throws up all the Java internals. You need to learn to ignore those and just look for the lines that refer to your code. This is pretty easy in your case as they all start with net.projecteuler
You can name your anonymous functions to help more quickly identify them:
(fn check-max [x] (<= (+ current-sum x) max-sum))
In your case using all this info you can see that apply-if is being passed a single argument function as fun. Apply does this (f [1 2 3]) -> (f 1 2 3). From your comment what you want is map. (map f [1 2 3]) -> (list (f 1) (f 2) (f 3)). When I replace apply with map the program seems to work.
Finally, if you want to examine values you might want to look into clojure-contrib.logging which has some helpers to this effect. There is a spy macro which allows you to wrap an expression, it will return exactly the same expression so it does not affect the result of your function but will print out EXPR = VALUE, which can be handy. Also on the group various people have posted full tracing solutions. And there is always the trusty println. But the key skill here is being able to identify precisely what blew up. Once you know that it is usually clear why, but sometimes printouts are needed when you can't tell what the inputs are.
dont have a REPL on me though it looks like:
(defn apply-if [pred-fun fun coll]
(apply fun (filter pred-fun coll)))
takes a list like '(1 2 3 4 5) filters some of them out '(1 3 5)
and then creates a function call like (fun 1 3 5)
and it looks like it is being called (apply-if (fn [x] with a function that wants to receive a list of numbers as a single argument.
you could change the apply-if function to just pass call to the fun (with out the apply) or you could change the call to it to take a function that takes an arbitrary number of arguments.