Hi Thomas,

I like your idea on how to provide default values for optional
arguments. I use arguments quite a bit in that way, and if FUNC
did that automatically it would make the code a bit cleaner.

The /tags refinement would make code involving calling functions with
complicated refinements much easier to understand. All you would have to
do is supply the one /tags refinement, and you wouldn't have to worry
about which order the tags are in versus which order the arguments are in.
The refinements would be right next to the values.


A similar capability is already built into some functions, such as
OPEN, where you can do:

    file: open/mode %test.txt [binary new]

meaning the same as:

        file: open/binary/new %test.txt

(This was from a message on the list from Jeff.)

Unfortunately this /mode refinement doesn't seem to allow passing of
arguments. It would be even more useful if you could do:

        file: open/mode %test.txt [new with #"^L"]

to specify page-break as the line terminator.

Just a couple more ideas. I looked at the source of the function
you created:

my-function: func [
    "My function"
    a [string!] "required argument"
    /b "A refinement" /c c-value [string!]
                        {An optional argument with the default value "Hello"}
    /tags tag-list [block!]
    "A block of words to set, ie [size: 50]"][
    c: either c [c-value] ["Hello"]
    if tags [
        do bind (compose/deep tag-list) 'tags
    ]
    print [a c]
]

The part

        c: either c [c-value] ["Hello"]

Is not a good idea, since if somewhere else in the function you appended
something to C, the string "Hello" would change. Also, there's a slightly
more elegant way to do this check that I learned from a message from
Gabriele. (Oops, I see he answered before me.) Maybe the resulting code
should be something like:

        c: any [c-value copy "Hello"]

But your function-making function would have to discriminate between
datatypes that needed to be copied, and those that didn't.


All this reminds me of another little idea I keep pushing:

>> unset!: (type?)
== unset!
>> say-hello: func[a [string!] b [string! unset!]]
    [b: any [all [value? 'b b] "there!"] print [a b]]
>> say-hello "Hey"
Hey there!
>> say-hello "Hey" "man!"
Hey man!

This kind of optional argument has the disadvantage that something
that comes after might be taken as an unintended argument:

>> say-hello "Hey" s2: square-root 2
** Script Error: say-hello expected b argument of type: string unset.
** Where: say-hello "Hey" s2: square-root 2

so it's best in this case to always use the optional argument within
a program, unless you wrap it in parens, or it's at the end of a block:

>> (say-hello "Hey") s2: square-root 2
Hey there!
== 1.4142135623731
>> if now/time < 1:00 [say-hello "Hey"] s2: square-root 2
Hey there!
== 1.4142135623731

Nice talking to you,
Eric

Reply via email to