For the following line:
(random 9 current-pseudo-random-generator)
I'm getting the following error:
. . random: contract violation
expected: (or/c (integer-in 1 4294967087) pseudo-random-generator?)
given: #<procedure:current-pseudo-random-generator>
>
What's wrong?
current-pseudo-random-generator is a parameter, so you must use it like
(random 9 (current-pseudo-random-generator))
By default, random will use that automatically so you could simplify your example to (random 9).
Related
I'm trying to create a logic in google sheets. But getting the error "Wrong number of arguments to IF. Expected between 2 and 3 arguments, but received 4 arguments."
I have tried this formula. It works if the number is upto 45000. It shows error if the number goes byound that.
IF(B4<20000, 0, IF(B4>20000, ROUND(IF(B4<34286,685,IF(B4<45714,1715,IF(B4<57143,3200,IF(B4<68571,5140,IF(B4>68571,6860,0)),0))))))
use:
=IF(B4<20000, 0,
IF(B4>20000, ROUND(
IF(B4<34286, 685,
IF(B4<45714, 1715,
IF(B4<57143, 3200,
IF(B4<68571, 5140,
IF(B4>68571, 6860, 0))))), 0)))
Preamble
I was looking throught the source code in clojure.core for no particular reason.
I started reading defmacro ns, here is the abridged source:
(defmacro ns
"...docstring..."
{:arglists '([name docstring? attr-map? references*])
:added "1.0"}
[name & references]
(let [...
; Argument processing here.
name-metadata (meta name)]
`(do
(clojure.core/in-ns '~name)
~#(when name-metadata
`((.resetMeta (clojure.lang.Namespace/find '~name) ~name-metadata)))
(with-loading-context
~#(when gen-class-call (list gen-class-call))
~#(when (and (not= name 'clojure.core) (not-any? #(= :refer-clojure (first %)) references))
`((clojure.core/refer '~'clojure.core)))
~#(map process-reference references))
(if (.equals '~name 'clojure.core)
nil
(do (dosync (commute ##'*loaded-libs* conj '~name)) nil)))))
Looking Closer
And then trying to read it I saw some strange macro patterns, in particular we can look at:
~#(when name-metadata
`((.resetMeta (clojure.lang.Namespace/find '~name) ~name-metadata)))
The clojure.core version
Here is a standalone working extraction from the macro:
(let [name-metadata 'name-metadata
name 'name]
`(do
~#(when name-metadata
`((.resetMeta (clojure.lang.Namespace/find '~name) ~name-metadata)))))
=> (do (.resetMeta (clojure.lang.Namespace/find (quote name)) name-metadata))
When I ran this could I couldn't help but wonder why there is a double list at the point `((.resetMeta.
My version
I found that by just removing the unquote-splicing (~#) the double list was unnecessary. Here is a working standalone example:
(let [name-metadata 'name-metadata
name 'name]
`(do
~(when name-metadata
`(.resetMeta (clojure.lang.Namespace/find '~name) ~name-metadata))))
=> (do (.resetMeta (clojure.lang.Namespace/find (quote name)) name-metadata))
My Question
Thus, why does clojure.core choose this seemingly extraneous way of doing things?
My Own Thoughts
Is this an artifact of convention?
Are there other similar instances where this is used in more complex ways?
~ always emits a form; ~# can potentially emit nothing at all. Thus sometimes one uses ~# to splice in a single expression conditionally:
;; always yields the form (foo x)
;; (with x replaced with its macro-expansion-time value):
`(foo ~x)`
;; results in (foo) is x is nil, (foo x) otherwise:
`(foo ~#(if x [x]))
That's what's going on here: the (.resetMeta …) call is emitted within the do form that ns expands to only if name-metadata is truthy (non-false, non-nil).
In this instance, it doesn't really matter – one could use ~, drop the extra brackets and accept that the macroexpansion of an ns form with no name metadata would have an extra nil in the do form. For the sake of a prettier expansion, though, it makes sense to use ~# and only emit a form to handle name metadata when it is actually useful.
This code works, printing the rows in the given table:
(defn count-extreferences-subset [config]
(let [emr-dbs (:emr-databases config)]
(println "Counting external references: " emr-dbs)
(jdbc/with-db-connection [dbconn (:db-spec (first emr-dbs))]
(let [q "SELECT * FROM LOCREG"
rs (jdbc/query dbconn [q])]
(dorun (map println rs))))))
According to the documentation in clojure.jdbc, this should also work, but should print the rows as the result set is realized (preventing memory overflow for large result sets):
(defn count-extreferences-subset [config]
(let [emr-dbs (:emr-databases config)]
(println "Counting external references: " emr-dbs)
(jdbc/with-db-connection [dbconn (:db-spec (first emr-dbs))]
(let [q "SELECT * FROM LOCREG"
_ (jdbc/query dbconn [q] {:row-fn println})]))))
However this fails at run-time with the following exception:
java.lang.IllegalArgumentException: No value supplied for key: {:row-fn #object[clojure.core$println 0x46ed7a0e "clojure.core$println#46ed7a0e"]}
Any idea why the use of the :row-fn option is failing?
I believe the curly braces are the problem. Your code should follow the following pattern:
(jdbc/query db-spec
["select name, cost from fruit where cost = 12"]
:row-fn add-tax)
You can fine more information in The Clojure Cookbook. I highly recommend buying a copy!
I seem to have a case of disappearing items after invoking sort! on a list of strings:
(I have derived this code from Autogen template that I was working on.)
(use-modules (ice-9 pretty-print))
(let ((files '("log4cplus/socketappender.h"
"log4cplus/qt4debugappender.h"
"log4cplus/nteventlogappender.h"
"log4cplus/ndc.h"
"log4cplus/msttsappender.h"
"log4cplus/mdc.h"
"log4cplus/loglevel.h"
"log4cplus/loggingmacros.h"
"log4cplus/logger.h"
"log4cplus/log4judpappender.h"
"log4cplus/log4cplus.h"
"log4cplus/layout.h"
"log4cplus/hierarchylocker.h"
"log4cplus/hierarchy.h"
"log4cplus/fstreams.h"
"log4cplus/clogger.h"
"log4cplus/asyncappender.h"
"log4cplus/version.h"
"log4cplus/tstring.h"
"log4cplus/qt5debugappender.h"
"log4cplus/nullappender.h"
"log4cplus/fileappender.h"
"log4cplus/consoleappender.h"
"log4cplus/clfsappender.h"
"log4cplus/appender.h"
"log4cplus/win32debugappender.h"
"log4cplus/win32consoleappender.h"
"log4cplus/tracelogger.h"
"log4cplus/tchar.h"
"log4cplus/syslogappender.h"
"log4cplus/initializer.h"
"log4cplus/configurator.h"
"log4cplus/config.hxx"
"log4cplus/thread/threads.h"
"log4cplus/thread/syncprims.h"
"log4cplus/thread/syncprims-pub-impl.h"
"log4cplus/thread/impl/tls.h"
"log4cplus/thread/impl/threads-impl.h"
"log4cplus/thread/impl/syncprims-pmsm.h"
"log4cplus/thread/impl/syncprims-impl.h"
"log4cplus/thread/impl/syncprims-cxx11.h"
"log4cplus/spi/rootlogger.h"
"log4cplus/spi/objectregistry.h"
"log4cplus/spi/loggingevent.h"
"log4cplus/spi/loggerimpl.h"
"log4cplus/spi/loggerfactory.h"
"log4cplus/spi/filter.h"
"log4cplus/spi/factory.h"
"log4cplus/spi/appenderattachable.h"
"log4cplus/streams.h"
"log4cplus/internal/socket.h"
"log4cplus/internal/internal.h"
"log4cplus/internal/env.h"
"log4cplus/internal/cygwin-win32.h"
"log4cplus/helpers/thread-config.h"
"log4cplus/helpers/socket.h"
"log4cplus/helpers/pointer.h"
"log4cplus/helpers/lockfile.h"
"log4cplus/helpers/connectorthread.h"
"log4cplus/helpers/timehelper.h"
"log4cplus/helpers/stringhelper.h"
"log4cplus/helpers/socketbuffer.h"
"log4cplus/helpers/snprintf.h"
"log4cplus/helpers/queue.h"
"log4cplus/helpers/property.h"
"log4cplus/helpers/loglog.h"
"log4cplus/helpers/fileinfo.h"
"log4cplus/helpers/appenderattachableimpl.h"
"log4cplus/config/windowsh-inc.h"
"log4cplus/config/win32.h"
"log4cplus/config/macosx.h"
"log4cplus/boost/deviceappender.hxx")))
(begin
;; Add the generated header as it will not be found by file search.
(append! files (list "log4cplus/config/defines.hxx"))
(display "before sort:\n")
(pretty-print files)
(sort! files string<?)
(display "after sort:\n")
(pretty-print files)))
The output that I see is this:
before sort:
("log4cplus/socketappender.h"
"log4cplus/qt4debugappender.h"
"log4cplus/nteventlogappender.h"
"log4cplus/ndc.h"
"log4cplus/msttsappender.h"
"log4cplus/mdc.h"
"log4cplus/loglevel.h"
"log4cplus/loggingmacros.h"
"log4cplus/logger.h"
"log4cplus/log4judpappender.h"
"log4cplus/log4cplus.h"
"log4cplus/layout.h"
"log4cplus/hierarchylocker.h"
"log4cplus/hierarchy.h"
"log4cplus/fstreams.h"
"log4cplus/clogger.h"
"log4cplus/asyncappender.h"
"log4cplus/version.h"
"log4cplus/tstring.h"
"log4cplus/qt5debugappender.h"
"log4cplus/nullappender.h"
"log4cplus/fileappender.h"
"log4cplus/consoleappender.h"
"log4cplus/clfsappender.h"
"log4cplus/appender.h"
"log4cplus/win32debugappender.h"
"log4cplus/win32consoleappender.h"
"log4cplus/tracelogger.h"
"log4cplus/tchar.h"
"log4cplus/syslogappender.h"
"log4cplus/initializer.h"
"log4cplus/configurator.h"
"log4cplus/config.hxx"
"log4cplus/thread/threads.h"
"log4cplus/thread/syncprims.h"
"log4cplus/thread/syncprims-pub-impl.h"
"log4cplus/thread/impl/tls.h"
"log4cplus/thread/impl/threads-impl.h"
"log4cplus/thread/impl/syncprims-pmsm.h"
"log4cplus/thread/impl/syncprims-impl.h"
"log4cplus/thread/impl/syncprims-cxx11.h"
"log4cplus/spi/rootlogger.h"
"log4cplus/spi/objectregistry.h"
"log4cplus/spi/loggingevent.h"
"log4cplus/spi/loggerimpl.h"
"log4cplus/spi/loggerfactory.h"
"log4cplus/spi/filter.h"
"log4cplus/spi/factory.h"
"log4cplus/spi/appenderattachable.h"
"log4cplus/streams.h"
"log4cplus/internal/socket.h"
"log4cplus/internal/internal.h"
"log4cplus/internal/env.h"
"log4cplus/internal/cygwin-win32.h"
"log4cplus/helpers/thread-config.h"
"log4cplus/helpers/socket.h"
"log4cplus/helpers/pointer.h"
"log4cplus/helpers/lockfile.h"
"log4cplus/helpers/connectorthread.h"
"log4cplus/helpers/timehelper.h"
"log4cplus/helpers/stringhelper.h"
"log4cplus/helpers/socketbuffer.h"
"log4cplus/helpers/snprintf.h"
"log4cplus/helpers/queue.h"
"log4cplus/helpers/property.h"
"log4cplus/helpers/loglog.h"
"log4cplus/helpers/fileinfo.h"
"log4cplus/helpers/appenderattachableimpl.h"
"log4cplus/config/windowsh-inc.h"
"log4cplus/config/win32.h"
"log4cplus/config/macosx.h"
"log4cplus/boost/deviceappender.hxx"
"log4cplus/config/defines.hxx")
after sort:
("log4cplus/qt4debugappender.h"
"log4cplus/qt5debugappender.h"
"log4cplus/socketappender.h"
"log4cplus/spi/appenderattachable.h"
"log4cplus/spi/factory.h"
"log4cplus/spi/filter.h"
"log4cplus/spi/loggerfactory.h"
"log4cplus/spi/loggerimpl.h"
"log4cplus/spi/loggingevent.h"
"log4cplus/spi/objectregistry.h"
"log4cplus/spi/rootlogger.h"
"log4cplus/streams.h"
"log4cplus/syslogappender.h"
"log4cplus/tchar.h"
"log4cplus/thread/impl/syncprims-cxx11.h"
"log4cplus/thread/impl/syncprims-impl.h"
"log4cplus/thread/impl/syncprims-pmsm.h"
"log4cplus/thread/impl/threads-impl.h"
"log4cplus/thread/impl/tls.h"
"log4cplus/thread/syncprims-pub-impl.h"
"log4cplus/thread/syncprims.h"
"log4cplus/thread/threads.h"
"log4cplus/tracelogger.h"
"log4cplus/tstring.h"
"log4cplus/version.h"
"log4cplus/win32consoleappender.h"
"log4cplus/win32debugappender.h")
As you can see, the after sorting list is missing half of the items.
What am I doing wrong in the Scheme source?
UPDATE
So by trial and error I have stumbled upon what seems to be a fix. When I change (sort! files string-ci<?) to (set! files (sort! files string<?)), I get the desired result. But I am confused, why is in-place sort not working as I expect.
From the manual:
Sort the sequence items, which may be a list or a vector. less is used for comparing the sequence elements. The sorting is destructive, that means that the input sequence is modified to produce the sorted result. This is not a stable sort.
https://www.gnu.org/software/guile/manual/html_node/Sorting.html
The procedure is destructive however it doesn't promise that input sequence is usable. So you always need to use returned value as a sorted sequence.
Yes, I am aware of the emacs profiler feature. I'm looking for something similar to the time keyword in bash, something like:
(time (myfunc))
which would return or print the time taken by the myfunc call. Is there such a thing?
benchmark.el provides benchmark-run and benchmark-run-compiled functions as well as a benchmark version to run interactively. The linked example:
C-u 512 M-x benchmark (sort (number-sequence 1 512) '<)
Elapsed time: 0.260000s (0.046000s in 6 GCs)
The timer used by all those functions is the benchmark-elapse macro, which you can also use directly if desired:
ELISP> (require 'benchmark)
ELISP> (benchmark-elapse
(sit-for 2))
2.00707889
I found exactly what I was looking for at http://nullprogram.com/blog/2009/05/28/
(defmacro measure-time (&rest body)
"Measure and return the running time of the code block."
(declare (indent defun))
(let ((start (make-symbol "start")))
`(let ((,start (float-time)))
,#body
(- (float-time) ,start))))