Why learning Clojure, I sometimes need to see what a function does at each step. For example:
(defn kadane [coll]
(let [pos+ (fn [sum x] (if (neg? sum) x (+ sum x)))
ending-heres (reductions pos+ 0 coll)]
(reduce max ending-heres)))
Should I insert println here and there (where, how); or is there a suggested workflow/tool?
This may not be what you're after at the level of a single function (see Charles Duffy's comment below), but if you wanted to do get an overview of what's going on at the level of a namespace (or several), you could use tools.trace (disclosure: I'm a contributor):
(ns foo.core)
(defn foo [x] x)
(defn bar [x] (foo x))
(in-ns 'user) ; standard REPL namespace
(require '[clojure.tools.trace :as trace])
(trace/trace-ns 'foo.core)
(foo.core/bar 123)
TRACE t20387: (foo.core/bar 123)
TRACE t20388: | (foo.core/foo 123)
TRACE t20388: | => 123
TRACE t20387: => 123
It won't catch inner functions and such (as pointed out by Charles), and might be overwhelming with large code graphs, but when exploring small-ish code graphs it can be quite convenient.
(It's also possible to trace individually selected Vars if the groups of interest aren't perfectly aligned with namespaces.)
If you use Emacs with CIDER as most Clojurians do, you already have a built-in debugger:
https://docs.cider.mx/cider/debugging/debugger.html
Chances are your favorite IDE/Editor has something built-in or a plugin already.
There is also (in no particular order):
spyscope
timbre/spy
tupelo/spyx
sayid
tools.trace
good old println
I would look at the above first. However there were/are other possibilities:
https://gist.github.com/ato/252421
https://github.com/philoskim/debux
https://github.com/pallet/ritz/tree/develop/nrepl-core
https://github.com/hozumi/eyewrap
probably many more
Also, if the function is simple enough you can add defs at development-time to peek inside the bindings at a given time inside your function.
Sayid is a tool presented at Clojure Conj 2016 that's directly appropriate to the purpose and comes with an excellent Emacs plugin. See the talk at which it was presented.
To see inside invocations of transient functions, see ws-add-inner-trace-fn (previously, ws-add-deep-trace-fn).
I frequently use the spyx and related functions like spy-let from the Tupelo library for this purpose:
(ns tst.clj.core
(:require [tupelo.core :as t] ))
(t/refer-tupelo)
(defn kadane [coll]
(spy-let [ pos+ (fn [sum x] (if (neg? sum) x (+ sum x)))
ending-heres (reductions pos+ 0 coll) ]
(spyx (reduce max ending-heres))))
(spyx (kadane (range 5)))
will produce output:
pos+ => #object[tst.clj.core$kadane$pos_PLUS___21786 0x3e7de165 ...]
ending-heres => (0 0 1 3 6 10)
(reduce max ending-heres) => 10
(kadane (range 5)) => 10
IMHO it is hard to beat a simple println or similar for debugging. Log files are also invaluable as you get closer to production.
Related
I defined a generic function taking 2 arguments:
(defgeneric interact (a b))
The order of the arguments should not be important, so (interact x y) and (interact y x) should be the same, but I don't want to define two methods that do the same for every combination of different objects.
A Method-Combination of this type should help:
(defmethod interact :around (a b)
(if (some-function a b)
;;some-function has to be true if (eq (class-of a) (class-of b))
;;else (some-function a b) is (not (some-function b a))
;;similar #'<=
(call-next method)
(interact b a))
But I would have to know #'some-function and be able to know the type of the arguments I have to define.
Edit: both proposed approaches have a few limitations discussed in the comments below. Please read them before using this answer!
Can I suggest two options - a working but hacky option for when you only have two arguments, and a vaguely sketched out generic approach which I think should work but I haven't written:
Option 1:
(defparameter *in-interact-generic-call* nil)
(defgeneric interact (x y))
(defmethod interact ((x T) (y T))
; this can be called on pretty much anything
(if *in-interact-generic-call*
(cause-some-kind-of-error) ; Replace this with a more sensible error call
(let ((*in-interact-generic-call* T))
(interact y x))))
(defmethod interact ((x integer) (y string))
; example
(print x )(prin1 y))
(interact 5 "hello") ; should print 5 "hello"
(interact "hello" 5) ; should print 5 "hello"
;(interact "hello" "hello") ; should cause an error
Essentially the idea is to define a generic function which always matches anything, use it to try to swap the arguments (to see if that matches anything better) and if it's already swapped the arguments then to raise some kind of error (I've not really done that right here).
Option 2
Define the generic function as something like interact-impl. Actually call the standard function (defined by defun) interact.
In interact, define a loop over all permutations of the order of your arguments. For each permutation try calling interact-impl (e.g. using (apply #'interact-impl current-permutation).)
At least in sbcl, no matching arguments gives me a simple-error. You probably would want to do a more detailed check that it's actually the right error. Thus the code in interact looks something like
; completely untested!
(do (all-permutations all-permutations (cdr all-permutations))
(...) ; some code to detect when all permutations are exhausted and raise an error
(let (current-permutation (first all-permutations))
(handler-case
(return (apply #'interact-impl current-permutation))
(simple-error () nil)) ; ignore and try the next option
)
)
So what you are looking for is an arbitrary linear order on the class objects.
How about string order on class names?
(defun class-less-p (a b)
"Lexicographic order on printable representation of class names."
(let* ((class-a (class-of a))
(name-a (symbol-name class-a))
(pack-a (package-name (symbol-package name-a)))
(class-b (class-of b))
(name-b (symbol-name class-b))
(pack-b (package-name (symbol-package name-b))))
(or (string< pack-a pack-b)
(and (string= pack-a pack-b)
(string<= name-a name-b)))))
try to figure out how to use "append" in Scheme
the concept of append that I can find like this:
----- part 1: understanding the concept of append in Scheme-----
1) append takes two or more lists and constructs a new list with all of their elements.
2) append requires that its arguments are lists, and makes a list whose elements are the elements of those lists. it concatenates the lists it is given. (It effectively conses the elements of the other lists onto the last list to create the result list.)
3) It only concatenates the top-level structure ==> [Q1] what does it mean "only concatenates the top-level"?
4) however--it doesn't "flatten" nested structures.
==> [Q2] what is "flatten" ? (I saw many places this "flatten" but I didn't figure out yet)
==> [Q3] why append does not "flatten" nested structures.
---------- Part 2: how to using append in Scheme --------------------------------
then I looked around to try to use "append" and I saw other discussion
based on the other discussion, I try this implementation
[code 1]
(define (tst-foldr-append lst)
(foldr
(lambda (element acc) (append acc (list element)))
lst
'())
)
it works, but I am struggling to understand that this part ...(append acc (list element)...
what exactly "append" is doing in code 1, to me, it just flipping.
then why it can't be used other logics e.g.
i) simply just flip or
iii).... cons (acc element).....
[Q4] why it have to be "append" in code 1??? Is that because of something to do with foldr ??
again, sorry for the long question, but I think it is all related.
Q1/2/3: What is this "flattening" thing?
Scheme/Lisp/Racket make it very very easy to use lists. Lists are easy to construct and easy to operate on. As a result, they are often nested. So, for instance
`(a b 34)
denotes a list of three elements: two symbols and a number. However,
`(a (b c) 34)
denotes a list of three elements: a symbol, a list, and a number.
The word "flatten" is used to refer to the operation that turns
`(3 ((b) c) (d (e f)))
into
`(3 b c d e f)
That is, the lists-within-lists are "flattened".
The 'append' function does not flatten lists; it just combines them. So, for instance,
(append `(3 (b c) d) `(a (9)))
would produce
`(3 (b c) d a (9))
Another way of saying it is this: if you apply 'append' to a list of length 3 and a list of length 2, the result will be of length 5.
Q4/5: Foldl really has nothing to do with append. I think I would ask a separate question about foldl if I were you.
Final advice: go check out htdp.org .
Q1: It means that sublists are not recursively appended, only the top-most elements are concatenated, for example:
(append '((1) (2)) '((3) (4)))
=> '((1) (2) (3) (4))
Q2: Related to the previous question, flattening a list gets rid of the sublists:
(flatten '((1) (2) (3) (4)))
=> '(1 2 3 4)
Q3: By design, because append only concatenates two lists, for flattening nested structures use flatten.
Q4: Please read the documentation before asking this kind of questions. append is simply a different procedure, not necessarily related to foldr, but they can be used together; it concatenates a list with an element (if the "element" is a list the result will be a proper list). cons just sticks together two things, no matter their type whereas append always returns a list (proper or improper) as output. For example, for appending one element at the end you can do this:
(append '(1 2) '(3))
=> '(1 2 3)
But these expressions will give different results (tested in Racket):
(append '(1 2) 3)
=> '(1 2 . 3)
(cons '(1 2) '(3))
=> '((1 2) 3)
(cons '(1 2) 3)
=> '((1 2) . 3)
Q5: No, cons will work fine here. You wouldn't be asking any of this if you simply tested each procedure to see how they work. Please understand what you're using by reading the documentation and writing little examples, it's the only way you'll ever learn how to program.
Let's say I have a program like this:
(define (foo x)
(local
((define y (- x 1)))
(* x y)))
(foo 3)
I want to be able to open a REPL between lines 3 and 4, such that I can explore (and possibly modify) the values of x and y by executing arbitrary statements.
To do this in Ruby, I would take the equivalent program:
def foo(x)
lambda {
y = x - 1
x * y
}.call
end
puts (foo 3)
And modify it by adding a call to pry to give me a nicely-scoped repl where I want it:
require 'pry'
def foo(x)
lambda {
y = x - 1
binding.pry
x * y
}.call
end
puts (foo 3)
To do it in js, I would run this program under Firebug and just put a breakpoint on line 4:
foo = function(x) {
return (function(){
var y = x - 1;
return x * y;
})();
};
console.log(foo(3));
And then I could explore stuff in the evaluation window.
Is there anything I can do to get this in Racket? The closest I've found is DrScheme's debugger, but that just presents all the values of the current scope, it doesn't let you explore them in a REPL as far as I can see.
This isn't answering your original question, it's in response to your comment about making your own. I thought that was a really interesting idea so I explored it. What I was able to figure out:
Let's say you want this to work:
(define top-x 10)
(define (f)
(for ([i 10])
(displayln i)
(when (= i 5)
(pry)))) ; <= drop into a REPL here, resume after exiting REPL
A first attempt at pry:
(define (pry)
(let loop ()
(display "PRY> ")
(define x (read))
(unless (or (eof-object? x) (equal? x '(unquote exit)))
(pretty-print (eval x))
(loop))))
This seems to work:
> (f)
0
1
2
PRY> (+ 10 10)
20
PRY> ,exit
3
4
>
But although it lets you access Racket functions like +, you can't access even your top-level variables like top-x:
> (f)
0
1
2
PRY> top-x
; top-x: undefined;
; cannot reference undefined identifier
You can get the top-level stuff by giving eval access to the current namespace, as explained here. So pry needs a namespace argument:
(define (pry ns)
(let loop ()
(display "PRY> ")
(define x (read))
(unless (or (eof-object? x) (equal? x '(unquote exit)))
(pretty-print (eval x ns)) ; <---
(loop))))
And to get that argument you need this incantation to your debugee file:
(define-namespace-anchor a) ; <---
(define ns (namespace-anchor->namespace a)) ; <---
(define top-x 10)
(define (f)
(for ([i 5])
(displayln i)
(when (= i 2)
(pry ns)))) ; <---
Now the REPL can see and change top-x:
> (f)
0
1
2
PRY> top-x
10
PRY> (set! top-x 20)
#<void>
PRY> top-x
20
PRY> ,exit
3
4
>
Cool! But it can't change the local variable, i:
> (f)
0
1
2
PRY> i
; i: undefined;
; cannot reference an identifier before its definition
Shoot. The reason why is explained here.
You might imagine that even though eval cannot see the local bindings in broken-eval-formula, there must actually be a data structure mapping x to 2 and y to 3, and you would like a way to get that data structure. In fact, no such data structure exists; the compiler is free to replace every use of x with 2 at compile time, so that the local binding of x does not exist in any concrete sense at run-time. Even when variables cannot be eliminated by constant-folding, normally the names of the variables can be eliminated, and the data structures that hold local values do not resemble a mapping from names to values.
You might say, OK, but in that case...
How does DrRacket provide a debugger?
From what I was able to figure out, DrRacket does this by annotating the syntax before evaluating the program. From drracket/gui-debugger/annotator.rkt:
;; annotate-stx inserts annotations around each expression that introduces a
;; new scope: let, lambda, and function calls. These annotations reify the
;; call stack, and allows to list the current variable in scope, look up
;; their value, as well as change their value. The reified stack is accessed
;; via the CURRENT-CONTINUATION-MARKS using the key DEBUG-KEY
So I think that would be the jumping-off point if you wanted to tackle this.
In the DrRacked IDE you have a DEBUG Q >| button. You can step through your program or you can do as you said in other languages, press right mouse button at the expression you want to investigate and either choose continue to this point for once only or pause at this point for a breakpoint, then press GO > to run the program.
To inspect or change x, put you mouse pointer over it and use right mouse button. To change you choose (set! x ...) in the menu.
As for the in language repl, You could make your own (pry) to start a repl in there and in Common Lisp you could have just signaled an error to get to the nice debugger.
I've been playing around with the Is Clojure is Still Fast? (and prequel Clojure is Fast) code. It seemed unfortunate that inlining the differential equation (f) is one of the steps taken to improving performance. The cleanest/fastest thing I've been able to come up without doing this is the following:
; As in the referenced posts, for giving a rough measure of cycles/iteration (I know this is a very rough
; estimate...)
(def cpuspeed 3.6) ;; My computer runs at 3.6 GHz
(defmacro cyclesperit [expr its]
`(let [start# (. System (nanoTime))
ret# ( ~#expr (/ 1.0 ~its) ~its )
finish# (. System (nanoTime))]
(println (int (/ (* cpuspeed (- finish# start#)) ~its)))))
;; My solution
(defn f [^double t ^double y] (- t y))
(defn mysolveit [^double t0 ^double y0 ^double h ^long its]
(if (> its 0)
(let [t1 (+ t0 h)
y1 (+ y0 (* h (f t0 y0)))]
(recur t1 y1 h (dec its)))
[t0 y0 h its]))
; => 50-55 cycles/it
; The fastest solution presented by the author (John Aspden) is
(defn faster-solveit [^double t0 ^double y0 ^double h ^long its]
(if (> its 0)
(let [t1 (+ t0 h)
y1 (+ y0 (* h (- t0 y0)))]
(recur t1 y1 h (dec its)))
[t0 y0 h its]))
; => 25-30 cycles/it
The type hinting in my solution helps quite a bit (it's 224 cycles/it without type hinting on either f or solveit), but it's still nearly 2x slower than the inlined version. Ultimately this performance is still pretty decent, but this hit is unfortunate.
Why is there such a performance hit for this? Is there a way around it? Are there plans to find ways of improvingthis? As pointed out by John in the original post, it seems funny/unfortunate for function calls to be inefficient in a functional language.
Note: I'm running Clojure 1.5 and have :jvm-opts ^:replace [] in a project.clj file so that I can use lein exec/run without it slowing things down (and it will if you don't do this I discovered...)
Benchmarking in the presence of a JIT compiler is tricky; you really must allow for a warm-up period, but then you also can't just run it all in a loop, since it may then be proved a no-op and optimized away. In Clojure, the usual solution is to use Hugo Duncan's Criterium.
Running a Criterium benchmark for (solveit 0.0 1.0 (/ 1.0 1000000) 1000000) for both versions of solveit results in pretty much exactly the same timings on my machine (mysolveit ~3.44 ms, faster-solveit ~3.45 ms). That's in a 64-bit JVM run with -XX:+UseConcMarkSweepGC, using Criterium 0.4.2 (criterium.core/bench). Presumably HotSpot just inlines f. In any case, there's no performance hit at all.
Adding to the already good answers, the JVM JIT most often does inline the primitive function calls when warmed up, and in this case, when you bench it with a warmed JIT you see the same results. Just wanted to say Clojure also has an inlining feature though for cases where that yields benefits.
(defn f
{:inline-arities #{2}
:inline (fn [t y] `(- (double ~t) (double ~y)))}
^double [^double t ^double y]
(- t y))
Now Clojure will compile away the calls to f, inlining the function at compile time. Whereas the JIT will inline the function at runtime as needed otherwise.
Also note that I added a ^double type hint to the return of f, if you don't do that, it gets compiled to return Object, and a cast needs to be added, I'm not sure if that really affects performance much, but if you want a fully primitive function that takes primitives and return primitives you need to type hint the return as well.
i have a simple clojure syntax problem (bc i am new to the language). for both examples i have a list lst of (1 2 3 4):
in Lisp i can write:
=>`(first of list is ,(first lst))
(first of list is 1)
in Clojure, if i write the same thing (with the language translation of , to ~ as i THOUGHT i read somewhere) i get:
=>'(first of list is ~(first lst))
(first of list is (clojure.core/unquote (first lst)))
i was hoping i can do what i want to in Clojure as well, and that i just have the syntax wrong. all the examples i find though have functions first and use a ` (backtick). i dont want to call a function like:
`(my-function ~(first lst))
i just want to return '(some list with ,(first lst) replaced in it)
can i do such a thing in Clojure?
EDIT: i gave a poor example seeing as my ACTUAL problem dealt with strings. let me try another example...
=>(def color-lst '(red green blue))
what i wanted to return was:
=>`(the color i want is ~(first color-lst))
this yeilded all the strange returns i saw. the other way to do this is
=>(format "the color i want is %s" (first color-lst))
this is how i solved my problem.
Even if your problem is solved, there are some fundamental differences between CL and Clojure worth mentioning:
The main difference concerning symbols in backquotes between CL and Clojure is, that Clojure resolves quasiquoted symbols; yielding a namespace qualified symbol (take a look at the reader section of the Clojure docs):
user> `foo
user/foo
So, in CL:
CL-USER> (let ((list '(foo bar baz)))
`(first is ,(first list)))
(FIRST IS FOO)
But in Clojure:
user> (let [lst '(foo bar baz)]
`(first is ~(first lst)))
(clojure.core/first user/is foo)
In order to get a non-qualified symbol in Clojure (within backquotes), you'd have to use something like this:
user> `~'foo
foo
So, to get the same result as the CL version (ignoring readtable-case), you'd have to use:
user> (let [lst '(foo bar baz)]
`(~'first ~'is ~(first lst)))
(first is foo)
It's slightly unclear to me what you mean by "first of list is" in your code:
'(first of list is ,(first lst))
But if you meant by that just a placeholder for the beginning of the list, then the following should work fine (make sure to use backtick!):
`(1 2 3 ~(first [1 2]))
=> (1 2 3 1)
Alternatively, using quote will result in the following (which seems to be your problem):
'(1 2 3 ~(first [1 2]))
=> (1 2 3 (clojure.core/unquote (first [1 2])))
found another way. perhaps the whole time i was just not doing things the 'Clojure' way?
(formate "first of list is %d" (first lst)) yeilds what i was looking for.
i think it was partly my fault in the problem description, i gave a bad example. it seems the problem arose bc i was using strings (possibly improperly?) in the list. that and 'first' is also an acceptable function call. all of that confused the issue i believe.