Open meijeru opened 6 years ago
I offer the following questions for discussion:
. should there be a prescribed order as suggested above, and if not, should the order be completely free?
. should there be at most a single return spec?
. can the type information, if present, be empty, and if so, does it mean any-type!
?
can the type information, if present, be empty, and if so, does it mean
any-type!
?
currently it is default!
not any-type!
, I suggest it's left like this (default!
doesn't contain unset!
and unset!
can be used to make vararg funcs, which is a bad hack ☺)
This is noted. Another question for discussion is whether the /local
refinement must be last or not.
@meijeru I believe it should be:
<return-spec> ::= return: [<typeset-element>*] <argument-doc>°
@greggirwin, worth to extend your PR, because some functions in Red codebase now appear to have a malformed spec.
>> func [return: [] "malformed!"][]
*** Script Error: invalid function definition: return:
*** Where: func
*** Stack:
@9214, yes, it makes sense to allow a doc-string for return:
.
As a contribution to the discussion: the parse rule for function spec in %help.red
suggests that (1) refinements and return spec(s) may occur in any order, (2) there may be more than one return spec, and (3) the local refinement must be last. Is this a good interpretation?
(2) More than one return:
doesn't make any sense to me. In fact it's forbidden by both R/S compiler and Red compiler. Interpreter's logic is currently a mess that allows senseless things like this: f: func [return: [integer!] /x return: [string!]] []
to be considered valid yet as you know it does not accept docstrings for returns, but I don't believe multiple returns are intentional even there.
(1&3) Order of return and locals is only enforced by R/S right now, the other spec formats are orderless by their nature (using any [...]
block) so these are likely bugs in help
. I can see two lines of reasoning though:
Personally I'm more (60 to 40) inclined to support orderlessness.
Help
doesn't currently support multiple return
specs. The last one wins.
We should consider the func spec dialect as a work in progress. The basic rules are in place, but advanced and new capabilities need to be considered, as we are discussing here.
A reason to support more than one return is to specify what type may be returned if a given refinement is used. Is that useful enough to support it? If so, the compiler should be able to enforce it. It could also collect the various return types and group them for you into a single return typeset.
A reason to support more than one return is to specify what type may be returned if a given refinement is used. Is that useful enough to support it? If so, the compiler should be able to enforce it
So imagine I declare a function like this:
f: func [
x return: [integer!]
/s return: [string!]
/b return: [block!]
/u return: [unset!]
What type will the result of f/s/b/u 100
be? Typeset from all of its returns?
It's an interesting idea to consider. But no. I'm not buying it yet. So much complexity... for what? Besides, I have a feeling that enforcing this will only be possible by inserting a runtime check into the function code, resulting in extra overhead. Count me as an opponent ☺
Great example. For my part, I am good with keeping things simple here, because the user can always spec the type and put notes in the code. If we want to change that in the future, nothing breaks. And if we want a strict language, make it a dialect.
I'm wondering if Red is going to support the attributes block, like REBOL did, e.g. func [[throw] x y] [...]
, or is there another design planned for this.
Worth addressing in function spec's (re)-design:
>> has ['x :y][]
== func [/local 'x :y][]
>> func [/local 'x :y][]
== func [/local 'x :y][]
This doesn't affect semantics in any way, and words with the same symbols are counted as locals.
I've noticed that some function specs include the (incredibly useful) signature for function!
args, but it's not currently possible to create a function!
using the same spec. Maybe only red/system supports it currently?
>> function probe spec-of :parse []
["Process a series using dialected grammar rules"
input [binary! any-block! any-string!]
rules [block!]
/case "Uses case-sensitive comparison"
/part "Limit to a length or position"
length [number! series!]
/trace
callback [function! [
event [word!]
match? [logic!]
rule [block!]
input [series!]
stack [block!]
return: [logic!]
]]
return: [logic! block!]
]
*** Script Error: invalid type specifier: event word! match? logic! rule block! input series! stack block! return logic!
*** Where: function
*** Stack:
The order of elements (argument specs, optional argument specs, and return spec(s)) in a function spec block is insufficiently determined -- there is no formal documentation, and the compiler and the intepreter treat this apparently differently, so that a formal spec cannot be derived from there. The most constraining formulation would be the following:
Here ° means optional and * means zero or more, as usual.