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.
Related
With the scan_fmt crate, how do I handle EOF, when used with the scanln_fmt helpers? I want to do something like this where x is None if a empty line was provided:
let (isEOF, x) = scanln_fmt_some!("{d}");
How can I distinguish between empty new line input and EOF?
The scan_fmt crate does not expose a way to distinguish between EOF and other errors.
The macros only return either a (Option<X>, Option<Y>, ...) (as from scan[ln]_fmt_some) or a Result<(X, Y, ...), ScanError> (as from scan[ln]_fmt). And ScanError's contents seems to only explain what type failed to parse, but not why.
I'm trying to write an SWI-Prolog predicate that applies numbervars/3 to a term's anonymous variables but preserves the user-supplied names of its non-anonymous variables. I eventually plan on adding some kind of hook to term_expansion (or something like that).
Example of desired output:
?- TestList=[X,Y,Z,_,_].
> TestList=[X,Y,Z,A,B].
This answer to the question Converting Terms to Atoms preserving variable names in YAP prolog shows how to use read_term to obtain as atoms the names of the variables used in a term. This list (in the form [X='X',Y='Y',...]) does not contain the anonymous variables, unlike the variable list obtained by term_variables, making isolation of the anonymous variables fairly straightforward.
However, the usefulness of this great feature is somewhat limited if it can only be applied to terms read directly from the terminal. I noticed that all of the examples in the answer involve direct user input of the term. Is it possible to get (as atoms) the variable names for terms that are not obtained through direct user input? That is, is there some way to 'write' a term (preserving variable names) to some invisible stream and then 'read' it as if it were input from the terminal?
Alternatively... Perhaps this is more of a LaTeX-ish line of thinking, but is there some way to "wrap" variables inside single quotes (thereby atom-ifying them) before Prolog expands/tries to unify them as variables, with the end result that they're treated as atoms that start with uppercase letters rather than as variables?
You can use the ISO core standard variable_names/1 read and write option. Here is some example code, that replaces anonymous variables in a variable name mapping:
% replace_anon(+Map, +Map, -Map)
replace_anon([_=V|M], S, ['_'=V|N]) :- member(_=W, S), W==V, !,
replace_anon(M, S, N).
replace_anon([A=V|M], S, [A=V|N]) :-
replace_anon(M, S, N).
replace_anon([], _, []).
variable_names/1 is ISO core standard. It was always a read option. It then became a write option as well. See also: https://www.complang.tuwien.ac.at/ulrich/iso-prolog/WDCor3
Here is an example run:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.25)
?- read_term(X,[variable_names(M),singletons(S)]),
replace_anon(M,S,N),
write_term(X,[variable_names(N)]).
|: p(X,Y,X).
p(X,_,X)
To use the old numbervars/3 is not recommended, since its not compatible with attribute variables. You cannot use it for example in the presence of CLP(FD).
Is it possible to get (as atoms) the variable names for terms that are not obtained through direct user input?
if you want to get variable names from source files you should read them from there.
The easiest way to do so using term expansion.
Solution:
read_term_from_atom(+Atom, -Term, +Options)
Use read_term/3 to read the next term from Atom.
Atom is either an atom or a string object.
It is not required for Atom to end with a full-stop.
Use Atom as input to read_term/2 using the option variable_names and return the read term in Term and the variable bindings in variable_names(Bindings).
Bindings is a list of Name = Var couples, thus providing access to the actual variable names. See also read_term/2.
If Atom has no valid syntax, a syntax_error exception is raised.
write_term( Term ) :-
numbervars(Term, 0, End),
write_canonical(Term), nl.
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.
In another question, I saw the following syntax:
#[unset!]
What is that? If I say type? #[unset!] in R3, it tells me unset!, but it doesn't solve the mystery of what #[] is.
So curious.
#[] is the serialized form for values. Play with MOLD versus MOLD/ALL in the console to get a feel for it.
the #[] "syntax" is actually not a syntax as such (not legal syntax, if you try it), only special cases of such constructs are "legal", like the #[unset!] syntax, #[true] syntax, #[false] syntax, #[none!] syntax, or #[datatype! unset!] syntax.
What is even more interesting, is, what the #[unset!] value actually is. It happens to be the value every "uninitialized" variable in REBOL has (not in functions, though, function local variables are initialized to #[none!]), as well as the result of such expressions like print 1, do [], (), etc.
Regarding the "function local variables ... initialized to #[none!]" I should add, that only the variables following an "unused refinement" (i.e. the one not used in the actual call) are initialized to #[none!] together with the refinement variable.
To explain the issue further, the syntactic (Data exchange dialect) difference between true and #[true] is, that the former is a word, while the latter is a value of the logic! type. Seen from the semantic (Do dialect) point of view, the difference is smaller, since the (global) word is interpreted as a variable, which happens to refer to the #[true] value.
Looks like it's the value-construction syntax for an unset instance, as opposed to the word unset!:
>> comparison: [unset! #[unset!]]
== [unset! unset!]
>> type? first comparison
== word!
>> type? second comparison
== unset!
>> second comparison
>> first comparison
== unset!
If you're in a programmatic context you could do this with to-unset, but having a literal notation lets you dodge the reduce:
>> comparison: reduce ['unset! to-unset none]
== [unset! unset!]
>> second comparison
>> first comparison
== unset!
Looks like they've reserved the #[...] syntax for more of these kinds of constructors.
Look at the example below:
trace on
>> e: none
Trace: e: (set-word)
Trace: none (word) ;<<<<<
>> e: #[none]
Trace: e: (set-word)
Trace: none (none) ;<<<<<
none is a word in the first one, but in the second one, #[none] is not a word, it is the Rebol value of the datatype none!.
Similarly for other values like true, false. The #[unset!] case is special since every undefined variable actually has this value.
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)