Is that one argument or none for a Perl 6 block? - arguments

What is the Perl 6 way to tell the difference between an argument and no argument in a block with no explicit signature? I don't have any practical use for this, but I'm curious.
A block with no explicit signature puts the value into $_:
my &block := { put "The argument was $_" };
The signature is actually ;; $_? is raw. That's one optional argument. The #_ variable isn't defined in the block because there is no explicit signature.
There's the no argument, where $_ will be undefined:
&block(); # no argument
But there's also a one argument situation where $_ will be undefined. A type object is always undefined:
&block(Int);
But, an $_ with nothing in it is actually an Any (rather than, say, Nil). I can't tell the difference between these two cases:
&block();
&block(Any);
Here's a longer example:
my $block := {
say "\t.perl is {$_.perl}";
if $_ ~~ Nil {
put "\tArgument is Nil"
}
elsif ! .defined and $_.^name eq 'Any' {
put "\tArgument is an Any type object"
}
elsif $_ ~~ Any {
put "\tArgument is {$_.^name} type object"
}
else {
put "\tArgument is $_";
}
};
put "No argument: "; $block();
put "Empty argument: "; $block(Empty);
put "Nil argument: "; $block(Nil);
put "Any argument: "; $block(Any);
put "Int argument: "; $block(Int);
Notice the no argument and Any argument forms show the same things:
No argument:
.perl is Any
Argument is an Any type object
Empty argument:
.perl is Empty
Argument is Slip type object
Nil argument:
.perl is Nil
Argument is Nil
Any argument:
.perl is Any
Argument is an Any type object
Int argument:
.perl is Int
Argument is Int type object

As far as I know, the only way to know the number of parameters passed without an explicit signature, is to use #_ inside the body, which will generate a :(*#_) signature.
my &block := { say "Got #_.elems() parameter(s)" };
block; # Got 0 parameter(s)
block 42; # Got 1 parameter(s)
dd block.signature; # :(*#_)
Yeah, the good old #_ is still there, if you want it :-)

{ put $_.perl }
Is sort of similar to this: (which doesn't work)
-> ;; $_? is raw = CALLERS::<$_> { put $_.perl }
Since the default is default for $_ outside of the block is Any, if you don't place anything into $_ before you call the function you get Any.
To get something at all similar where you can tell the difference use a Capture :
my &foo = -> ;; |C ($_? is raw) {
unless C.elems {
# pretend it was defined like the first Block above
CALLER::<$_> := CALLER::CALLERS::<$_>
}
my $called-with-arguments := C.elems.Bool;
if $called-with-arguments {
say 'called with arguments';
} else {
say 'not called with arguments';
}
}

Here's how I solved this. I'd love to do this in a cleaner way but the cleverness of the language gets in the way and I have to work around it. This works for positional parameters but there are deeper shenanigans for named parameters and I won't deal with those here.
I had another question, Why does constraining a Perl 6 named parameter to a definite value make it a required value?, where the answers clarified that there are actually no optional parameters. There are merely parameters that have a default value and that there is an implicit default value if I don't explicitly assign one.
The crux of my problem is that I want to know when I gave the parameter a value and when I didn't. I give it a value through an argument or an explicit default. An implicit default is a type object of the right type. That's Any if I didn't specify a type. That implicit default must satisfy any constraint I specify.
The first goal is to tightly constrain the values a user can supply when they call code. If an undefined value is not valid then they shouldn't be allowed to specify one.
The second goal is to easily distinguish special cases in the code. I want to reduce the amount of special knowledge some part of the deeper code needs to know.
I can get the third case (where I know there was no argument or suitable default) by explicitly assigning a special value that I know can't be anything other meaningful thing. There's a value that's even more meaningless than Any. That's Mu. It's the most undefined values of all undefined values. The Any is one of two subtypes of Mu (the other is Junction) but you should almost never see a Mu end up in one of your values in normal code. Undefined things in user code start at Any.
I can create a constraint that checks for the type I want or for Mu and set a default of Mu. If I see a Mu I know there was no argument and that it's Mu because my constraint set that.
Since I'm using Mu there are some things I can't do, like use the === operator. Smart matching won't work because I don't want to test the inheritance chain. I can check the object name directly:
my $block := ->
$i where { $^a.^name eq 'Mu' or $^a ~~ Int:D } = Mu
{
say "\t.perl is {$i.perl}";
put do given $i {
when .^name eq 'Mu' { "\tThere was no argument" }
when Nil { "\tArgument is Nil" }
when (! .defined and .^name eq 'Any') {
"\tArgument is an Any type object"
}
when .defined {
"\tArgument is defined {.^name}"
}
default { "\tArgument is {.^name}" }
}
};
put "No argument: "; $block();
put "Empty argument: "; try $block(Empty); # fails
put "Nil argument: "; try $block(Nil); # fails
put "Any type argument: "; try $block(Any); # fails
put "Int type argument: "; try $block(Int); # fails
put "Int type argument: "; $block(5);
Now most of those invocations fail because they don't specify the right things.
If these were routines I could make multis for a small number of cases but that's an even worse solution in the end. If I had two parameters I'd need four multis. With three such parameters I'd need six. That's a lot of boilerplate code. But, blocks aren't routines so that's moot here.

Related

How to have multiple (alternate) return types in Nim?

I can declare a proc to return a "union type", but cannot actually return values of more than one type:
proc test(b: bool) : int|string =
if b: 1 else: "hello"
echo test true
echo test false
Expected:
1
hello
Actual:
Error: type mismatch: got 'string' for '"hello"' but expected 'int literal(1)'
Even if I swap the return types (string|int) the error is the same. I am only allowed to return an int. I tried putting the return type in parens; and I tried using or instead of |. No dice.
What am I missing? (I don't want to use a variant object.)
The code can be tested online at the Nim Playground. I've scoured google and the Nim documentation, and come up empty.
Return types have to be known at compile time in Nim. Imagine you tried to return the result of that procedure to a string variable. Now you're in a scenario where one return value works, but the other would be a compilation error. In order to allow Nim to figure out whether to throw an error or not it must be able to figure out which type will be returned at compile time. The solution here is to use a static[bool] and a when in place of the if. If you actually need a type that can hold different types on runtime you have to use variant objects.

Checking, if optional parameter is provided in Dart

I'm new to Dart and just learning the basics.
The Dart-Homepage shows following:
It turns out that Dart does indeed have a way to ask if an optional
parameter was provided when the method was called. Just use the
question mark parameter syntax.
Here is an example:
void alignDingleArm(num axis, [num rotations]) {
if (?rotations) {
// the parameter was really used
}
}
So I've wrote a simple testing script for learning:
import 'dart:html';
void main() {
String showLine(String string, {String printBefore : "Line: ", String printAfter}){
// check, if parameter was set manually:
if(?printBefore){
// check, if parameter was set to null
if(printBefore == null){
printBefore = "";
}
}
String line = printBefore + string + printAfter;
output.appendText(line);
output.appendHtml("<br />\n");
return line;
}
showLine("Hallo Welt!",printBefore: null);
}
The Dart-Editor already marks the questionmark as Error:
Multiple markers at this line
- Unexpected token '?'
- Conditions must have a static type of
'bool'
When running the script in Dartium, the JS-Console shows folloing Error:
Internal error: 'http://localhost:8081/main.dart': error: line 7 pos 8: unexpected token '?'
if(?printBefore){
^
I know, that it would be enough to check if printBefore is null, but I want to learn the language.
Does anyone know the reason for this problem?
How to check, if the parameter is set manually?
The feature existed at some point in Dart's development, but it was removed again because it caused more complication than it removed, without solving the problem that actually needed solving - forwarding of default parameters.
If you have a function foo([x = 42]) and you want a function to forward to it, bar([x]) => f(x);, then, since foo could actually tell if x is passed or not, you actually ended up writing bar([x]) => ?x ? foo(x) : foo();. That was worse than what you had to do without the ?: operator.
Ideas came up about having a bar([x]) => foo(?:x) or something which pased on x if it was present and not if it was absent (I no longer remember the actual proposed syntax), but that got complicated fast, fx converting named arguments to positional - bar({x,y}) => foo(?:x, ?:y); - what if y was provided and x was not. It was really just a bad solution for a self-inflicted problem.
So, the ?x feature was rolled back. All optional parameters have a default value which is passed if there is no matching argument in a call. If you want to forward an optional parameter, you need to know the default value of the function you are forwarding to.
For most function arguments, the declared default value is null, with an internal if (arg == null) arg = defaultValue; statement to fix it. That means that the null value can be forwarded directly without any confusion.
Some arguments have a non-null default value. It's mostly boolean arguments, but there are other cases too. I recommend using null for everything except named boolean parameters (because they are really meant to be named more than they are meant to be optional). At least unless there is a good reason not to - like ensuring that all subclasses will have the same default value for a method parameter (which may be a good reason, or not, and should be used judiciosuly).
If you have an optional parameter that can also accept null as a value ... consider whether it should really be optional, or if you just need a different function with one more argument. Or maybe you can introduce a different "missing argument" default value. Example:
abstract class C { foo([D something]); }
class _DMarker implements D { const _DMarker(); }
class _ActualC {
foo([D something = const _DMarker()]) {
if (something == const _DMarker()) {
// No argument passed, because user cannot create a _DMarker.
} else {
// Argument passed, may be null.
}
}
}
This is a big workaround, and hardly ever worth it. In general, just use null as default value, it's simpler.
I was trying something similar:
This does not work
widget.optionalStringParameter ? widget.optionalStringParameter : 'default string'
This works
widget.optionalStringParameter != null ? widget.optionalStringParameter : 'default string'
This also works
widget.optionalStringParameter ?? 'default string'
There was support for checking if an optional parameter was actually provider in early Dart days (pre 1.0) but was removed because it causes some troubles.

If not let - in Swift

is there is a way to negate the "if let" in swift?
This looks silly to me:
if let type = json.type {
} else {
XCTFail("There is no type in the root element")
}
I can't use XCTAssertNotNil, because json.type is a enum.
enum JSONDataTypes {
case Object
case Array
case Number
case String
}
Thanks a lot
EDIT: it is a:
var type: JSONDataTypes? = nil
Swift 2.0 (Xcode 7) and later have the new guard statement, which sort of works like an "if not let" -- you can conditionally bind a variable in the remainder of the enclosing scope, keeping the "good path" in your code the least-indented.
guard let type = json.type else {
XCTFail("There is no type in the root element")
}
// do something with `type` here
The catch to this is that the else clause of a guard must exit that scope (because otherwise you'd fall into code after that clause, where the guarded variables, like type above, are unbound). So it has to end with something like return, break, continue or a function that is known to the compiler to never return (i.e. annotated #noreturn, like abort()... I don't recall offhand if that includes XCTFail, but it should (file a bug if it's not).
For details, see Early Exit in The Swift Programming Language.
As for really-old stuff... There's no negated form of if-let in Swift 1.x. But since you're working with XCTest anyway, you can just make testing the optional part of an assertion expression:
XCTAssert(json.type != nil, "There is no type in the root element")
Here's how you do it:
if json.type == nil {
// fail
}
Another alternative I've used a few times:
switch json.type
{
case .None: // ...
case .Some(.Object): // ...
case .Some(.Array): // ...
case .Some(.Number): // ...
case .Some(.String): // ...
}
Since the ? is actually Optional<T> which is an enum on its own, defined as:
enum Optional<T> : Reflectable, NilLiteralConvertible
{
case None
case Some(T)
...
}

What does it mean to pass `_` (i.e., underscore) as the sole parameter to a Dart language function?

I'm learning Dart and see the following idiom a lot:
someFuture.then((_) => someFunc());
I have also seen code like:
someOtherFuture.then(() => someOtherFunc());
Is there a functional difference between these two examples?
A.k.a., What does passing _ as a parameter to a Dart function do?
This is particularly confusing given Dart's use of _ as a prefix for declaring private functions.
It's a variable named _ typically because you plan to not use it and throw it away. For example you can use the name x or foo instead.
The difference between (_) and () is simple in that one function takes an argument and the other doesn't.
DON’T use a leading underscore for identifiers that aren’t private.
Exception: An unused parameter can be named _, __, ___, etc. This
happens in things like callbacks where you are passed a value but you
don’t need to use it. Giving it a name that consists solely of
underscores is the idiomatic way to indicate the value isn’t used.
https://dart.dev/guides/language/effective-dart/style
An underscore (_) is usually an indication that you will not be using this parameter within the block. This is just a neat way to write code.
Let's say I've a method with two parameters useful and useless and I'm not using useless in the code block:
void method(int useful, int useless) {
print(useful);
}
Since useless variable won't be used, I should rather write the above code as:
void method(int useful, int _) { // 'useless' is replaced with '_'
print(useful);
}
From the Dart Doc - PREFER using _, __, etc. for unused callback parameters.
Sometimes the type signature of a callback function requires a
parameter, but the callback implementation doesn't use the
parameter. In this case, it's idiomatic to name the unused parameter
_. If the function has multiple unused parameters, use additional
underscores to avoid name collisions: __, ___, etc.
futureOfVoid.then((_) {
print('Operation complete.');
});
This guideline is only for functions that are both anonymous and
local. These functions are usually used immediately in a context
where it's clear what the unused parameter represents. In contrast,
top-level functions and method declarations don't have that context,
so their parameters must be named so that it's clear what each
parameter is for, even if it isn't used.
Copy paste the following code in DartPad and hit Run -
void main() {
Future.delayed(Duration(seconds: 1), () {
print("No argument Anonymous function");
});
funcReturnsInteger().then((_) {
print("Single argument Anonymous function " +
"stating not interested in using argument " +
"but can be accessed like this -> $_");
});
}
Future<int> funcReturnsInteger() async {
return 100;
}
That expression is similar to "callbacks" in node.js, the expression have relation to async task.
First remember that => expr expression is shorthand for {return *expr*}, now in someFuture.then((_) => someFunc()), someFuture is a variable of type Future, and this keeps your async task, with the .then method you tell what to do with your async task (once completed), and args in this method you put the callback ((response) => doSomethingWith(response)).
You learn more at Future-Based APIs and Functions in Dart. Thanks
Very common use, is when we need to push a new route with Navigator but the context variable in the builder is not going to be used:
// context is going to be used
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => NewPage(),
));
// context is NOT going to be used
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => NewPage(),
));
I think what people are confusing here is that many think the _ in
someFuture.then((_) => someFunc());
is a parameter provided to the callback function which is wrong, its actually a parameter passed back from the function that you can give a name that you want (except reserved keywords of course), in this case its an underscore to show that the parameter will not be used. otherwise, you could do something like in example given above:((response) => doSomethingWith(response))

Why isn't this Perl code an error

I'm writing a WxPerl program and instead of
$panel->SetDropTarget( MyTextDropTarget->new($panel) );
I wrote
$panel->SetDropTarget->( MyTextDropTarget->new($panel) );
and Perl didn't complain. (Perl called some function with some arguments, and the script did error out with an error message:
Usage: Wx::Window::SetDropTarget(THIS, target) at ./x.pl line 230.
I'm curious as to how Perl parsed the 'wrong' version.
Added edit:
Okay, so if $x = \&some_function, then I understand why
$x->($arg1, $arg2, ...)
calls some_function($arg1, $arg2, .....).
runrig's example is one possibility, but I'm quite sure that:
1) $panel contains a blessed object reference, not a string.
2) SetDropTarget is a method (in a base class) of $panel.
From the error message we can assume that SetDropTarget() being called. If runrig's example still applies here (and I'd guess it does), then even though SetDropTarget isn't followed by parentheses, i.e. I have
$panel->SetDropTarget->
instead of
$panel->SetDropTarget()->
Perl is still invoking SetDropTarget? (which inspects the number and type of its arguments and then fatally complains at runtime). Is that what happens?
Because it's perfectly valid syntax. $panel->SetDropTarget->( MyTextDropTarget->new($panel) ) means "Call the &SetDropTarget method from $panel, and then dereference the subref that &SetDropTarget returns." It's not what you meant to write, I'm guessing, but any error thrown would be at runtime, even in strict mode.
Your SetDropTarget likely does not return a code reference, but you can't tell that until runtime:
#!/usr/bin/perl
my $panel = 'main';
$panel->SetDropTarget->("bloomin'");
sub SetDropTarget {
return sub { print "Set the $_[0] drop target!\n" }
}
Perl parsed
$panel->SetDropTarget->( MyTextDropTarget->new($panel) );
to mean "$panel is an object; call its SetDropTarget method (optional parenthesis omitted), which will return a reference to a sub; call that sub, passing the the result of MyTextDropTarget->new($panel) as its single parameter."
That is, Perl expected SetDropTarget to be something like foo in the following code:
sub foo {
return sub {
my $bar = shift;
return $bar . ', world!';
}
}
foo()->('Hello');
foo->('Goodby');

Resources