(partial apply str) and apply-str in clojure's -> - variables

If I do the following:
user=> (-> ["1" "2"] (partial apply str))
#<core$partial__5034$fn__5040 clojure.core$partial__5034$fn__5040#d4dd758>
...I get a partial function back. However, if I bind it to a variable:
user=> (def apply-str (partial apply str))
#'user/apply-str
user=> (-> ["1" "2" "3"] apply-str)
"123"
...the code works as I intended it. I would assume that they are the same thing, but apparently that isn't the case. Can someone explain why this is to me?

-> is a macro, so it doesn't have to follow the rules you would expect in terms of application. The macro transforms the source before the forms are evaluated. Try macroexpanding the forms:
user> (macroexpand '(-> ["1" "2"] (partial apply str)))
(partial ["1" "2"] apply str)
What are you trying to achieve here by using the '->' macro?
EDIT: Note that:
user> ((partial apply str) ["1" "2"])
"12"

You don't have to do that at all.
(->> ["1" "2" "3"] (apply str))
Why not do that instead?

The first expression, (-> ["1" "2"] (partial apply str)), expands into:
(partial ["1" "2"] apply str) which basically means:
Create a function from ["1" "2"] (which is also a function, since vectors are functions of index keys!) with the Vars apply and str already supplied as the first two arguments. This function gets printed as the weird #<core$partial...> string.
Only when this function will be called will you get an IllegalArgumentException since vectors only take one integer argument, not two Var arguments.

The Macro -> Threads the expr through the forms as second argument. In your case ends up in expanding to: (partial ["1" "2"] apply str), creating a parital function based on vector.
But you want to invoke a parital function based on apply and str on the threaded expr and thus need:
(-> ["1" "2"] ((partial apply str)))
Well: this code i quite confusing and not idiomatic Clojure.

The -> macro adds parens around apply-str in your second version, that's why the macro expands to code that ends up calling your function. Look at the source code for -> and you can see:
(defmacro ->
"Threads the expr through the forms. Inserts x as the
second item in the first form, making a list of it if it is not a
list already. If there are more forms, inserts the first form as the
second item in second form, etc."
([x] x)
([x form] (if (seq? form)
(with-meta `(~(first form) ~x ~#(next form)) (meta form))
(list form x)))
([x form & more] `(-> (-> ~x ~form) ~#more)))
The relevant part is when it's dealing with two arguments, x and form. If form is a seq, x is inserted as the second argument in that list. Otherwise, the macro puts form and x it into a list itself. This is so you can use a bare symbol as shorthand for a list containing one symbol.
user> (macroexpand '(-> 123 (foo)))
(foo 123)
user> (macroexpand '(-> 123 foo))
(foo 123)

Related

Elm Syntax, Pipe forward a match case without using temp variable

F#, Pipe forward a match case without using temp variable
Similar to the question above, is there a way to pipe-forward a variable to a match case without using a temp variable or a lambda?
The idea:
let temp =
x
|> Function1
|> Function2
// ........ Many functions later.
|> FunctionN
in
result =
case temp of
Case1 -> "Output 1"
Case2 -> "Output 2"
_ -> "Other Output"
I hope to achieve the following:
result =
x
|> Function1
|> Function2
// ........ Many functions later.
|> FunctionN
|> case of // Syntax Error! Should use "case temp of"
Case1 -> "Output 1"
Case2 -> "Output 2"
_ -> "Other Output"
I can use a lambda function, but I would still be "naming" the temp variable.
result =
x
|> Function1
|> Function2
// ........ Many functions later.
|> FunctionN
|> \temp -> case temp of
Case1 -> "Output 1"
Case2 -> "Output 2"
_ -> "Other Output"
Is there a way in the Elm syntax to "get rid" of the temp variable? Thanks.
No, Elm does not have that ability.
Other languages like Haskell allow something similar via the LambdaCase extension, but Elm tends to avoid having too many ways to say the same thing, erring on the side of keeping syntax simple.
The issue has been raised before, and Elm's author rejected the proposal with the following comment:
More generally though, the focus right now is not on growing the syntax of Elm. (We're actually dropping stuff more often.) If something can be expressed in Elm already, I'm not hugely interested in providing alternate ways to express it. In this case, I think we would be adding syntax to make things less regular and harder to read.

Expected Int, got IntProgression instead

I am trying to get on Kotlin so I am following this tutorial of their own.
So they're trying to create a sequence given a string, such as this:
"a vect" -> [
a vect :
a vec : t
a ve : ct
...
]
And the way to do it is, according to the video, the following:
val seq = sequenceOf(canonicalisedInput.lastIndex + 1 downTo 0).map {
canonicalisedInput.substring(0, it) to canonicalisedInput.substring(it)
}
And I get what I does (well, the idea of it). The problem is that substring expects two Ints, while it (which I assume is an implicit iterator of some sorts that comes from the downTo progression) is an IntProgression. Same for the second substring call.
What am I missing?
The code you posted contains a mistake: sequenceOf(...) with single argument passed returns a sequence with that one item, that is, Sequence<IntProgression> . To get a sequence of indices (Sequence<Int>), use asSequence() function instead:
(canonicalisedInput.lastIndex + 1 downTo 0).asSequence().map { ... }
The substring(...) function called second is the overload that returns the substring starting from the index passed as the argument.
And it is the implicit name for the innermost lambda single parameter, in your case it is the parameter of map, that is, the sequence item to be mapped by the lambda.
So, the expression inside lambda is a pair (created by to infix function) of two substring, one from the beginning of the original string to the index in the sequence, the other one -- from that index to the end of the string.
So the code should definitely work with indices sequence, that's why the mistake is quite clear.
sequenceOf(canonicalisedInput.lastIndex + 1 downTo 0) —
this expression creates a sequence which consists of a single IntProgression item.
If you want to convert an IntProgression to a Sequence<Int>, use asSequence extension function:
(canonicalisedInput.length downTo 0).asSequence()

Why eval works where macro doesn't when building WHERE conditions in Korma

I'm trying to dynamically add WHERE conditions to Korma SQL query
(-> the-query
(where {:archived false})
(add-where-conditions params)
(limit 200)
(select))
I'm trying to dynamically build call to korma's where function. The call would look something like (where query (or (between :freq [100 200]) (between :freq [300 400]) ... )). The helper function make-conds makes a list of the arguments for where function like: (or (between :freq [100 200]) ...
I attempted the following approaches to build the dynamic where call. Only the first one, the one with eval works. Why? Is there a better way to do this?
(defn add-where-conditions [query params]
(eval (list 'where query (make-conds params))))
(defmacro add-where-conditions-2 [query params]
(list 'where query (make-conds params))) ; broken
(defmacro add-where-conditions-3 [query params]
`(where ~query ~(make-conds params))) ; broken
Disclaimer: I'm a newbie to Clojure and Korma
The reason why the macros don't work is that in both cases the value for the params argument is the symbol params. This is why in add-where-conditions-2 and add-where-conditions-3 when the macros make the call (make-conds params), the value that function receives is not the list you are thinking of but the symbol params, showing an error in the lines of:
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Symbol clojure.lang.RT.seqFrom (RT.java:505)
The first case works because the function receives the list (not the symbol) as the value for the params argument, so eval receives the list (where {:your-query nil} (or (between :freq [100 200]) ,,,)), which is what the where macro expects and knows how to handle.
The where macro parses the expression in search of some predicates which it uses to build expressions. where*, the function alternative, doesn't have that kind of functionality, so I can't think of an alternative to eval for eating the cake and having it too.

Clojure: ^:dynamic in macros?

As some of you know I am implementing Shen in Clojure.
Since Shen has a dual namespace and all symbols evaluate to themselves I need a Clojure macro, which binds the symbol to itself and the value to a postfixed symbol.
Now also symbols like *language* have to be bound. But when I use the following macro with *language* as a parameter I get Warning: *language* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *language* or change the name.
(defmacro set [x y]
`(let [y# ~y]
(def ^:dynamic ~x '~x)
(intern *ns* (symbol (str (name ~x) "__varPoF__")))
(def ^:dynamic ~(symbol (str (name x) "__varPoF__")) y#)
y#))
Can someone tell me why this is not working?
The use of reader macros is wrong here. You have to use with-meta. I'm also not sure why you need the intern call.
(defmacro set
[x y]
(let [dynamic {:dynamic true}]
`(let [y# ~y]
(def ~(vary-meta x merge dynamic) '~x)
(def ~(vary-meta (symbol (str (name x) "__varPoF__")) merge dynamic) y#)
y#)))
Shameless self-promotion: with-meta and the reader.
What you receive is a WARNING due to the convention in Clojure < 1.3 for which vars named with "earmuffs", i.e. with leading and trailing starts, where dynamically rebindable.
Since Clojure 1.3 this is no longer the case, and the Reader throws that warning to, well, warn you that things might not be as you expect. It shouldn't break you code though, as WARNINGs are not errors.

In clojure why does splitting a string from an empty file return 1 element?

Consider the following:
=> (even? (count []))
true
so far so good. Now consider (assume my-file is empty):
(odd? (count (str/split (slurp my-file) #"\|")))
true
err ... why is the vector returned from an empty file not even (zero) ?
=>(str/split (slurp my-file) #"\|")
[""]
Ahh, can someone explain why an empty string is returned in this case?
I'm attempting to determine if there are an odd number of records in a file or not.
clojure.string/split uses java.util.regex.Pattern/split to do the splitting. See this question about Java for explanation. Namely, split returns everything before the first match of your pattern as the first split, even if the pattern doesn't match at all.
The canonical way to test if a collection (list,array,map,string etc.) is empty or not is to call seq on it, which will return nil for an empty collection.
(defn odd-number-of-records? [filename]
(let [txt (slurp filename)]
(when (seq txt)
(odd? (count (str/split txt #"\|"))))))