I am working with Om and I didn't fully understand the following expression :
(.. e -target -checked)
Here, "e" is a javascript event, and "-target -checked" is a way to access properties, if I understood well. But what about the two dots at the beginning ?
That's one of the forms for clojurescript interop.
The most basic one is
(.method object) ; Equivalent to object.method()
(.-property object) ; Equivalent to object[property]
In order to access several nested properties, there is a shortcut with the .. operator, so that you can do:
(.. object -property -property method)
(.. object -property -property -property)
Instead of:
(.method (.-property (.-property object)))
(.-property (.-property (.-property object)))
And the code results in a cleaner more readable expression. As you can see, the parallel is that the form is the same as normal interop but without the dot, so that property access turns into -prop and method calls turn into method (no dot).
Those forms above are equivalent to this JS forms:
object[property][property][method]()
object[property][property][property]
Read up this good post to learn more about clojurescript's javascript interop forms: http://www.spacjer.com/blog/2014/09/12/clojurescript-javascript-interop/
Related
I'm having trouble getting something to work in ClojureScript that works in Clojure no problem.
(defn unmap [nspace & vars]
(doseq [var vars] (ns-unmap nspace var)))
Usage as:
(unmap 'some.nspace 'vars 'to 'be 'removed)
You can also make unmap a macro so you don't have to quote everything. All it does is iterate over a list of symbols and pluck their bindings from a given namespace.
Neither the macro form, or the unmap function work in ClojureScript (they work fine in Clojure). I get the following error when trying to define the above function.
Unexpected error (AssertionError) macroexpanding cljs.core/ns-unmap.
Assert failed: Arguments to ns-unmap must be quoted symbols
Not sure if this is a bug. It seems like ClojureScript is looking for a type hint. If anyone knows how to get this to work it would be appreciated.
In ClojureScript, the ns-unmap macro is designed to be used at the REPL to manipulate both runtime and compiler state used in the implementation of namespaces at dev time.
The symbols passed to ns-unmap need to be known at compile time in order for it to properly manipulate compiler state at macroexpansion time.
This problem can be solved by defining a macro which expands to a do containing each of the desired ns-unmap invocations.
Here is an example:
(defmacro unmap [nspace & vars]
`(do
~#(map (fn [var]
`(ns-unmap ~nspace ~var))
vars)))
I'm attempting to use a string saved in a variable to call a function like so:
(defn update-product-list [] "Test")
(defn handle-state-change [action]
((resolve (symbol action))))
(handle-state-change "update-product-list")
However, this gives me the following error: Assert failed: Argument to resolve must be a quoted symbol
I've also tried changing the above line to:
((resolve (quote (symbol action))))
But this still gives an error. I also tried changing it just to:
((resolve 'action))
But this gives a different error I don't quite understand: js/action is shadowed by a local. I don't want to override the function just call it. Not sure where I'm going wrong. I've looked at a few examples, but can't see to pin it down.
ClojureScript supports :advanced optimization, in which Google Closure Compiler will rename, inline, or eliminate (unused) functions in order to implement minification. In short, the name of the function you want to look up will, in general, simply no longer exist under :advanced.
Because of this, ClojureScript's resolve is a compile-time facility (a macro requiring a literal quoted symbol).
If you are using :simple or self-hosted ClojureScript, more options are available to you because the support needed persists into runtime. For example Planck has a planck.core/resolve that behave's like Clojure's resolve. A similar approach is possible in Lumo, and similar facilities can be fashioned if using :simple.
In general though, given :advanced, if you need to map strings to a set of functions, you need to somehow arrange to have a static mapping constructed at compile time to support this (the set of functions must be known a priori, at compile time).
If you have a namespace (the name of which is statically known at compile time) which defines functions that need to be dynamically called via strings, you could consider making use of ns-publics:
cljs.user=> (ns foo.core)
foo.core=> (defn square [x] (* x x))
#'foo.core/square
foo.core=> (in-ns 'cljs.user)
nil
cljs.user=> (when-some [fn-var ((ns-publics 'foo.core) (symbol "square"))]
(fn-var 3))
9
This will work under :advanced. The mapping constructed by ns-publics is static; built at compile-time. If you have multiple namespaces that need such treatment, you could merge several calls to ns-publics to build a larger map.
The advantage of this approach is that the code involved is pretty short and requires little maintenance. The disadvantage is that it dumps all of the public vars of the namespace (foo.core in this example) into your generated code (and the generated code for vars is somewhat verbose). Another disadvantage is that you need to statically know the namespace(s) involved at compile time.
If you need to further minimize generated code size, you could just build / maintain a simple static map from string to function value as in
(def fns {"square" foo.core/square})
and use it appropriately, keeping it up to date as your codebase evolves.
Another option would be to mark the functions that you need to access using ^:export meta, and then to call those functions using JavaScript interop. For example if you define the function this way
(defn ^:export square [x] (* x x))
then you can use strings / interop to lookup the function and call it at runtime. Here's an example:
((goog.object/getValueByKeys js/window #js ["foo" "core" "square"]) 3)
The use of ^:export and :advanced is covered here. If you know that you are using :simple or less, then you can simply use JavaScript interop to call the functions of interest, without needn't to use ^:export.
Note that there is no general solution that would let you look up a function by name at runtime under :advanced without somehow putting some aspect of that function into your code at compile time. (In fact, if a function is not referenced in a way that Google Closure Compiler can statically, see, the function implementation will be completely eliminated as dead code.) In the above, ns-publics grabs all the vars for a namespace at compile time, rolling your own lookup map sets up static code to refer to the function value, and using ^:export statically arranges to make the name of the function persist into runtime.
You need to use it like this:
((resolve 'inc) 5)) => 6
or, deconstructed a bit:
(let [the-fn (resolve 'inc)]
(the-fn 7))
=> 8
If you have the function name as a string, use the symbol function to convert from string => symbol (from clojuredocs.org):
user=> ((-> "first" symbol resolve) [1 2 3])
1
And, never forget the Clojure CheatSheet!
I'm trying to pass a function to a method and then pass parameters to the method I passed when calling it, but if I pass more than one parameter then the method fails with an error:
function debugMeStuffs($someBlah, $somePoo) {
Write-Host $someBlah
Write-Host $somePoo
}
function invokeOnHosts ([scriptblock]$funcToCall, $param1, $param2, $startRange, $endRange) {
#Param($funcToCall)
$i = $startRange
for($i = [int]$startRange; $i -le $endRange; $i++) {
# HOW DO I MAKE THIS WORK WITH MULTIPLE PARAMETERS?!?!?!?
$funcToCall.Invoke('blah' 'poo')
}
}
invokeOnHosts $function:debugMeStuffs "param1" "param2" 4 7
Things I've tried:
$funcToCall("blah" "poo")
$funcToCall('blah' 'poo')
$funcToCall.Invoke("blah" "poo")
$funcToCall.Invoke('blah' 'poo')
$funcToCall 'blah' 'poo'
$funcToCall.Invoke 'blah' 'poo'
$funcToCall "blah" "poo"
$funcToCall.Invoke "blah" "poo"
None of the above seem to work. Is there something else I need to do to make this work?
.Invoke() is a .NET method, so the usual method-call syntax applies: you need
parentheses - (...) - around the list of arguments
you must separate the arguments with ,
$funcToCall.Invoke('blah', 'poo')
This contrasts with PowerShell's own syntax for calling cmdlets and functions, which is shell-like[1]:
no (...) around the argument list
arguments must be separated with spaces.
& $funcToCall blah poo # equivalent of the method call above.
A command such as the above is parsed in argument mode, which is why quoting the arguments in this simple case is optional.
Note the need for &, PowerShell's call operator, which is needed to execute the script block stored in $funcToCall; this is generally necessary for invoking a command stored in a variable, and also for command names / paths that are quoted.
Given that it's easy to get confused between PowerShell's command syntax and .NET's method syntax, it's best to stick with PowerShell-native features[2], if possible.
That said, being able to call methods on .NET types directly is a wonderful extensibility option.
To help avoid accidental use of method syntax when calling PowerShell commands, you can use Set-StrictMode -Version 2 or higher, but note that that entails additional strictness checks.
[1] PowerShell is, after all, a shell - but it is also a full-featured scripting language that offers near-unlimited access to the .NET framework.
Reconciling these two personalities is a difficult balancing act, and the shell-like command-invocation syntax is a frequent problem for newcomers with a programming background, given that the rest of the language looks like a traditional programming language and that calling methods on .NET types does use the traditional syntax.
[2] This means preferring PowerShell's cmdlets, functions, and operators to use of the underlying .NET types' methods; doing so also usually provides rewards you with operating at a higher level of abstraction.
I am trying to determine whether a given argument within a macro is a function, something like
(defmacro call-special? [a b]
(if (ifn? a)
`(~a ~b)
`(-> ~b ~a)))
So that the following two calls would both generate "Hello World"
(call-special #(println % " World") "Hello")
(call-special (println " World") "Hello")
However, I can't figure out how to convert "a" into something that ifn? can understand. Any help is appreciated.
You might want to ask yourself why you want to define call-special? in this way. It doesn't seem particularly useful and doesn't even save you any typing - do you really need a macro to do this?
Having said that, if you are determined to make it work then one option would be to look inside a and see if it is a function definition:
(defmacro call-special? [a b]
(if (#{'fn 'fn*} (first a))
`(~a ~b)
`(-> ~b ~a)))
This works because #() function literals are expanded into a form as follows:
(macroexpand `#(println % " World"))
=> (fn* [p1__2609__2610__auto__]
(clojure.core/println p1__2609__2610__auto__ " World"))
I still think this solution is rather ugly and prone to failure once you start doing more complicated things (e.g. using nested macros to generate your functions)
First, a couple of points:
Macros are simply functions that receive as input [literals, symbols, or collections of literals and symbols], and output [literals, symbols, or collections of literals and symbols]. Arguments are never functions, so you could never directly check the function the symbol maps to.
(call-special #(println % " World") "Hello") contains reader macro code. Since reader macros are executed before regular macros, you should expand this before doing any more analysis. Do this by applying (read-string "(call-special #(println % \" World\") \"Hello\")") which becomes (call-special (fn* [p1__417#] (println p1__417# "world")) "Hello").
While generally speaking, it's not obvious when you would want to use something when you should probably use alternative methods, here's how I would approach it.
You'll need to call macroexpand-all on a. If the code eventually becomes a (fn*) form, then it is guaranteed to be a function. Then you can safely emit (~a ~b). If it macroexpands to eventually be a symbol, you can also emit (~a ~b). If the symbol wasn't a function, then an error would throw at runtime. Lastly, if it macroexpands into a list (a function call or special form call), like (println ...), then you can emit code that uses the thread macro ->.
You can also cover the cases such as when the form macroexpands into a data structure, but you haven't specified the desired behavior.
a in your macro is just a clojure list data structure (it is not a function yet). So basically you need to check whether the data structure a will result is a function or not when it is evaluated, which can be done like show below:
(defmacro call-special? [a b]
(if (or (= (first a) 'fn) (= (first a) 'fn*))
`(~a ~b)
`(-> ~b ~a)))
By checking whether the first element of the a is symbol fn* or fn
which is used to create functions.
This macro will only work for 2 cases: either you pass it a anonymous function or an expression.
I know:
C++, Java, and tons others:
object.method() , object.method(arg)
Objective-C:
[object method] , [object method:arg]
Smalltalk:
object method , object method: arg
PHP, Perl
object->method(), object->method(arg)
$object->method;
$object->method($arg1, $arg2, ...);
OCaml
object#method , object#method args
CLOS
(method object) , (method object arg)
And even, I have used:
method object
method(object)
Can you name other alternatives ways of sending a message to an object ( I think that would be the correct term ) in different programming languages?
Refer to
Wikipedia: Comparison of OO Languages -> Method call style
Most interesting may be the "generic function" notation - in CLOS (the O-O part of Common Lisp), they're called like (method object arg) (with defgeneric for method as a generic function and defmethod to define its specialization/override); in languages more oriented to algebraic notation, like Dylan and Python (e.g. with PEAK), the calls will be more like method(object, arg) instead.
The coolest thing about the generic/method approach (which Common Lisp pioneered, AFAIK) is that it doesn't have to treat the first object differently from all the others -- method dispatch can happen upon any combination of arguments' runtime types, not just the runtime type of one of the arguments (single-argument dispatching is obviously covered as a special case;-). Say goodbye to Visitor and all other variants (cfr e.g. this paper) which basically try to simulate multiple dispatching in single-dispatch languages!-)
Just for completeness’ sake:
While VB.NET normally uses the same style as C#, one can also omit the parentheses on methods and on parameterless functions/constructors:
stream.WriteLine "Hello"
Dim x = stream.ReadLine
But the IDE will automatically add the parentheses for parametrized method calls (oddly enough, it won’t do the same for functions and constructors).
Furthermore, VB.NET still knows the (somewhat antique) Call keyword which once again forces parentheses around parametrized method calls:
Call stream.WriteLine("Hello") '// is the same as'
stream.WriteLine("Hello")
'// This won’t compile:'
Call stream.WriteLine "Hello"
in Perl, its:
$object->method;
$object->method($arg1, $arg2, ...);
and the potentially dangerous indirect object syntax (which wont work if you have a sub named method in the current scope:
method $object $arg1, $arg2...;
Following on from Alex Martelli's comment, multi methods in the JVM language Nice
FiniteStateMachineMultiMethodExample
VisitorPatternMultiMethodExample
and other examples.