I can document a function like this:
f: func [
"a description"
arg1 [string!] "a description of an argument 1"
][
arg1
]
I can use ?/help in order to retrieve informations about the the function (a description, a usage, the argument list, a description of each argument and it's type)
? f
USAGE:
F arg1
DESCRIPTION:
a description
F is a function value.
ARGUMENTS:
arg1 -- a description of an argument 1 (Type: string)
I cannot document dialects like this. Is there an automatic way to document dialects (like func does)? Do I have to do this manually?
There's nothing for it currently, but it's a good idea. So good that someone has suggested it before. :-)
Do I have to do this manually?
You can manually write a new generator which defines your "dialect spec" format. Then either do something like give it a HELP command, or extend HELP to recognize it.
Very short example to demonstrate a group of techniques which may come in handy in doing something like this (not all expected to be obvious, rather to hint at the flexibility):
make-dialect: function [spec [block!] body [block!]] [
return function ['arg [block! word!]] compose/deep/only [
case [
arg = 'HELP [
foreach keyword (spec/keywords) [
print [keyword "-" {your help here}]
]
]
block? arg [
do func [arg] (body) arg
]
'default [
print "Unrecognized command. Try HELP."
]
]
]
]
So there's your function that takes a dialect spec and makes a function. Once you've got your generator, using it can be less manual:
mumble: make-dialect [keywords: [foo baz bar]] [
print ["arg is" mold arg]
]
>> mumble help
foo - your help here
baz - your help here
bar - your help here
>> mumble [<some> [dialect] {stuff}]
arg is [<some> [dialect] {stuff}]
The techniques used here are:
Soft Quoting - Usually you would have to say mumble 'help to "quote" the help as a lit-word! to get it to pass the word! to mumble (as opposed to running the default HELP command). But because arg was declared in the generated function as 'arg it was "soft quoted"...this means that words and paths will not be evaluated. (Parens, get-words, and get-paths still will be.) It's a tradeoff because it means that if someone has a variable they want to pass you they have to say :var or (var) as the argument instead of just var (imagine if the block to pass the dialect is in a variable) so you don't necessarily want to use it...but I thought it an interesting demo to make mumble help work without the lit-word!
Deep Composition - The spec and the body variables which are passed to make-dialect only exist as long as make-dialect is running. Once it's over, they'll be gone. So you can't leave those words in the body of the function you are generating. This uses COMPOSE/DEEP to evaluate parens in the body before the function generator runs to make the result, effectively extracting the data for the blocks and stitching them into the function's body structure.
Reusing Function's Binding Work - The generated function has a spec with a parameter arg that didn't exist at the call site of make-dialect. So arg has to be rebound to something, but what? It's possible to do it manually, but one easy way is to let FUNC do the work for you.
Those are some of the techniques that would be used in the proposed solution, which seeks to not only document dialects but provide an easy method by which their keywords might be remapped (e.g. if one's Rebol system has been configured for another spoken language).
Related
I've got this function here:
my #modifiers = <command option>;
sub triple(|c(Str:D $app1!, Str:D $app2!, Str:D $key! where .chars == 1, Str:D $mod where ($mod ~~ any #modifiers) = 'command' )) {
print_template(|c);
}
sub print_template(*#values) {
...work done here...
}
The problem I'm having is if I call it without the 4th argument, with something like triple 'App1', 'App2', 'p';, the default $mod argument does not get passed on to the print_template argument.
Is there a way to accomplish this?
For full context, this is the toy program here: https://paste.debian.net/1226675/
TL;DR 1. An explanation of the problem. 2. A DRY solution. 3. The DRYest solution: a parameters-capture function.
An explanation of the problem
A call proceeds in two steps:
Construct a call, without knowing what routine will hear the call. This includes constructing a capture of the call arguments. This capture is already done and dusted, immutable, before step 2.
See what routine candidates there are that might bind to the call. Try to bind the capture to their signatures. Some parameters in a routine's signature might specify defaults in case an argument is missing.
So, given a capture c, you can't alter it to make up for any arguments that aren't in it, and Raku doesn't automatically create a new capture that pretends any arguments that aren't in it are now in it. Instead you're going to have to manually add the missing values.
A DRY solution
The string 'command' appears twice in the suggested solution in your answer.
One way to write a DRY solution is to use the whole capture, which will include all the passed arguments, and then append any parameters for which corresponding arguments were not passed. That is to say, instead of:
my \d = \(|c[0..2], c[3] // 'command');
write this:
my \d = \(|c, |($mod if not c[3]));
The DRYest solution: a parameters-capture function
Ultimately what your scenario calls for is a function which completely ignores the arguments used to call a routine and instead just creates a new capture consisting of all of a routine's parameters. Then one could just write, say:
print_template(|parameters-capture);
That strikes me as pretty non-trivial. It would mean walking a routine's parameter data. This would presumably go via something like &?ROUTINE.signature.params. But &?ROUTINE is a compile-time variable and is relative to the current routine, so how do you get to that in a function you've called from the routine whose parameters you're interested in? And even if you can get to it, how do you get from compile-time parameter data structures to the run-time values that end up bound to the parameters? It's all way past my paygrade. It's perhaps a lot easier to do this sort of guts coding than it is in, say, the Perl world, where it means C coding, but still.
OK, based on responses in IRC, this does not appear to be possible. One suggested workaround:
sub triple(|c(Str:D $app1!,
Str:D $app2!,
Str:D $key! where .chars == 1,
Str:D $mod where ($mod ~~ any #modifiers) = 'command' )) {
my \d = \(|c[0..2], c[3] // 'command');
print_template(|d);
}
Another way to get to the same overall result (and probably the way I'd go) would be to split this out into a multi and dispatch based on the number of parameters. Here's one way that could look (with validation of the shared params moved to the proto:
my #modifiers = <command option>;
proto triple(Str:D, Str:D, Str:D $ where .chars == 1, $?) {*}
multi triple(|c($, $, $, Str:D $ where any #modifiers)) { print_template |c }
multi triple(|c($, $, $)) { print_template |c, 'command' }
sub print_template(*#values) {
# work done here
}
say triple 'App1', 'App2', 'p';
I am a newbie in Kotlin. I am curious about the difference of labeled this in Kotlin with prefix # or postfix #.
I have just seen a code which writes SignInActivity#this, which seems to work exactly same as this#SignInActivity.
Are these two exactly the same thing? If not, what is the difference between the two?
I was trying to do some research on *#this form, but I couldn't find any reference on it. All I could find was this official doc which demonstrates this#*. It will be nice if anybody could share me with the correct reference I should go to.
SignInActivity# this is just another expression for this, with the functionality of defining an unnecessary label called SignInActivity(which has nothing to do with actual class name) for this.
According to Kotlin grammar documentation:
labelReference (used by atomicExpression, jump)
: "#" ++ LabelName
;
labelDefinition (used by prefixUnaryOperation, annotatedLambda)
: LabelName ++ "#"
;
hello# is just a label with the name "hello" (for Returns and Jumps) ,
whereas #hello is a reference for the labeled loop or block.
These expressions combined can be used as below:
loop# for (i in 1..100) {
for (j in 1..100) {
if (...) break#loop //jump to loop#
}
}
SignInActivity#this means SignInActivity.this (Java)
this#SignInActivity means - using the SignInActivity context instead a local context (usually is in closures).
Let us say I have a situation like this:
;; Capture whatever the print word pointed to into a variable
outer-print: :print
foo: context [
;; within foo, override print and implement in terms of outer-print
print: func [value] [
outer-print "About to print"
outer-print value
outer-print "Done printing"
]
]
I can do this, or if I have more than one thing I want from the outer context I could capture it explicitly:
;; Capture current context into something called outer
outer: self
foo: context [
;; within foo, override print and implement in terms of outer/print
print: func [value] [
outer/print "About to print"
outer/print value
outer/print "Done printing"
]
]
Is this the right idiom, or is there a better way of doing it? Are there circumstances where this might not give me what I expect?
this is good style, especially the second, which is more flexible as it allows you to mass-effect all uses of the outer print, without any ambiguity. when using direct binding, it may occur that the word outer-print is redefined or the context changes between two calls to make foo [] and in the end, points to two different bindings.
static symbol resolving
For the sake of completeness there is a third alternative which doesn't require any extra words to be setup. I don't have a proper naming for it, feel free to suggest a better title.
This method defies any binding issues down the line because you use the function value directly:
foo: context compose/deep [
;; within foo, override print and implement using native print directly
print: func [value] [
(:print) "About to print"
(:print) value
(:print) "Done printing"
]
]
Now the interesting part is if you SOURCE the inner print function:
>> p: get in foo 'print
>> SOURCE P
== p: func [value][native "About to print" native value native "Done printing"]
see how the native value of print is used directly in the body, instead of a word referring to it.
This is, in fact, probably the closest we can get to some form of compilation in pure REBOL. instead of constantly using symbols to fetch and evaluate, we can simply statically resolve them manually, using reduce or compose as in the above.
pros:
It can never be hi-jacked by some advanced and malicious binding code, i.e. even if there are no direct word bounds to PRINT in ANY and ALL contexts, you still have a direct reference to the original function in your body.
cons:
Its a very static way to code, and isn't very "Rebolish".
The
;; Capture current context into something called outer
comment suggests that you think there is some "current context" in Rebol. That is false. Every word has got its own context. Thus, there are cases when your
outer: self
code doesn't work as you expect. For example, let's suppose that you want to access two variables, 'print and 'set. It is possible for the words to have different "outer" contexts. In that case the trick will be certain to not work for at least one of the words, but it may, in fact, not work for both.
I know you can type declare arguments and returns on functions
some-func: function [
"some func"
number [ integer! ]
] [
result [ integer! ]
] [
help number
return number
]
some-func 1
some-func "blah"
NUMBER is an integer of value: 1
** Script error: some-func does not allow string! for its number argument
How about object properties though?
o: make object! [
a [string!]
b [integer!]
c [o2]
none
]
o2: make object! [
c [string!]
]
an-object: make o [
a: 3.141
b: "an integer"
c: "blah"
]
help an-object
N-OBJECT is an object of value:
a decimal! 3.141
b string! "an integer"
c string! "blah"
I've seen the type declaration on properties as examples, but is it just for documentation?
This is a really good question, and something I've thought about for years. It turns out that Rebol's internal object storage mechanism can handle this, but there's no way of expressing it in source code. Why not you ask? Here's why:
Rebol currently has the concept of name-value pairs. That's how contexts and objects are expressed. However, it is often desirable for objects to include other information that's not just a name or value. The datatype is a good example. Other examples are comments attached to values, and protections/permissions on values (such as allowing read and write).
So, the problem becomes: how many various features do we want to support in the language syntax, and specifically how would we do that? It gets further complicated by the "optional" characteristic of these features. So, you can't really use positional semantics to describe the object. That means adding a syntactic method, which means adding keywords (because Rebol really tries to avoid punctuation.)
So, as a result, the source form would become fairly verbose, and I think we could question whether it would be worth the benefit we'd get from allowing the feature in the first place.
So, this is a case where the simple principle of Rebol takes precedence over feature creep.
All that said, if you've got an idea for a simple method of doing it, let it be known!
It's just for documentation .. type checking is only done on functions.
Any idea why the following doesn't work? (R3)
o: make object! [
foo: does [do "bar"]
bar: does [print "hello from bar"]
]
o/foo
** Script error: bar has no value
** Where: catch either -apply- do foo
** Near: catch/quit either var [[do/next data var]] [data]
Try this:
o: make object! [
foo: does [do get bind load "bar" self]
bar: does [print "hello from bar"]
]
o/foo ;this will work
You need that BINDing because your "bar" lives in the object, not in global scope.
Check this out as well:
my-func: does [print "ok"]
o: make object! [
foo: does [do "my-func"]
bar: does [print "hello from bar"]
]
o/foo ;this will work too
You need to LOAD it because it is a string, but it has to be a word to be BINDed.
So these will work too (put them in your object):
do get bind to-word "bar" self
or
do get bind 'bar self
No Scope!!!?
The reason do "self/bar" cannot know where to find 'BAR is because there is no scope in Rebol (not in the traditional CS meaning at least).
Words in Rebol only have meaning once they have been statically bound to a context. This automagically occurs when you 'MAKE an object, so many people don't even realize it even after years of use.
Here are the steps (loosely) when an object (a.k.a. context) is created.
It picks up all the root set words in its spec (in this case [FOO: BAR:] )
Adds them to its current internal words (SELF: by default, more if you are using an object as basis)
Then binds all the words in the block (hierarchicaly) to those set-words it added to its spec.
Executes the block.
So you see, once you execute the block its too late, the words already got assigned their meaning, which allows the interpreter to ask for their values (which could trigger an expression evaluation, hence the E in REBOL).
Global, cause that all there really is once executing.
DO and LOAD cannot automatically bind to anything but the global context... because there is no such thing as the "current context" like you'd have in traditional OOP and imperative languages (remember, no scope). Really, once its executing, that information doesn't exist anymore, unless you bound the "current" context to a word... which is what 'SELF does, but to be bound it has to already be loaded, which, when executing a string, never occured.
clueless functions
I'll finish by adding that it may not be obvious at first sight, but while it was binding the Object spec block, it still didn't know what FOO and BAR really were. in fact, the only way FOO and BAR could access the 'O object, is because their function block, when it was run thru 'MAKE, got bound to the object... yep, before it even knew it was a function. then if the function defined its own locals, it would re-bind its body block to those new locals.. because you guessed it... a function creates its own inner context, which gets the same MAKE treatment (but without the internal SELF word).
I hope this helps clear things in a more obvious light.
here is a proof that code isn't scoped:
a: make object! [
data: "HAHAHAAAAA!!!"
action: does [print self/data]
]
b: make object! [
data: "BUMBLING BEHEMOT"
action: does [print self/data]
]
b/action: get in a 'action
; this will print HAHAHAAAAA!!!
b/action
To explain moliad's answer a bit more, see the following explanation:
REBOL words carry a reference to their context with them. It’s not
where a word is evaluated that makes the difference, but where it’s
declared.
from http://blog.revolucent.net/2009/07/deep-rebol-bindology.html
Here is a very good example:
x: 0
b: [] loop 3 [use [x] [x: random 100 append b 'x]]
;== [x x x] <-- there are three X which looks same words (and they are same actually)
reduce b
;== [95 52 80] <-- but they have different values in their contexts
probe x
;== 0 <-- in global context, it has another value as well
This looks weird at first look, but actually it is not. USE creates a new context each time in the LOOP, we set X (in the context the USE created) to a value, then APPEND the WORD (not the value!) to a block.
All the words that we append to the block carries their own contexts with them, but they look same word.
When we REDUCE (or PRINT etc.), when we GET their values in their own contexts, we see that they all have different values!