level1
level1

Reputation: 87

Cannot pass list as argument to function

I have a substitute function that will take in an expression such as (or false x y) and a binding map such as '{x false, y true} and will return the list with the appropriate substitutions. The result is in l and displayed. How might I pass l into another function to do some other processing? The definition for the function I'm passing to looks like this:

(defn f [expression]
    )

I have tried passing l as a parameter when calling f, but I get the following error:

IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Symbol  clojure.lang.RT.seqFrom (RT.java:550)

Here is my substitute function:

    (defn deep-substitute [m l]
  (map (fn [i]
         (if (seq? i)
           (deep-substitute m i)
           (m i i)))
       l
       (f 'l)))

My new function fully works the way I expect it to when calling it with an unevaluated list, but not when I pass it an unevaluated list.

Upvotes: 0

Views: 664

Answers (2)

Satyam Ramawat
Satyam Ramawat

Reputation: 37

first try with the basic approach of the passing list as an argument to the function. You can refer below example

(defn passlist [a]
  (println a))
(passlist '(1 2 3))

Output will:

#'user/passlist
(1 2 3) 

Upvotes: 1

Arthur Ulfeldt
Arthur Ulfeldt

Reputation: 91534

The job of deep-substitute is to fill in a template form and return it. The problem gets harder if you try to make deep-substitute also responsible for doing the next step in the transformations as well. Perhaps let it return the value, then pass that value on to another transform function after it's returned.

Here's an annotated working example:

user>  (defn deep-substitute [m l]      
         (map (fn [i]          
                (if (seq? i)             ;; if this is a sequence, 
                  (deep-substitute m i)  ;; finish the sequence and include the result here
                  (get m i i)))          ;; otherwise get the new value from the map, if found
              l))                        ;; if it's not found, us the value unchanged.
#'user/deep-substitute

then test it on your example:

user> (deep-substitute '{x false, y true} '(or false x y))
(or false false true)

and a more nested example:

user> (deep-substitute '{x false, y true} '(or false (and x (or y x)) y))
(or false (and false (or true false)) true)

a common next step is to wrap that in a macro so it can modify forms before they are evaluated, then evaluate that newly created from to find out what value it becomes:

user> (defmacro dsub [m l]
        (deep-substitute m l))
#'user/dsub

and test it

user> (dsub {x false, y true} (or false (and x (or y x)) y))
true

user> (dsub {x false, y true} (or false  x))
false

or pass the resulting form (unevaluated) into another function by nesting it:

user> (defn f [expression]
        (reverse expression))
#'user/f

user> (f (deep-substitute '{x false, y true} '(or false (and x (or y x)) y)))
(true (and false (or true false)) false or)

A common pattern is to use the threading macros -> ->> etc. to pass the result from transform to transform until the final result is made by composing many simple operations:

user> (->> '(or false (and x (or y x)) y)
           (deep-substitute '{x false, y true})
           f
           (deep-substitute '{false, 41 true 42}))
(42 (and 41 (or 42 41)) 41 or)

Upvotes: 1

Related Questions