How to check for DOM .contains? in clojurescript? - dom

In JS one does document.some_element.contains(other_element) to find whether an element is contained within another.
How to do this in Clojurescript/Hiccup/Reagent framework?
I have tried:
(js/contains some-element another-element)
(-> js/contains some-element another-element)
(.-contains some-element another-element)
(js/.contains some-element another-element)

The proper syntax to call a method on an object is (.contains a b) which would be equal to a.contains(b). The js/ namespace is reserved for accessing the "global "scope and thus cannot be used with locals.
(.contains a b) can also be written as (. a (contains b)), which is actually what the .contains expands to after the compiler is done with it.
There is also .. which allows chaining interop forms, so (.. js/document -some-element (contains another-element)) would match document.some_element.contains(another_element). Note that js/document here is accessing the global document.
-> can also be used by requires repeating the ., eg (-> js/document .-some-element (.contains another-element)).

Related

Why can't code in #:fallbacks refer to the generic methods?

This code:
(require racket/generic)
;; A holder that assigns ids to the things it holds. Some callers want to know the
;; the id that was assigned when adding a thing to the holder, and others don't.
(define-generics holder
(add-new-thing+id holder new-thing) ;returns: holder id (two values)
(add-new-thing holder new-thing) ;returns: holder
#:fallbacks
[(define (add-new-thing holder new-thing) ;probably same code for all holder structs
(let-values ([(holder _) (add-new-thing+id holder new-thing)])
holder))])
produces this error message:
add-new-thing+id: method not implemented in: (add-new-thing+id holder new-thing)
I'm able to fix it by adding a define/generic inside the fallbacks, like this:
#:fallbacks
[(define/generic add add-new-thing+id)
(define (add-new-thing holder new-thing)
(let-values ([(holder _) (add holder new-thing)])
holder))])
but this seems to add complexity without adding value, and I don't understand why one works and the other doesn't.
As I understand #:fallbacks, the idea is that the generic definition can build methods out of the most primitive methods, so structs that implement the generic interface don't always need to reimplement the same big set of methods that usually just call the core methods with identical code—but they can override those "derived" methods if needed. say, for optimization. That's a very useful thing*—but have I misunderstood fallbacks?
It seems strange that fallbacks code couldn't refer to the generic methods. Isn't the main value of fallbacks to call them? The documentation for define/generic says that it's a syntax error to invoke it outside a #:methods clause in a struct definition, so I'm probably misusing it. Anyway, can someone explain what are the rules for code in a #:fallbacks clause? How are you supposed to write it?
* The Clojure world has something similar, in the potemkin library's def-abstract-type and deftype+, but not as well integrated into the language. potemkin/def-map-type illustrates very nicely why fallbacks—as I understand them, anyway—are such a valuable feature.
The second version of your code is correct.
The first version of your code would work if you had a fallback definition of add-new-thing+id, but because you are referring to any possible definition of that method outside of the fallback scope, you need to import it.
It effectively feels a bit repetitive to have to define the generic again inside the fallback clause. It's because #:fallbacks works the same way as #:methods, and therefore has the same behavior of overriding generics with its own definitions.
To make it explicit that you are overriding a method, you need to "import" it inside your clause, using define/generic (which is not really defining anything, it is just importing the generic into the context).
As the documentation for define/generic says:
When used inside the method definitions associated with the #:methods keyword, binds local-id to the generic for method-id. This form is useful for method specializations to use generic methods (as opposed to the local specialization) on other values.
Then in define-generics:
The syntax of the fallback-impls is the same as the methods provided for the #:methods keyword for struct.
Which means #:fallbacks has the same behavior as using #:methods in a struct.
Why?
The logic behind that behavior is that method definition blocks, like #:methods and #:fallbacks have access to their own definitions of all the generics, so that it's easy to refer to your own context. To explicitly use a generic from outside this context, you need to use define/generic.

Class finalization: how to avoid creating dummy instances?

I've run into a problem that a third-party library needs to act on a class as if it was finalized. After some reading I understand the motivation behind this mechanism, but I don't really know how it functions.
Example:
(make-instance 'expression :op '+ :left 'nan :right 'nan)
(defmethod normalize-expression ((this expression))
(optima:match this
((optima::or (expression :left 'nan) (expression :right 'nan)) 'nan)
((expression :op op :left x :right y) (funcall op x y))))
Unless I add the first line, the function will not compile, giving me this error:
; caught ERROR:
; (during macroexpansion of (SB-PCL::%DEFMETHOD-EXPANDER NORMALIZE-EXPRESSION ...))
; SB-MOP:CLASS-SLOTS called on #<STANDARD-CLASS EXPRESSION>, which is not yet finalized.
; See also:
; AMOP, Generic Function SB-MOP:CLASS-SLOTS
optima is a pattern-matching library, the (expression :op op ...) is matching instances of class expression against the given pattern. I don't know in much details, but it looks like it needs to know what are the accessors defined for this class, and it looks like that information is not available until it is finalized. So, is there any way to sidestep the finalization problem?
The class will not be extended (at least not in this project, and it's not being planned). It doesn't hurt that much to create a dummy instance... it is just an ugly solution, so I hoped to find a better one. Also, perhaps, I'd get some more info on finalization, which is good too :)
Forgetting to ensure class finalization seems to be quite common mistake when using MOP.
In lisp, classes are defined in two "phases":
Direct class definition
Effective class definition
Direct class definition is isomorphic to defclass form. It has class name, names of superclasses, list of direct slots (i.e., slots defined on this particular class but on its superclasses).
Effective class definition contains all information needed for compiler/interpreter. It contains list of all class slots (including those defined on superclasses), class instance layout, references to accessor methods, etc.
Process of transforming direct class definition to effective class definition is called class finalization. Since CLOS supports redefining classes, finalization might be called multiple times for a class. One of the reasons why finalization is delayed is because class may be defined before its superclasses are defined.
Regarding your particular problem: is seems that optima:match should ensure that class is finalized before trying to list its slots. This can be done with two functions: class-finalized-p (to check whether class needs finalization) and finalize-inheritance to actually perform finalization. Or you can use utility function closer-mop:ensure-finalized. (closer-mop is a library for portable usage of CLOS MOP).
E.g.,:
(c2mop:ensure-finalized (find-class 'expression))

In common-lisp how can i override/change evaluation behaviour for a specific type of object?

In common-lisp, I want to implement a kind of reference system like this:
Suppose that I have:
(defclass reference () ((host) (port) (file)))
and also I have:
(defun fetch-remote-value (reference) ...) which fetches and deserializes a lisp object.
How could I intervene in the evaluation process so as whenever a reference object is being evaluated, the remote value gets fetched and re-evaluated again to produce the final result?
EDIT:
A more elaborate description of what I want to accomplish:
Using cl-store I serialize lisp objects and send them to a remote file(or db or anything) to be saved. Upon successful storage I keep the host,port and file in a reference object. I would like, whenever eval gets called on a reference object, to first retrieve the object, and then call eval on the retrieved value. Since a reference can be also serialized in other (parent) objects or aggregate types, I can get free recursive remote reference resolution by modyfing eval so i dont have to traverse and resolve the loaded object's child references myself.
EDIT:
Since objects always evaluate to themselves, my question is a bit wrongly posed. Essentially what I would like to do is:
I would like intercept the evaluation of symbols so that when their value is an object of type REFERENCE then instead of returning the object as the result of the symbol evaluation, to return the result of (fetch-remote-value object) ?
In short: you cannot do this, except by rewriting the function eval and modifying your Lisp's compiler. The rules of evaluation are fixed Lisp standard.
Edit After reading the augmented question, I don't think, that you can achieve full transperency for your references here. In a scenario like
(defclass foo () (reference :accessor ref))
(ref some-foo)
The result of the call to ref is simply a value; it will not be considered for evaluation regardless of its type.
Of course, you could define your accessors in a way, which does the resolution transparently:
(defmacro defresolver (name class slot)
`(defmethod ,name ((inst ,class))
(fetch-remote-reference (slot-value inst ',slot))))
(defresolver foo-reference foo reference)
Edit You can (sort of) hook into the symbol resolution mechanism of Common Lisp using symbol macros:
(defmacro let-with-resolution (bindings &body body)
`(symbol-macrolet ,(mapcar #'(lambda (form) (list (car form) `(fetch-aux ,(cadr form)))) bindings) ,#body))
(defmethod fetch-aux ((any t)) any)
(defmethod fetch-aux ((any reference)) (fetch-remote-reference any))
However, now things become pretty arcane; and the variables are no longer variables, but magic symbols, which merely look like variables. For example, modifying the content of a variable "bound" by this macro is not possible. The best you can do with this approach is to provide a setf expansion for fetch-aux, which modifies the original place.
Although libraries for lazy evaluatione and object persistence bring you part of the way, Common Lisp does not provide a portable way to implement fully transparent persistent values. Lazy or persistent values still have to be explicitly forced.
MOP can be used to implement lazy or persistent objects though, with the slot values transparently forced. It would take a change in the internals of the Common Lisp implementations to provide general transparency, so you could do e.g. (+ p 5) with p potentially holding a persistent or lazy value.
It is not possible to directly change the evaluation mechanisms. You would need to write a compiler for your code to something else. Kind of an embedded language.
On the CLOS level there are several ways to deal with it:
Two examples:
write functions that dispatch on the reference object:
(defmethod move ((object reference) position)
(move (dereference reference) position))
(defmethod move ((object automobile) position)
...))
This gets ugly and might be automated with a macro.
CHANGE-CLASS
CLOS objects already have an indirection, because they can change their class. Even though they may change their class, they keep their identity. CHANGE-CLASS is destructively modifying the instance.
So that would make it possible to pass around reference objects and at some point load the data, change the reference object to some other class and set the slots accordingly. This changing the class needs to be triggered somewhere in the code.
One way to have it automagically triggered might be an error handler that catches some kinds of errors involving reference object.
I would add a layer on top of your deserialize mechanism that dispatches based on the type of the incoming data.

Recommended macros to add functionality to Clojure's defrecord constructor?

defrecord in clojure allows for defining simple data containers with custom fields.
e.g.
user=> (defrecord Book [author title ISBN])
user.Book
The minimal constructor that results takes only positional arguments with no additional functionality such as defaulting of fields, field validation etc.
user=> (Book. "J.R.R Tolkien" "The Lord of the Rings" 9780618517657)
#:user.Book{:author "J.R.R Tolkien", :title "The Lord of the Rings", :ISBN 9780618517657}
It is always possible to write functions wrapping the default constructor to get more complex construction semantics - using keyword arguments, supplying defaults and so on.
This seems like the ideal scenario for a macro to provide expanded semantics. What macros have people written and/or recommend for richer defrecord construction?
Examples of support for full and partial record constructor functions and support for eval-able print and pprint forms:
http://david-mcneil.com/post/765563763/enhanced-clojure-records
http://github.com/david-mcneil/defrecord2
David is a colleague of mine and we are using this defrecord2 extensively in our project. I think something like this should really be part of Clojure core (details might vary considerably of course).
The things we've found to be important are:
Ability to construct a record with named (possibly partial) parameters: (new-foo {:a 1})
Ability to construct a record by copying an existing record and making modifications: (new-foo old-foo {:a 10})
Field validation - if you pass a field outside the declared record fields, throw an error. Of course, this is actually legal and potentially useful, so there are ways to make it optional. Since it would be rare in our usage, it's far more likely to be an error.
Default values - these would be very useful but we haven't implemented it. Chas Emerick has written about adding support for default values here: http://cemerick.com/2010/08/02/defrecord-slot-defaults/
Print and pprint support - we find it very useful to have records print and pprint in a form that is eval-able back to the original record. For example, this allows you to run a test, swipe the actual output, verify it, and use it as the expected output. Or to swipe output from a debug trace and get a real eval-able form.
Here is one that defines a record with default values and invariants. It creates a ctor that can take keyword args to set the values of the fields.
(defconstrainedrecord Foo [a 1 b 2]
[(every? number? [a b])])
(new-Foo)
;=> #user.Foo{:a 1, :b 2}
(new-Foo :a 42)
; #user.Foo{:a 42, :b 2}
And like I said... invariants:
(new-Foo :a "bad")
; AssertionError
But they only make sense in the context of Trammel.
Here is one approach: http://david-mcneil.com/post/765563763/enhanced-clojure-records

Questions about Lists and other stuff in Clojure

I have a few questions concerning Lists, classes and variables in clojure.
This may seem quite stupid but how do I access elements in a List ?
I'm coding a program that allows you to manipulate a phonebook; You can add an entry, delete one or print the information about one. This leads me to two questions :
Is there a way to create a class "entry" that would contain "name" "adress" "phone number" variables ? or is that impossible in clojure (and functional programming in general ?) If I can't have a List of objects containing that information, how would I go about this task ?
I was thinking of having a function that reads user input to know what the user wants to do (add entry, delete entry or print info) then calls the appropriate function to do that which calls back the first function when it's done. Is passing as a parameter the List of entries to each function the right thing to do ?
This may seem quite stupid but how do I access elements in a List ?
(nth coll index)
For example:
(nth [1 2 3 4] 2) ; -> 3 (since it uses zero-based indexing)
Is there a way to create a class "entry" that would contain "name" "adress" "phone number" variables ? or is that impossible in clojure (and functional programming in general ?) If I can't have a List of objects containing that information, how would I go about this task ?
It's possible in Clojure, but unidiomatic. In Clojure, the basic abstraction for data entities are maps, not classes (except for some corner cases where direct interoperation with Java frameworks is needed). So you would just use a map:
(def entry {:name "x" :address "y" :phone-number "z"})
To access the item's name, you either use
(:name entry)
or
(get entry :name)
The former works only when the keys of the map are keywords, the latter works with all types of key.
So for your example, your data model (the phonebook) would be a seq (say, a list or a vector) of such maps.
I was thinking of having a function that reads user input to know what the user wants to do (add entry, delete entry or print info) then calls the appropriate function to do that which calls back the first function when it's done. Is passing as a parameter the List of entries to each function the right thing to do?
Since your model consists of only one main data structure (the phone book seq), passing it as an arg is certainly an appropriate way to design your functions. If you expect to have more kinds of top-level containers (i.e. for a more real world application), I'd recommend looking into the Application Context Pattern, which will look a bit intimidating at first (at least it did for me, and it contains a lot of Clojure-specific jargon), but is well worth the effort to learn.
Have you considered buying the book Programming Clojure? A pdf version is only $21 US. Well worth the money in my opinion.
(entry :name)
will also work as well when accessing a map. So you have three ways of accessing an element of a map by using the keyword:
(entry :name)
or
(:name entry)
or
(get entry :name)
where
(def entry {:name "x" :address "y" :phone-number "z"})
As Rayne mentioned, the second form is only possible if the key is a keyword. You can use the other "short" form with keys of other types:
user=>(def my-map {"a" "b" "c" "d"})
user=>(my-map "c")
"d"
user=>(get my-map "a")
"b"
For part one of your question, if you will be accessing the items in your list with (nth ...) you may consider using a vector. Vectors are not like arrays in other languages. for instance chopping them and adding new elements to the end are also efficient in addition to numerical indexing. Under the hood the arrays are actually very similar to maps.
best of all arrays are functions of an index:
(def a [1 2 3 4])
(a 2) ==> 3
for parts 2 and 3 pmf's answer cover them very nicely.