Am 08.03.2018 um 16:42 schrieb Stefano Troncaro:
@Urs
Great! I tested it a bit and it seems to be working as intended.

I have forgotten one thing that I've only halfway completed by now: "accepted" properties without type checking. Currently, if the "strict" flag is set, only keys present in the rules are accepted. But these are also expected, so what's still missing is a way to specify rules as optional so we can filter unknown properties but still have optional ones. I've started on it and I think I know how to do it but I had to leave the computer.


I'm curious about the "complains about the wrong type for 'target'" part though. I remembered that words when typed like that were symbols, so I did this to check it out:

    \version  "2.19.80" \include  "oll-core/package.ily" #(use-modules  (oop 
goops))

    obj = something

    testType =
    #(define-void-function  (obj) (scheme?)
        (display  (format  "'~a' is of type '~a'\n"  obj (class-of obj))))

    \testType \obj checkIfSym =
    #(define-void-function  (obj) (symbol?)
        (display  (format  "'~a' of type '~a' passed the symbol? test\n"  obj 
(class-of obj))))

    \checkIfSym \obj testTypeInCM =
    #(define-void-function  (cm) (ly:context-mod?)
        (let  ((props (context-mod->props cm)))
          (for-each  (lambda  (prop)
                      (testType (cdr  prop)))
            props)))

    \testTypeInCM  \with  { target =NoteHead anothertarget ="NoteHead" 
yetanothertarget = #'NoteHead
    } %Gives this output: %'something' is of type '#<<class> <string>
    7f52818c4d40>' %'something' of type '#<<class> <symbol>
    7f52818c4c60>' passed the symbol? test %'NoteHead' is of type
    '#<<class> <string> 7f52818c4d40>' %'NoteHead' is of type
    '#<<class> <string> 7f52818c4d40>' %'NoteHead' is of type
    '#<<class> <symbol> 7f52818c4c60>'

Also, I thought that predicates were just type checks. But in the second example it looks like the symbol? predicate made scheme think of the object as a symbol instead of a string. I find this kind of confusing, is there something else going on that I'm not seeing?

If I'm not mistaken completely this part may seem somewhat ambigous.
If you simply type some characters (in LilyPond) they are initially a string. But if you make the parser "expect" something at a given point it will parse it like that. if you define an argument for a define-something-function as symbol? then plain characters will be parsed as a symbol. But in the key=value parts of a \with block they are parsed as string. This is something one just has to know - just like the fact that you have to enclose a string in quotes if it contains spaces or similar issues.

Best
Urs



@David
Thank you. The define-syntax and syntax-rules thing looked easier to understand at first glance so I tried to use that. I'll experiment with macros then.

2018-03-08 9:21 GMT-03:00 Urs Liska <li...@openlilylib.org <mailto:li...@openlilylib.org>>:



    Am 08.03.2018 um 10:35 schrieb Urs Liska:



    Am 08.03.2018 um 08:44 schrieb Urs Liska:

    Hi Stéfano,


    Am 08.03.2018 um 07:26 schrieb Stefano Troncaro:
    @Urs
    I looked into your examples and \with blocks are very useful.

    You said earlier that you were thinking about how to make it so
    that the context-mod could have required arguments, default
    values for missing ones, and even predicates. I was thinking
    that context-mod->props could be made to accept this
    information as an optional argument. Then it can return a
    'curated' list of props or raise warnings/errors. That I think
    shouldn't be difficult to do.

    Great idea, thank you. Actually it's pretty much along the lines
    I was already thinking about - but I hadn't thought of the
    obvious of doing it directly in context-mod->props.

    Although I'm undecided on what would be a convenient way of
    storing the 'requirement data'. The obvious one to me is an
    alist with a structure like this: `((key1 . (required . #t))
    (key2 . ((default . 9) (pred . ,number?))) ...), but I'm not
    sure. What do you think?


    The "required" is not necessary because if a key shows up in
    this list it implicltly is required. One addition I'd do is add
    a keyword 'strict. When that's present any keys *not* in the
    list are rejected.

    #(define rules
        `((key1 .                ;; type plus default
            ((type . ,number?)
             (default . 5)))
          (key2 .                ;; only the type
            ((type . ,symbol?)))
          (key3)                 ;; required without type or default
          (key4 .                ;; default value but no type
            ((default . #t)))
          ))

    #(define rules2
        (cons
         'strict
         `((key1 .
             ((type . ,number?)
              (default . 5)))
           (key2 .
             ((type . ,symbol?))))))
With rules1 the function would simply check for the presence of
    the specified keys while with rules2 unknown keys would be
    rejected (issue a warning and be dropped)

    Defining the rules structures is somewhat picky - but this won't
    be done in the *user* documents but basically in packages or
    similar library structures, so it should be ok.

    I'll give that a shot as I can use this in a current project -
    but of course I'd also review pull requests ;-)

    Best
    Urs

    I have implemented the above structure as predicates for use with
    context-mod->props in
    
https://github.com/openlilylib/oll-core/commit/2ef019f643cbb719bdba15bd28107bb7f12124da
    
<https://github.com/openlilylib/oll-core/commit/2ef019f643cbb719bdba15bd28107bb7f12124da>
    (on the typed-props branch), but so far it doesn't do anything
    yet. But as you said, Stéfano, this isn't very hard to do. I just
    wanted to push that before you'd start working on it yourself.

    Urs


    OK, I've completed the code but didn't merge it to master yet.
    The interface can now be used like this:

    %%%
    \version "2.19.80"

    \include "oll-core/package.ily"

    #(define rules
        `((ind ,number? 5)
          (target ,symbol?)
          (payload)
          (msg ,string? "No message given")))

    testRules =
    #(define-void-function (opts) (ly:context-mod?)
        (let ((props (context-mod->props rules #t opts)))
          (pretty-print props)))

    \testRules \with {
       msg = "Something"
       unk = "Unknown option"
       target = something
    }
    %%%

    This correctly assigns the 'msg' property, sets 'ind' to the
    default 5, complains about the wrong type for 'target' and the
    missing 'payload' property. The failing properties are discarded
    and will presumably cause errors further down the line, but that
    is the responsibility of a package or a document author.

    Best
    Urs

    _______________________________________________
    lilypond-user mailing list
    lilypond-user@gnu.org <mailto:lilypond-user@gnu.org>
    https://lists.gnu.org/mailman/listinfo/lilypond-user
    <https://lists.gnu.org/mailman/listinfo/lilypond-user>



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

Reply via email to