Soliciting feedback for specify operation on dynamic clojure hosts

60 views
Skip to first unread message

Herwig Hochleitner

unread,
May 3, 2013, 8:29:15 PM5/3/13
to cloju...@googlegroups.com
I would like to reignite discussion on my design proposal for specify, http://dev.clojure.org/display/design/specify+i.e.+reify+for+instances
and to reach sufficient consensus  to get it on track or get it declined.

The reason I'm posting this to dev and not to clojurescript is, that it affects clojure variants on other dynamic hosts aswell.

Apart from whether we actually want specify on dynamic hosts, there seem to be two main issues:

1. Should there be a public kernel operation (specify*), that allows attaching closures as protocol methods directly, rather than relying on gclosure lambda lifting and verifying that it works for relevant use cases in every gclosure release? 
2a. If yes, should specify* take multiple single-arity closures for method arities
2b. or should it take a regular multi-arty closure and pry the multiple single-arity closures from it, which the compiler generates for a multi-arity fn

2a implies (specify* {-meth {1 f1 2 f2}})
2b implies (specify* {-meth f})

the most recent patchset 02xx on the ticket for the proposal implements 2a
rebased to current master

kind regards

David Nolen

unread,
May 3, 2013, 9:09:49 PM5/3/13
to cloju...@googlegroups.com
The main reason for the non-movement on your implementation specify is that the patch does far more than what Rich proposed - which was that specify would be like reify but for single objects - this implies *cloning*. If the patch had followed the original limited idea it would have likely been adopted already as an experimental feature. At which point people could have given it a spin and provided feedback on its utility in practice and on its limitations.

specify & specify* appears to mutate the target object w/o cloning, this is OK for prototypes, but broken for instances defeating the whole point of the original idea as far as I can tell.

Applying the first patch produces a version of ClojureScript where I'm unable to confirm the mutating behavior of specify & specify* - there are many errors when trying to run the CLJS REPL.

David


--
You received this message because you are subscribed to the Google Groups "Clojure Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure-dev...@googlegroups.com.
To post to this group, send email to cloju...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojure-dev?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Herwig Hochleitner

unread,
May 4, 2013, 11:29:15 AM5/4/13
to cloju...@googlegroups.com
2013/5/4 David Nolen <dnolen...@gmail.com>
The main reason for the non-movement on your implementation specify is that the patch does far more than what Rich proposed

To be fair, I had no Idea what Rich proposed, or what even you wanted to see in a design. I have had tried to scratch my own itch with a thing called extend-instance, which was supposed to modify the instance. Then you told me Rich had come up with a name for that: http://dev.clojure.org/jira/browse/CLJS-398
I then continued developing for my own needs with the specify name: http://dev.clojure.org/jira/browse/CLJS-414
And I created a design page to allow others to review the design.
 
- which was that specify would be like reify but for single objects - this implies *cloning*.

It certainly doesn't from a technical perspective. In fact the mutation of the original object is by design, to allow efficient specification of a list of 10000 json objects.
 
If the patch had followed the original limited idea it would have likely been adopted already as an experimental feature.

Didn't know about that. I blame myself for not having asked for more information.
 
specify & specify* appears to mutate the target object w/o cloning, this is OK for prototypes, but broken for instances defeating the whole point of the original idea as far as I can tell.

It might appear so from a design perspective, but it's actually the other way round:
When cloning is an option, there is no issue at all, since you can control the prototype of objects you new yourself, hence give it whatever type you please.
specify makes sense, as soon as you get a bunch of objects from a source, that transfers ownership to you, but doesn't allow you to control the prototype.
One such example is the usage of JSONP, where objects are always created by eval.

Also it makes really good sense as the bottom of the protocol / type stack. As you might have noted, the patches substantially cleanup extend-type (the current bottom of cljs types), by having it specify the prototype.
 
Applying the first patch produces a version of ClojureScript where I'm unable to confirm the mutating behavior of specify & specify* - there are many errors when trying to run the CLJS REPL.

I'm very sorry, the naive rebase I did for the 02xx patchset, didn't work, since the js* operation seems to be gone. I'll update and fix till tomorrow.

In the meantime, could you elaborate on the point of the original idea and Rich's proposal?

kind regards

David Nolen

unread,
May 4, 2013, 11:42:22 AM5/4/13
to cloju...@googlegroups.com
On Sat, May 4, 2013 at 11:29 AM, Herwig Hochleitner <hhochl...@gmail.com> wrote:
To be fair, I had no Idea what Rich proposed, or what even you wanted to see in a design. I have had tried to scratch my own itch with a thing called extend-instance, which was supposed to modify the instance. Then you told me Rich had come up with a name for that: http://dev.clojure.org/jira/browse/CLJS-398
I then continued developing for my own needs with the specify name: http://dev.clojure.org/jira/browse/CLJS-414
And I created a design page to allow others to review the design.

Sorry I probably should have linked to the few places where Rich mentioned `specify` - the devnotes in the CLJS repo and the old thread about getting `reify` in to CLJS. I never moved forward with `specify` myself since I was able to implement a fairly efficient `reify` without it. I believe Rich suggested that with `specify` you could implement `reify`. He didn't mention `extend-type`, and in fact in the devnotes in the repo for `extend` it says "Maybe not?".
 
 - which was that specify would be like reify but for single objects - this implies *cloning*.

It certainly doesn't from a technical perspective. In fact the mutation of the original object is by design, to allow efficient specification of a list of 10000 json objects.

The question here is whether a powerful object mutation feature like this isn't better provided by an external library.
  
specify & specify* appears to mutate the target object w/o cloning, this is OK for prototypes, but broken for instances defeating the whole point of the original idea as far as I can tell.

It might appear so from a design perspective, but it's actually the other way round:
When cloning is an option, there is no issue at all, since you can control the prototype of objects you new yourself, hence give it whatever type you please.
specify makes sense, as soon as you get a bunch of objects from a source, that transfers ownership to you, but doesn't allow you to control the prototype.
One such example is the usage of JSONP, where objects are always created by eval.

This seems at odds to the Clojure/ClojureScript ethos of keeping the cloning work out of the users hands.
 
Also it makes really good sense as the bottom of the protocol / type stack. As you might have noted, the patches substantially cleanup extend-type (the current bottom of cljs types), by having it specify the prototype.

Cleanup is nice but not a compelling reason to include or not include a language enhancement.

David

Herwig Hochleitner

unread,
May 4, 2013, 4:40:58 PM5/4/13
to cloju...@googlegroups.com
2013/5/4 David Nolen <dnolen...@gmail.com>
Sorry I probably should have linked to the few places where Rich mentioned `specify` - the devnotes in the CLJS repo and the old thread about getting `reify` in to CLJS. I never moved forward with `specify` myself since I was able to implement a fairly efficient `reify` without it. I believe Rich suggested that with `specify` you could implement `reify`. He didn't mention `extend-type`, and in fact in the devnotes in the repo for `extend` it says "Maybe not?".

Thanks, I'll look it up before fixing the merge issues. Maybe it will inform a specific api style for specify*?
 
The question here is whether a powerful object mutation feature like this isn't better provided by an external library.

An excellent point and if it could be done, I probably wouldn't even have opened a ticket (which I now know was the wrong way to start this anyway).
Alas, any library needs a way to get from protocol methods to js methods.
specify* is pretty much an api to access the builtin name mangling.

In fact, I would be happy to just publish specify* and leave everything else to libs, since specify* is what I really need and use.
 
This seems at odds to the Clojure/ClojureScript ethos of keeping the cloning work out of the users hands.

JSONP keeps the cloning out of the user's hand aswell. It's also Clojure's ethos that platform integration trumps cleanliness.
Right now Clojurescript prevents objects that haven't originated from a Clojurescript constructor from interacting with protocols, even though it's technically possible.

Cleanup is nice but not a compelling reason to include or not include a language enhancement.

At this point we really only should be discussing whether and in which form we want to make the functions public, that fell out by refactoring. 
(because it's also clojure's ethos that the only person allowed allowed to write fns of more than 15 lines, is Rich Hickey ;-)

You may notice, that my specify impl doesn't do anything "new". It's just the bit's and pieces, pulled out from the two page long extend-type *macro*:

While promoting my patches, I've tried all the time to tiptoe around the fact, that the implementation should have looked like that in the first place, because I think it's enough if reviewers notice such potentially embarassing facts. But now that the milk has been spilt, just take a look at the original implementation by Rich https://github.com/clojure/clojurescript/blob/b75730da8abc3abc6134d8dd9ec426ab792d3662/src/clj/cljs/core.clj#L42
then look at the current implementation, weep, and ask yourself (or git) how we got there.

My specify branch is still based on master in october, but you can check it out from github and play with it, until I fixed it for current master.

David Nolen

unread,
May 4, 2013, 5:22:18 PM5/4/13
to cloju...@googlegroups.com
On Sat, May 4, 2013 at 4:40 PM, Herwig Hochleitner <hhochl...@gmail.com> wrote:
 
The question here is whether a powerful object mutation feature like this isn't better provided by an external library.

An excellent point and if it could be done, I probably wouldn't even have opened a ticket (which I now know was the wrong way to start this anyway).
Alas, any library needs a way to get from protocol methods to js methods.
specify* is pretty much an api to access the builtin name mangling.

In fact, I would be happy to just publish specify* and leave everything else to libs, since specify* is what I really need and use.

Need and use for what? Your design page is sparse and I can imagine many other ways to do what you've done. For example, I find the explicit arities in specify* to be warty. I haven't seen any thought in 7 months on how this wart might be removed.

The design page mostly documents your *solution*. That's not what design pages are for.
 
 JSONP keeps the cloning out of the user's hand aswell. It's also Clojure's ethos that platform integration trumps cleanliness.
Right now Clojurescript prevents objects that haven't originated from a Clojurescript constructor from interacting with protocols, even though it's technically possible.

Cleanup is nice but not a compelling reason to include or not include a language enhancement.

But what about the likely common use case of wanting to clone + extend? Why not `specify` and `specify!`? Again I don't see much thought on this on the design page.
 
At this point we really only should be discussing whether and in which form we want to make the functions public, that fell out by refactoring. 
(because it's also clojure's ethos that the only person allowed allowed to write fns of more than 15 lines, is Rich Hickey ;-)

You may notice, that my specify impl doesn't do anything "new". It's just the bit's and pieces, pulled out from the two page long extend-type *macro*:

Tip toe around what? Do you think you'll offend anybody? :) 

Yes it's quite gnarly but what does that have to with your actual feature proposal? As such your patch is a minor enhancement plus a new bottom level macro that doesn't have nearly enough design work IMO.

A contribution that I would feel more positive about:

* A separate enhancement patch that implements your nice bit of refactoring - no other change
* A much more fleshed out design page - no patches

David

David Nolen

unread,
May 4, 2013, 5:40:50 PM5/4/13
to cloju...@googlegroups.com
Let's move the discussion over to the design page, I've made some comments there.

Herwig Hochleitner

unread,
May 5, 2013, 2:08:23 AM5/5/13
to cloju...@googlegroups.com
2013/5/4 David Nolen <dnolen...@gmail.com>
Need and use for what? Your design page is sparse and I can imagine many other ways to do what you've done. For example, I find the explicit arities in specify* to be warty. I haven't seen any thought in 7 months on how this wart might be removed.

Lists via JSONP were my motivating use case. It's for an app in a mobile browser field, therefore the emphasis on efficiency.
As I understand confluence is a wiki, I'm fully ok with you writing alternating design ideas into the page, inline or in sections as you see fit.
I'll comment on the explicit arities in the wiki.
 
The design page mostly documents your *solution*. That's not what design pages are for.

I'll fully grant that.

I'll try elaborating it a bit. 

But what about the likely common use case of wanting to clone + extend? Why not `specify` and `specify!`? Again I don't see much thought on this on the design page.

`specify` and `specify!`, of course! Now that you say it, it seems obvious. I'll buy that.
 
Tip toe around what? Do you think you'll offend anybody? :) 

Tip toe around calling other people's code crap or telling them how their tools can be used. But I think you are right, I could still be a lot more edgy, before starting to seriously cross people.
 
Yes it's quite gnarly but what does that have to with your actual feature proposal?

Its refactoring should inform the design of specify, since we don't want to add any complexity, and mostly stick to labeling things that are already there.
 
As such your patch is a minor enhancement plus a new bottom level macro that doesn't have nearly enough design work IMO.

Tend to agree. Frankly, I was partially aware, that the names and APIs I chose were crap. I half expected you to see how the parts from current gnarly thing fell into place in my patches and to merge it with an added commit, setting the new names private, until we figured out the proper API.
That would have been nice to keep it from bitrotting, but it's a completely unresonable expectation, of course, now that I think of it.

A contribution that I would feel more positive about:

* A separate enhancement patch that implements your nice bit of refactoring - no other change
* A much more fleshed out design page - no patches

I should have done that. Frankly, what bit me was the 'need it now' effect, right there.

thanks for your feedback!
Reply all
Reply to author
Forward
0 new messages