lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Having trouble understanding optional and variable amount of argumen


From: Urs Liska
Subject: Re: Having trouble understanding optional and variable amount of arguments
Date: Fri, 9 Mar 2018 22:44:53 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0

Hi Stéfano,


Am 09.03.2018 um 16:48 schrieb Stefano Troncaro:
A few thoughts

I think macro definitions for all the define- functions can be avoided like this:
\version "2.19.80"
\include "oll-core/package.ily"

#(define-macro (with-options func-def-proc vars preds rulings . body)
   `(,func-def-proc ,(append '(opts) vars) ,(append '(ly:context-mod?) preds)
      (let* ((rules ,rulings)
             (props (context-mod->props rules #t opts)))
        . ,body)))

testRules =
#(with-options define-void-function () ()
   `((ind ,number? 5)
     (target ,symbol?)
     (payload)
     (accepted-arg ,fraction? opt)
     (accepted-without-type opt)
     (msg ,string? "No message given"))
   (pretty-print props))

\testRules \with {
  msg = "Something"
  unk = "Unknown option"
  target = something
%  accepted-arg = 7/4
%  accepted-without-type = #(ly:make-moment 3/16)
}


Yes, I like this very much. You still have the familiar define-X-function with the args and predicates in the usual place, but with 'with-options' you signal that there will be a rule set for options.

With respect on how to write the rule-set, based on your input I see a few possibilities:

1) A very slight modification of its current form
   `((rule-enforcement strict)
     (ind ,number? 5)
     (target ,symbol?)
     (payload)
     (accepted-arg ,fraction? opt)
     (accepted-without-type opt)
     (msg ,string? "No message given"))
This keeps the "list of lists" approach you wanted.

I'm not 100% sure if I have a strong opinion between this and your hierarchical suggestion. But I *think* I like this one more.
I agree with you that options with a default value become optional and should not have to be flagged as such separately.

I think that the parsing of the options could be set to 'flexible' by default and it can be made strict adding that as the first element of the list. Alternatively, a rule-enforcement element may be required.

I suggest to require the statement about rule-enforcement because otherwise one would probably always confuse things.
But *if* we require it - and as the first element - it doesn't have to be a list (which would BTW rule out an option with that name) but can be a symbol:
   `(strict
     (ind ,number? 5)
     ...
 

2) Optional arguments could be anticipated with an opt instead of having it at the end:
   `((ind ,number? 5)
     (target ,symbol?)
     (payload)
     (opt accepted-arg ,fraction?)
     (opt accepted-without-type)
     (msg ,string? "No message given"))
This requires the same input as before but feels clearer to my eyes.

I partially disagree. Not with the idea of having the flag in front of the list but with using a/that symbol. Apart from ruling out 'opt as an option name (OK, in my implementation 'opt couldn't be used as a *default*) I think this is confusing because you have a first "column" of payload - opt - msg.

What do you think about
   `(strict
     (ind ,number? 5)
     (target ,symbol?)
     (payload)
     (? accepted-arg ,fraction?)
     (? accepted-without-type)
     (msg ,string? "No message given"))
?
Technically it's still a symbol but indicates much better the idea of "optional".

I see what you mean about the POV defining what can be called optional. As I described earlier, the "caller" POV feels more intuitive for me but that may just be personal taste. Without more opinions it's difficult to tell.

3) The "elimination of unnecessary parens" is indeed a very minor thing. That approach felt instantly familiar because it resembles how function predicates are defined, in that only the proc is written when there is no default value, but the proc and the default value are parenthesized when they are needed together. In the same logic, I thought the key could be by itself when all one needed was to communicate "this is optional" or "this is required", and parenthesized with more information when needed.

My previous idea was merely just these three together. As you pointed out, I think the first is the one of real importance, and the others are more in the realm of QOL suggestions.

For now I'll await your thoughts, and I'll open a pull request later.

I'd be glad about a PR along these lines!

Best
Urs


2018-03-09 4:29 GMT-03:00 Urs Liska <address@hidden>:


@Urs
I've thought about this some more. I don't know if you were interested in wrapping the functions that use opts and props in a macro, but I noticed a lot of redundancy so I gave it a try.
\version "2.19.80"
\include "oll-core/package.ily"

#(define-macro (define-void-function-with-options vars preds rulings . body)
   `(define-void-function ,(append '(opts) vars) ,(append '(ly:context-mod?) preds)
      (define rules
        ,rulings)
      (let ((props (context-mod->props rules #t opts)))
        . ,body)))

testRules =
#(define-void-function-with-options () ()
   `((ind ,number? 5)
     (target ,symbol?)
     (payload)
     (accepted-arg ,fraction? opt)
     (accepted-without-type opt)
     (msg ,string? "No message given"))
   (pretty-print props))

\testRules \with {
  msg = "Something"
  unk = "Unknown option"
  target = something
%  accepted-arg = 7/4
%  accepted-without-type = #(ly:make-moment 3/16)
}
Again, tell me if you find it convenient.


Hm.
The definition of testRules looks pretty good. What I'm not so sure about is that this would actually imply creating -with-options variants of *all* define- macros, and I'm not sure if that would add unnecessary complexity compared to "simply" calling context-mod->props within a function definition.

Actually, I start thinking if this doesn't call for a "proper" solution to be added to LilyPond itself. Of course I'm hijacking ly:context-mod? which is semantically there for a different purpose.
What I would like to see is a different predicate, say, ly:properties? that internally is a simple key-value alist but that can be entered with the same \with {} syntax.

Urs

_______________________________________________
lilypond-user mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/lilypond-user




reply via email to

[Prev in Thread] Current Thread [Next in Thread]