I use {:pre [(number? input )]} function to test whether the input is a number; however, this result to an exception when clojure is not sure what type it is. Foe example:
(number? A)
Unable to resolve symbol…
What's the idiomatic way to make sure the input is a number?
Edit: After I read the docs and tried several times, plus the kindly answers in this post, I find that probably a better question is how to handle exception. The purpose is to prevent someone from input something like a (letter a without any punctuation).
Yes, the function (number? some-value) does work well with numbers, strings. But it can't deal with wrong input like this:
A
input-without-quotation-marks
Are you sure that it isn't working?
(defn numbers-only [n] {:pre [(number? n)]}
(println "Yay!"))
(numbers-only "clojure")
AssertionError Assert failed: (number? n)
(numbers-only 27)
Yay!
Maybe you are mistyping the name of the param in the pre condition?
Unable to resolve symbol is a compile-time exception. A symbol that's not defined cannot be tested by a function because the expression will not compile.
Do you really want to test against random symbols that don't resolve to anything or are you just experimenting in the repl? I suspect the latter, but if for some reason you wanted the former you'd need a macro.
Related
I am writing a program that opens a lisp file, calls "read" on the stream until the stream is empty, and does things with the lists it collects.
This was working quite nicely until I discovered that "read" will perform package lookup, for instance if it encounters some-package:foo it will complain that Package SOME-PACKAGE does not exist.
Here is an example showing what I mean:
(read (make-string-input-stream "(list 'foo :foo some-package:foo)"))
So I now I would like one of three things:
Make it so "read" will ignore package namespaces so I can convert arbitrary source files to lists of symbols.
Use some other parsing library with similar behavior to "read" but that only gets plain symbols, either by mangling the : or ignoring the colon and everything before it.
Pre-processing the file and use regex or such to package lookups and replace them with plain names, such as converting "some-package:foo" to simply "foo"
The purpose of all of this in the first place was to make a function call dependency graph. I'm aware there exists things of that nature of much higher quality that exist, but I wanted to do it myself for fun/learning. However, I have hit a snag with this problem and don't know how to proceed.
For your use case, you could handle the package-error condition by creating the required package and restarting. That would also preserve the symbol identities. Note that you need to handle in-package forms when you encounter them.
The simplest answer is to tell the Lisp reader to read colon #\: as is:
(defun read-standalone-char (stream char)
(declare (ignore stream))
char)
(defun make-no-package-prefix-readtable (&optional (rt (copy-readtable)))
"Return a readtable for reading while ignoring package prefixes."
(set-syntax-from-char #\: #\Space rt)
(set-macro-character #\: #'read-standalone-char nil rt)
rt)
(let ((*readtable* (make-no-package-prefix-readtable)))
(read-from-string "(list 'foo :foo some-package:foo)"))
==> (LIST 'FOO #\: FOO SOME-PACKAGE #\: FOO) ; 33
The obvious problem is that this will read FOO:BAR and FOO :BAR identically, but you might be able to work around that.
(defn lines
"Given an open reader, return a lazy sequence of lines"
[^java.io.BufferedReader reader]
(take-while identity (repeatedly #(.readLine reader))))
what does this line mean? -> [^java.io.BufferedReader reader]
also I know this is a dumb question. can you show me the documentation where I could read this myself? So that I don't have to ask it here :)
You can find documentation here:
https://clojure.org/reference/java_interop#typehints
Clojure supports the use of type hints to assist the compiler in avoiding reflection in performance-critical areas of code. Normally, one should avoid the use of type hints until there is a known performance bottleneck. Type hints are metadata tags placed on symbols or expressions that are consumed by the compiler. They can be placed on function parameters, let-bound names, var names (when defined), and expressions:
(defn len [x]
(.length x))
(defn len2 [^String x]
(.length x))
...
Once a type hint has been placed on an identifier or expression, the compiler will try to resolve any calls to methods thereupon at compile time. In addition, the compiler will track the use of any return values and infer types for their use and so on, so very few hints are needed to get a fully compile-time resolved series of calls.
You should also check out:
https://clojure.org/guides/weird_characters
https://clojure.org/reference/reader
And never, ever fail to keep open a browser tab to The Clojure CheatSheet
You may also wish to review this answer.
I'm trying to write a function which takes a sequence of bindings and an expression and returns the result.
The sequence of bindings are formatted thus: ([:bind-type [bind-vec] ... ) where bind-type is either let or letfn. For example:
([:let [a 10 b 20]] [:letfn [(foo [x] (inc x))]] ... )
And the expression just a regular Clojure expression e.g. (foo (+ a b)) so together this example pair of inputs would yeild 31.
Currently I have this:
(defn wrap-bindings
[[[bind-type bind-vec :as binding] & rest] expr]
(if binding
(let [bind-op (case bind-type :let 'let* :letfn 'letfn*)]
`(~bind-op ~bind-vec ~(wrap-bindings rest expr)))
expr))
(defn eval-with-bindings
([bindings expr]
(eval (wrap-bindings bindings expr))))
I am not very experienced with Clojure and have been told that use of eval is generally bad practice. I do not believe that I can write this as a macro since the bindings and expression may only be given at run-time, so what I am asking is: is there a more idiomatic way of doing this?
eval is almost always not the answer though sometimes rare things happen. In this case you meet the criteria because:
since the bindings and expression may only be given at run-time
You desire arbitrary code to be input and run while the program is going
The binding forms to be used can take any data as it's input, even data from elsewhere in the program
So your existing example using eval is appropriate given the contraints of the question at least as I'm understanding it. Perhaps there is room to change the requirements to allow the expressions to be defined in advance and remove the need for eval, though if not then i'd suggest using what you have.
I am trying to write a macro that generates patterns for the core.match macro.
(defmacro match2
[state i predecessor]
`(match ~[state]
[(~(vec (concat (repeat i '_)
predecessor
'(& r)))
:seq)] ~i
:else false))
And this works fine if I use it directly with hardcoded predecessor:
(match2 ["B"] 0 ["B"]) ; 0
So far everything is fine, but if I try to pass the predecessor using function call:
(match2 ["B"] 0 ((fn [] ["B"]))) ; AssertionError Invalid list syntax [] in (fn [] ["B"])
The problem is that because match2 is a macro clojure won't evaluate the function call, and will just pass the form as it is. The unevaluated form then goes to core.match (again unevaluated, because core.match is itself a macro) and core.match throws exception because the form is not correct pattern.
How can I force evaluation on macro argument? Or any other workaround?
I was hinted that this is usually done with a second macro, but my attempts yielded no good results.
I see two options. Use eval in your macro.
Or, you could have your macro not call the match macro. Have it call another function which calls the match macro. That will force evaluation en route to match.
Here is a good article to read about this type of problem:
http://amalloy.hubpages.com/hub/Clojure-macro-writing-macros
core.match is a compiler. It turns some forms into executable expressions. The forms it can process must respect a syntax, hence the assert throw. As a macro, it compiles at... compile time. However hard you try, you cannot have it compile the result of runtime expressions.
Even if you manage to get (fn [] ["B"]) evaluated at compile time so to feed the value to match, this is not your goal I presume. What you're trying to do is to feed match with expressions evaluated by your program's logic. Been there, sorry to say it is not possible with core.match, which D. Nolen confirmed.
Nevertheless, matchure can do just that: create match functions / expressions at runtime, see fn-match. It is unmaintained AFAIK but just works. I've patched it some time ago to use clj 1.6, here.
I'm writing a simple DiceRoller application and I've created the primary function, however I'm wondering if there is a "smart" way to validate function inputs in Clojure rather than using branching conditionals to validate input? My function is below with a sample test, I would have to also test if n is not a number with another if or an or and it feels messy.
Also if anyone can point out a smarter way to do this function I would appreciate any feedback, this is my first attempt at trying to program functionally
(ns DiceRoller)
(defn roll
"rolls a specified number of n sided dice "
([] (roll 1 6))
([number] (roll number 6))
([number n]
(if-not number? number (throw (IllegalArgumentException. (str "incorrect input, integers only"))))
(take number (repeatedly #(+ (rand-int n) 1)))
)
)
Sure there is - you can use a :pre assertion for that.
(defn some-fun [x]
{:pre [(number? x)]}
(foo x))
Now you'll get AssertionError Assert failed: (number? x) if you pass the function a non-numeric argument x.
Checking whether the input is a number is kind of useless as #amalloy already pointed out, but there are lots of totally valid precondition (and postcondition for that matter) checks that you might want to apply to your function. You can see some more details on the subject here and here.
Mostly the Clojure attitude is "just assume you got the right thing". In this case, if you took out your check entirely, the user would get basically the same exception eventually. But if you really wanted to do this, you should do it correctly! Right now your code throws an exception on every input, because you're missing parens around (number? number).