how to compile (e.g. fail) a clojure file - clojure

I'm new to clojure. I have defined a function in test.clj
(defn foldl [f val coll]
(if (empty? coll) val
(foldl f (f val (first coll)) (rest coll))))
I tried loading this file
user=> load-file "test.clj"
#object[clojure.lang.RT$3 0x16bb1d20 "clojure.lang.RT$3#16bb1d20"]
"test.clj"
It doesn't complain but when I try to use it
foldl + 0 (1 2 3)
I get
Syntax error compiling at (REPL:0:0).
Unable to resolve symbol: foldl in this context
#object[clojure.core$_PLUS_ 0x3df3a187 "clojure.core$_PLUS_#3df3a187"]
0
Execution error (ClassCastException) at user/eval2008 (REPL:1).
java.lang.Long cannot be cast to clojure.lang.IFn
How do I force it to compile and tell me what's wrong with the function when I load it rather than when I execute it? Also what does the error mean?

You need to use parenthesis when calling functions like load-file i.e.
(load-file "test.clj")
without parenthesis this just evalutes the symbol load-file which resolves to the function and the string "test.clj". Both of these are displayed in the REPL.
Similarly when calling foldl:
(foldl + 0 '(1 2 3))
in contrast
foldl + 0 (1 2 3)
is a list of 4 forms - the symbols foldl and +, the long 0 and the list (1 2 3). Since you failed to load the file in the previous step, foldl cannot be found hence the error. + resolves to the clojure.core/+ function which is displayed in the REPL. 0 evaluates to itself and is displayed in the REPL, while the list (1 2 3) is evaulated by attempting to call 1 as a function with arguments 2 and 3. Since 1 does not implement IFn you receive the error "java.lang.Long cannot be cast to clojure.lang.IFn".

Related

Clojure how to send some args to a function that is called as a symbol

What I'm trying to do is call a function from a map with some locally defined variables without expressing the whole variable in the call to the function.
For example, the following code works, :
(let [a [0 1 2]]
(eval (list ({:fun 'count} :fun) a))) => 3
and this code works for a quoted 'a when it is globally defined:
(def a [0 1 2])
(eval (list ({:fun 'count} :fun) 'a))
but this code does not work:
(let [a [0 1 2]]
(eval (list ({:fun 'count} :fun) 'a)))
=> Unable to resolve symbol: a in this context
The first chunk is fine for small vectors like this one, but when I need to pass in a vector of several thousand items then the unquote "a" would cause it to throw an error for "Method too large" because the actual method sent to the machine is:
(let [a [0 1 2]]
(eval (count [0 1 2]))
What is a simple way to execute a call to the function with the variable itself as an argument?
It isn't clear why you are evaling the symbol 'count. Can't you just keep the function count in the map and call it as follows:
(let [a [0 1 2]] (({:fun count} :fun) a)) => 3
Then vector a can be any size you like.
Don't use an eval where a macro will do.
Don't use a macro where a function will do.
In retrospect, all you have done is defer compilation from when it is easy to when it is difficult.

In Clojure: Why unable to resolve symbol: hdcit in this context

I tried to solve the find two numbers index in a list where nums[i]+nums[j]==target:
(defn two-sum [nums target]
"Find sum of two numbers equals to target"
(if (<= 1 (count nums))
nil)
(let [hdict (hash-map)]
(for [i (range 1 (count nums))]
(if (get hdict (nums i))
[(get hdict (nums i)) i] ;return hdict[nums[i]] and i
(assoc hdcit (- target (nums i)) i)))))
I got this error:
1. Caused by java.lang.RuntimeException
Unable to resolve symbol: hdcit in this context
I'm confused: I've alread bind hdict as a hash-map, why still unable solved?
The error is a simple typo, though there are a couple other points worth considering:
Clojure if expressions always return a value and if you don't specify an else clause (the second expression) then it defaults to nil
So the if in the code above basically says:
(if contition
nil ;; the true case
nil ;; the false case)
Always returns nil. Though since it's not the last expression in the function this value will be ignored because:
The return value of a function (and most other expressions) is the last value in the expression.
Most likely you want to move the ) after the nil to the end of the function.
Clojure data structure are immutable, calling assoc on a map produces a new map that has an additional value while leaving the old on unchanged because someone else might be working on it.
So the assoc on the last line will never do anything.
for is not a "for loop", rather it produces a sequence of new values, lazily, based on a very powerful expression "mini language" (DSL)
This means that it only produces a value when it's read. So this for loop will not run unless something prints the value. The REPL will print this and make this function work only in development. I call this "the lazy bug".
Immutable data is a core concept in Clojure and basically all the goodness of the language flows, at least in part, from it.
Clojure's for expression is powerful enough to completely solve this problem:
user> (let [data [1 2 3 4 5 6 7 42 12]
target 12]
(for [x data
y data
:when (= (+ x y) target)]
[x y]))
([5 7] [6 6] [7 5])

is function print has bug in clojure?

I write a macro:
(defmacro te
[a b & c]
`(print
~(a b c)))
and run
(te print 2 inc 4)
got an error ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn user/eval8010 (form-init8519408738377285198.clj:1)
and I run
(macroexpand-1 '(te print 2 3 4)
;=> (clojure.core/print (3 4))
it means (print 2 (3 4)) return (3 4)? is it function print has bug?
My clojure version 1.7.0, JVM version 1.8.0_65-b17
update
Ok.the example is not understand easily by commit.
even i run the
(te print 2 inc 4)
user=> (te print 2 inc 4)
;=> 5nil
user=> (macroexpand-1 '(te print 2 inc 4))
;=> (clojure.core/print (inc 4))
it will print 5 and return nil,that mean (print 2 (inc 4)) return form (inc 4)?
This is not related to print at all.
it means (print 2 (3 4)) return (3 4)?
That's not what it means, and that's the source of your problem. It means "call the function print with first argument 2 and second argument the value of (3 4)". The expression (3 4) has no valid value because it means "call function 3 with argument 4" which is why you get an exception: 3 is a Long (number) and cannot be called as a function (in clojure internals, it does not implement the IFn function interface).
As a side note, if I understand what you're trying to achieve (I may be wrong) your macro can easily be written as a function, which in general means you should write it as a function, since functions are easier to deal with and work better with other functions.
Remember that the arguments to a macro haven't been evaluated when the macro
is invoked.
When you invoke your macro like this:
(te print 2 inc 4)
The parameters are bound to the following:
a: 'print
b: '2
c: '(inc 4) (because the macro is variadic any parameters past the first two are put
into a list in c)
The expression you end up with is this:
`(print ~('print '2 '(inc 4)))
Here's the problem: that inner print is not the same thing as the function
clojure.core/print. This is a macro, so it's an unevaluated symbol. You're using
the symbol itself as a function in this case, instead of using the function referred
to by the symbol.
Every symbol in Clojure is a function that looks itself up in a map.
That lookup takes two
parameters, a key and a default value. In this case the symbol print is trying to look
itself up in 2. Since 2 is not a map, it's returning the default value of (inc 4).
Recall that unquote (~) means evaluate the expression and substitue the result
into the code generated by the macro.
So the compiler evaluates: ('print '2 '(inc 4)) which returns (inc 4) and then
substitutes that into the original expression.
That's how you end up with (clojure.core/print (inc 4))
Try this:
(macroexpand-1 '(te blarg 2 inc 4))
You get exactly the same result even
though blarg isn't a variable that's defined anywhere in Clojure.
In your other example, the other answer is quite right. If you the third argument to your macro is not a function, then you'll get another error there.
Honestly, I'm not sure what you're trying to accomplish so I'm not sure if this really answers your question. But this is why you're seeing what you're seeing.

Clojure - map with unbound function

I'm following a Clojure tutorial in Try Clojure, where we are introduced to defining our functions -
(defn square [x] (* x x))
Then apply it to a list of numbers:
(map square [1 2 3 4])
Which promptly prints out an error: java.lang.IllegalStateException: Attempting to call unbound fn: #'sandbox14750/square
When I try to map for example function inc, that works fine - what's the difference between the built-in function inc and my square?
I had some trouble the first time I tried to run it though after refreshing the page it went fine.
Give me some Clojure:
> (defn square [x] (* x x))
#'sandbox6361/square
> (square 4)
16
> (map square [1 2 3 4])
(1 4 9 16)
If you want to make sure your functions are still available when you need them you can store your functions in locals instead of vars like so:
> (let [square (fn [x] (* x x))] (map square [1 2 3 4]))
(1 4 9 16)
>
many sandbpxed environments like Clojurebot on #clojure don't let you define arbitrary state so it's worth knowing that functions can be stored in many ways, not just in vars.

Putting a list in a parameter in scheme

So I am new to using Scheme/Guile and have an assignment where I must take 2 inputs; a simple variable and a list.
I then add the variable to each number in the list and print it out. I have got it to load but when I enter this:
(add 1 (1 2 3))
I get this error:
Backtrace:
39: 0* [add 1 ...
39: 1* [1 2 3]
standard inout:39:8: In expression (1 2 3):
standard input:39:8:wrong type to appy: 1
ABORT: (misc-error)
Here is the code that I currently have.
(define a (list a))
(define (add y a)
(define x 0)
(while (< x (length a))
(display (+ y (car a)))
(newline)
(set! a (cdr a))
(set! x (+ x 1))
)
)
My question is:
How do I get the list to work in the parameter? I have looked around online but havent found much to fix this problem.
Many thanks ahead of time for any help you can give me.
You're getting an error because (1 2 3) tells it to call the function 1 with two arguments, 2 and 3. To create a list containing 1, 2 and 3, use (list 1 2 3).
Do you really intend to write a procedure in such an imperative way? It looks not very Scheme-like. Evaluating your procedures in GNU Guile yields many error messages about unbound variables etc. set! is eval for beginners of Scheme ;) :) (SICP treats assignment extensively in chapter 3). You can do it much easier in functional style without the side-effects of set! and display.
If you are already aware about mapping and high-order functions, you could do something like this:
(define (add x)
(lambda (y) (+ x y)))
(map (add 1) (list 1 2 3))
===> (2 3 4)
If not, write a recursive procedure yourself:
(define (add-to-list x list)
(if (null? list)
'()
(cons (+ x (car list))
(add-to-list x (cdr list)))))
(add-to-list 1 '(1 2 3))
===> (2 3 4)
In order to learn thinking recursively, consult books like SICP, HTDP or "The litte Schemer".