Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to alias a function/macro as another one #234

Closed
vemv opened this issue Apr 17, 2022 · 5 comments
Closed

Ability to alias a function/macro as another one #234

vemv opened this issue Apr 17, 2022 · 5 comments

Comments

@vemv
Copy link
Contributor

vemv commented Apr 17, 2022

Context

One may use a composition of styles:

:style [:community :justified :map-nl :pair-nl :binding-nl :rod :hiccup]

Under such composition, the answer to the question "what is the style that will be applied to defn?" can easily be dynamic, and not even serializable:

{:set-by "repl or api call 4 specified :style :rod",
 :value  [:guided-body {:list {:option-fn #<Fn@36cf939d clojure.core/partial[fn]>}}]}

i.e., this value is not something users can immediately comprehend or copy/paste.

Use case

I have defn-like constructs, say com.example/defun or defn-instrumented.

I'd want to be able to tell zprint "whenever you find these, please consider them equivalent to defn".

So, if hypothetically I changed my :style [:community :justified :map-nl :pair-nl :binding-nl :rod :hiccup] vector to something else, I would have not to update anything else - com.example/defun and defn-instrumented would remain homogeneous, relative to defn.

Proposal

Assuming I'm requesting something new at all, the following might be an elegant API?

{:fn-map {"defn-instrumented" "defn", "com.example/defun" "defn"}}

Or perhaps these could deserve instead a dedicated key, e.g. :aliases/:equivalent.

What do you think?

Thanks - V

@vemv
Copy link
Contributor Author

vemv commented Apr 17, 2022

I tried:

:fn-map {"defn-xxxx" (-> zprint.config/default-zprint-options
                         :style-map
                         :rod
                         :fn-map
                         (get "defn"))}

So far it's not working, although it might be for unrelated reasons

@kkinnear
Copy link
Owner

Interesting problem, thanks for bringing it up. Before we get into the longer term solutions, I'm not sure why what you show, above, didn't work for you. Both of these work for me. The first one uses the current options map, and the second one (which is close to what you tried), uses a building block of the original configuration.

(set-options! {:fn-map {"newdefn" (-> (zprint.config/get-options)
                                      :style-map
                                      :rod
                                      :fn-map
                                      (get "defn"))}})

(set-options! {:fn-map {"moredefn" (-> zprint.config/default-zprint-options
                                       :style-map
                                       :rod
                                       :fn-map
                                       (get "defn"))}})

That is certainly one approach, and not a bad one. But your original issue was to support something where if people changed the which styles were used (which might well change what is configured in the :fn-map), then it would be nice if all of the things "like defn" were still "like defn". And this transfer of configuration from "defn" to "newdefn" (or whatever) only works at the time at which it is executed. So it is nice, but only after the :style has been done. Now, in a single call to set-options! the styles are applied first, so at least that would work. But if the style is changed (or another style is invoked) in a later call to set-options!, those changes would not be transferred to the things "like defn".

So, yes, something like what you proposed in the first post would be a better answer. And I agree, we do need an answer for this particular use-case. My first thought was identical to yours, actually. Keying off of the type of the value in the :fn-map, with a string value meaning "go look that up and use what you find there". The only challenge I see to that would be to keep track of the lookups to break cycles, or there is an infinite loop waiting to happen. But that isn't particularly hard to do.

So, yes, I want to think on it a bit more, but I'll do something that will solve this problem, and probably just what you have proposed.

I'm also thinking of making a :fn-type-map (perhaps with a different name), where a fn-type is looked up before it is
used. In this map, you would be able to define a new fn-type, and also you would be able to associate an options map with a fn-type (new or existing). I think this would allow some increased flexibility, since people could define a new fn-type. So, you could define a function type of :my-defn, and then have styles affect that :fn-type instead of affecting the functions in the :fn-map directly. You could then define any number of functions in the :fn-map as :my-defn, and when the definition of :my-defn changed, all of these functions would change accordingly. I've been thinking about this for a year or so now, and I think it may be time actually build this.

That sort of addition doesn't negate the need for the aliasing within the :fn-map directly, but it would be another way to solve some of those problems. I think both will be necessary to implement and utilize the approach you've suggested in Issue #229. Which is what I'm presently working on.

@vemv
Copy link
Contributor Author

vemv commented Apr 18, 2022

I'm not sure why what you show, above, didn't work for you

Probably it was something with my setup which is somewhat contrived, will give it another go later. I'd assume it works, particularly after your confirmation.

So, yes, I want to think on it a bit more, but I'll do something that will solve this problem, and probably just what you have proposed.

Happy about the hammocking!

I think both will be necessary to implement and utilize the approach you've suggested in Issue #229. Which is what I'm presently working on.

Glad to hear! Thanks so much for your work.

@kkinnear
Copy link
Owner

kkinnear commented Aug 2, 2022

The alias support is now available in 1.2.4. Thanks for the idea!

From CHANGELOG.md:

You can now alias one funtion in the :fn-map to another. The key is (as always) the function name as a string, and the value is another function name, also as a string. Thus {:fn-map {"mydefn" "defn"}} will cause the function "mydefn" to be formatted however "defn" is formatted.

@vemv
Copy link
Contributor Author

vemv commented Aug 3, 2022

Thanks much! Awesome news.

I'll be trying it out. I certainly owe you a big round of QAing/feedback - that is not forgotten :)

@vemv vemv closed this as completed Aug 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants