In Chapel, we can set the default value of function formal arguments easily, for example,
proc test( a = 1, b = 2.0, c = "hi" ) {
...
}
and call the function by using keywords also:
test( 10 ); // a = 10, b = 2.0, c = "hi"
test( b = 3.14 ); // a = 1, b = 3.14, c = "hi"
test( c = "yo" ); // a = 1, b = 2.0, c = "yo"
Here, I am wondering if it is possible to define a keyword argument that does not require a predefined default value. More specifically, I would like to write a function that can optionally receive an array depending on cases (e.g., to save intermediate data). Here, the only requirement is that I can check whether the actual argument is passed or not, and there is no need to give the default array value. I imagined something like
proc test( ..., optional d: [] real ) {
if present( d ) then ...;
}
or
proc test( ..., d: [] real = None ) {
if present( d ) then ...;
}
but was not able to find similar things. At the moment, my workaround is to give some dummy default value and check their properties to determine whether an actual argument is passed.
proc test( arr = empty2Dreal ) { ... } // where "empty2Dreal" is a pre-defined global array
or
proc test( arr = reshape( [0.0], {1..1,1..1} ) ) { ... } // some dummy array
}
However, I am wondering whether there might be a more elegant(?) or idiomatic(?) approach...
Edit
As suggested in the comment, it is also convenient to overload several functions to get different interfaces, but at some point I guess I need to pass some "dummy" object to the final (full-fledged) routine and ask the latter to see if the passed object is "dummy" or not... MWE is something like this:
const empty1Dint: [1..0] int;
proc test( x: real, arr: [] int )
{
writeln("test() with 2 args");
writeln(( x, arr ));
// here, I need to check whether the passed object is
// an actual array or not by some predefined rule
if arr.size > 0 then writeln("got a non-empty array");
}
proc test( x: real )
{
writeln("test() with 1 arg");
test( x = x, arr = empty1Dint );
}
var work = [1,2,3,4,5];
test( x = 1.0 );
writeln();
test( x = 1.0, arr = work );
which gives
test() with 1 arg
test() with 2 args
(1.0, )
test() with 2 args
(1.0, 1 2 3 4 5)
got a non-empty array
The corresponding default-value version is
const empty1Dint: [1..0] int;
proc test( x: real, arr: [] int = empty1Dint )
{
writeln("test() with 2 args");
writeln(( x, arr ));
if arr.size > 0 then writeln("got a non-empty array");
}
var work = [1,2,3,4,5];
test( x = 1.0 );
writeln();
test( x = 1.0, arr = work );
which gives
test() with 2 args
(1.0, )
test() with 2 args
(1.0, 1 2 3 4 5)
got a non-empty array
Although the above approach works for arrays, the rule needs to change depending on the type of objects used. So, I was wondering if there is some systematic way, e.g., to pass a "null pointer" or some unique global object to tell the final routine about the presence of the actual data. (But, as noted above, the above approach works for arrays).
Edit 2
Another approach may be simply to pass an additional flag for using the passed array (then there is no need to think much about the nature of the default object, so may be overall simpler...)
const empty1Dint: [1..0] int;
proc test( x: real, arr: [] int = empty1Dint, use_arr = false )
{
writeln( "x= ", x );
if use_arr {
writeln("working with the passed array...");
for i in 1..arr.size do arr[ i ] = i * 10;
}
}
test( x = 1.0 );
writeln();
var work: [1..5] int;
test( x = 2.0, arr = work, use_arr = true );
writeln( "work = ", work );
Edit 3
Following Option 3 in the answer, here is a modified version of my code using _void and void:
proc test( x: real, arr: ?T = _void )
{
writeln( "\ntest():" );
writeln( "x = ", x );
writeln( "arr = ", arr );
writeln( "arr.type = ", arr.type:string );
writeln( "T = ", T:string );
if arr.type != void {
writeln( "doing some checks" );
assert( isArray( arr ) );
}
if arr.type != void {
writeln( "writing arr" );
for i in 1..arr.size do arr[ i ] = i * 10;
}
}
// no optional arg
test( x = 1.0 );
// use an optional arg
var work: [1..5] int;
test( x = 2.0, arr = work );
writeln( "\nmain> work = ", work );
Result:
test():
x = 1.0
arr =
arr.type = void
T = void
test():
x = 2.0
arr = 0 0 0 0 0
arr.type = [domain(1,int(64),false)] int(64)
T = [domain(1,int(64),false)] int(64)
doing some checks
writing arr
main> work = 10 20 30 40 50
This answer discusses 3 answers:
The strategy discussed in the edit of the question.
A strategy using a Box type
A strategy using a generic function with a void default value
My favorite of these options is Option 3.
Option 1
proc test( x: real, arr: [] int = empty1Dint, use_arr = false ) strategy described in the question is reasonable, if a little verbose. The main drawback here is that you'd need more overloads of test if you didn't want the call sites to have to pass use_arr=true or use_arr=false. Here is a simple program that does that:
proc test(optional, hasOptional:bool) {
writeln("in test");
writeln(" optional is ", optional);
if hasOptional == false then
writeln(" note: default was used for optional");
}
proc test(optional) {
test(optional, hasOptional=true);
}
proc test() {
var emptyArray:[1..0] int;
test(emptyArray, hasOptional=false);
}
test();
test([1, 2, 3]);
Option 2
Another alternative is to create a class to store the optional argument data, and pass nil by default.
class Box {
var contents;
}
proc makeArray() {
var A:[1..2] int;
return A;
}
proc emptyBox() {
var A:[1..0] int;
var ret: owned Box(A.type) = nil;
return ret;
}
proc test( optional=emptyBox() ) {
writeln("in test with optional=", optional);
}
test();
test(new owned Box(makeArray()));
Here the main tricky part is that the array type returned by makeArray() and emptyBox() have to match. It'd be possible to use a type alias to have them refer to the same array type, but how exactly that would fit in depends on your application. Another problem with this approach is that it causes the array to be copied in the process of passing such an argument. And, one has to think about where the Box will be destroyed. Is test to hang on to the array value (e.g. storing it in a data structure) or just going to use it temporarily? This is set by the type returned by emptyBox in my example.
It's probably reasonable for the standard library to gain such a Box type but it doesn't have one now.
Option 3
My favorite solution to this problem is a third strategy altogether.
Chapel includes a value of void type called _void. The key is the declaration proc test( optional:?t=_void ). Here test is a generic function - the syntax argument:?t indicates that the argument can have a varied type (which will be available as t within the function). This is necessary to get a generic argument that also has a default value (otherwise the argument will have only the type inferred from the default value).
If no optional argument is provided, it will instantiate with optional having type void. Which makes sense as a way to not pass something. Technically it's not the same as checking if the default value was provided, but I think a call site like test(optional=_void) is reasonably clear at communicating that the value of optional should be ignored (since it's void).
Anyway here is the code:
proc test( optional:?t=_void ) {
writeln("in test");
writeln(" optional is ", optional);
if optional.type == void then
writeln(" note: default was used for optional");
}
test();
test([1, 2, 3]);
Related
i am currently trying to do some self learning in swift just for my own interest. in the course i bought it says that we should create a function similar to this one in order to solve my problem. but I'm blankly staring trying to figure out what this function actually does?
func unknown() -> () -> Int {
var x = 0
let z: () -> Int = {
x += 1
return x
}
return z
}
It is a function that returns another function which will return an integer that will be increased everytime you call it:
let afunc = unknown()
let value1 = afunc() // 1
let value2 = afunc() // 2
let value3 = afunc() // 3
The interesting part of this is the return type. () -> Int is a function that returns an Int, which means that unknown returns a function rather than something simple, like a number.
z is then a variable of that same type and is assigned a function definition to be returned.
If you assign the result of unknown to a variable, you can then invoke the returned function.
This implementation of a high order function is an interesting way of defining generators. An infinite sequence-like class would've achieve the same thing, but with more verbosity:
class MySequence {
private var x = 0
func unknown() -> Int {
x += 1
return x
}
}
var seq = MySequence()
let unknown = seq.unknown
print(unknown()) // 1
print(unknown()) // 2
print(unknown()) // 3
// ... and so on
The main difference between the class and the anonymous closure is the storage for x: the closure captures in due to using the variables within its body, while the class declares explicit storage for the property.
Some fancy stuff can result by using high order functions, like a generator for the Fibonacci numbers:
func fibonnaciSequence() -> () -> Int? {
var a = 0, b = 1
return { let c = a; a += b; b = c; return c }
}
let fibo = fibonnaciSequence()
while let f = fibo() {
// this will print forever
// actually not forever, it will stop at some point due to += overflowing
print(f)
}
I created a function that recieves input and compare it to a list, when find a match it return the match, in this case this match is the attribute of a class that i created.
I understand that the problem is with the return statement, so in the beginning of the function I declare the return as "Any", further more than that I'm kinda lost.
The error is this: A 'return' expression required in a function with a block body ('{...}')
class Class1(var self: String)
var test_class = Class1("")
fun giver(){
test_class.self = "Anything"
}
class Funciones(){
fun match_finder(texto: String): Any{
var lista = listOf<String>(test_class.self)
var lista_de_listas = listOf<String>("test_class.self")
var count = -1
for (i in lista_de_listas){
count = count + 1
if (texto == i){
lista_de_listas = lista
var variable = lista_de_listas[count]
return variable
}
}
}
}
fun main(){
giver()
var x = "test_class.self"
var funcion = Funciones()
var y = funcion.match_finder(x)
println(y)
}
To explain you what the problem is, let's consider the following code:
class MyClass {
fun doSomething(): String {
val numbers = listOf(1, 2, 3)
for (number in numbers) {
if (number % 2 == 0) {
return "There is at least one even number in the list"
}
}
}
}
If you try compiling it you'll get the same error message as in your question: A 'return' expression required in a function with a block body ('{...}'). Why is that?
Well, we defined a function doSomething returning a String (it could be any other type) but we're returning a result only if the list of numbers contains at least one even number. What should it return if there's no even number? The compiler doesn't know that (how could it know?), so it prompts us that message. We can fix the code by returning a value or by throwing an exception:
class MyClass {
fun doSomething(): String {
val numbers = listOf(1, 2, 3)
for (number in numbers) {
if (number % 2 == 0) {
return "There is at least one even number in the list"
}
}
// return something if the list doesn't contain any even number
return "There is no even number in the list"
}
}
The same logic applies to your original code: what should the function return if there is no i such that texto == i?
Please also note that the solution you proposed may be syntactically correct - meaning it compiles correctly - but will probably do something unexpected. The for loop is useless since the if/else statement will always cause the function to return during the first iteration, so the value "There is no match" could be returned even if a match actually exists later in the list.
I searched online, if someone has the same problem, the correct code is as follows:
class Funciones(){
fun match_finder(texto: String): Any{
var lista = listOf<String>(test_class.self)
var lista_de_listas = listOf<String>("test_class.self")
var count = -1
var variable = " "
for (i in lista_de_listas){
count = count + 1
if (texto == i){
lista_de_listas = lista
var variable = lista_de_listas[count]
return variable
} else {
return "There is no match"
}
}
return variable
}
}
I have created a function in scala equivalant to ORACLE DECODE function. I want to use the function with SPARK dataframes columns. I have tried it but getting multiple issues with Datatype mismatches.
I do not want to create UDF for each program. I want to create something generic and reuse it multiple times.
Function:
def ODECODE(column: Any, Param: Any*) : Any = {
var index = 0
while (index < Param.length) {
var P = Param(index)
var Q = column
if (P.equals(Q))
return Param(index + 1)
else index = index + 1
}
return Param (Param.length - 1)
}
I want to use it some thing like this:
Assuming "Emp" is a dataframe containing data from employee table with columns(first name, Last Name, Grade).
Emp.select(ODECODE("grade", "A", 1, "B", 2, "C", 3, "FAIL")).show()
This is one example. The datatype in the grade column can be String or Integer. So I have taken Datatypes in the decode function (Above) as ANY but with Dataframes it does not perform the Transformation. It gives datatype mismatches.
I want to create individual functions/Methods for some of the unsupported Oracle functions and reuse them where ever required in my transformations. So any suggestion to make this work is appreciated.
I know this is late, but I actually needed this and found your example. I was able to implement it with a few changes. I am no expert though, there may be a better way of doing this.
import util.control.Breaks._;
def ODECODE[T](column: String, params: Seq[T]) : String = {
try {
var index = 0;
breakable {
while (index < params.length) {
var P = params(index);
var Q = column;
if(P.equals(Q)) {
break;
}
index += 1;
}
}
params(index - 1).toString;
}catch {
case ife: Exception =>
ife.printStackTrace();
"0";
}
}
println(ODECODE("TEST", 0, "TEgST", 8, "***", 0))
In Go (and G++?), the following is a common idiom:
func sqr(x int) (n int, err error) {
n = x * x
err = nil
return
}
The (n int, err error) explicitly enumerates the name and type of the return values. There are in my opinion lots of advantages to this, and I like it.
In Perl 6, we can:
my sub sqr (Int:D $x) returns Int:D {
$x ** 2;
}
The return is implicit, which makes me kind of uncomfortable (we could make it explicit with return), but you may notice the return type is specified (as is the fact it's Defined).
Unsurprisingly, there's no obvious way to return a value explicitly by name, but I'm curious, since Perl (especially 6) is extensively modifiable in every way, if there's a way to implement this.1
1 However hacky it may be, but too hacky and I'd avoid using it for "real" things.
If all else fails, you can always write your own slang.
However, here are two less involved approaches I came up with, the first one using a dynamic variable of fixed name, the second one using an rw parameter of user-defined name:
multi sub trait_mod:<is>(Routine:D \r, :$dynrv!) {
r.wrap(-> | { my $*rv; callsame; $*rv })
}
multi sub trait_mod:<is>(Routine:D \r, :$pararv!) {
r.wrap(-> |c { my $rv; callwith(|c, $rv); $rv })
}
sub double($x) is dynrv {
$*rv = $x * 2;
return 666; # discarded
}
sub triple($x, $y is rw) is pararv {
$y = $x * 3;
return 666; # discarded
}
say double 42;
say triple 42;
Note that this only supports a single return value, though I have some ideas how multiple ones could be made to work...
edit: Eg this way:
multi sub trait_mod:<is>(Routine:D \r, :#dynrv!) {
r.wrap(-> | {
my #rv = Nil xx #dynrv;
my $*rv = Map.new(#dynrv Z=> #rv);
callsame;
#dynrv > 1 ?? #rv !! #rv[0];
})
}
multi sub trait_mod:<is>(Routine:D \r, Int :$pararv!) {
r.wrap(-> |c {
my #rv = Nil xx $pararv;
callwith(|c, |#rv);
$pararv > 1 ?? #rv !! #rv[0];
})
}
sub divmod($a, $b) is dynrv<d m> {
$*rv<d> = $a div $b;
$*rv<m> = $a mod $b;
}
sub plusmin($a, $b, $p is rw, $m is rw) is pararv(2) {
$p = $a + $b;
$m = $a - $b;
}
say divmod 14, 3;
say plusmin 14, 3;
While slangs can be used to get exactly what you want, I believe they're the wrong size solution to this problem. Firstly, cat's Go example is returning error information as well as an (Int). I'd suggest the PerlĀ 6 way for that is to simply return a Fail object using &fail which the caller can test for using .defined or the // operator;
if $something_wrong {
return fail "Dang! Even the squaring function isn't working today."
}
else {
return $x ** 2
}
I know this doesn't document the dual return values as requested, but do you want to use an explicit variable for exceptional out-of-band data? What if it wasn't error data but other information?
Let's assume we want to return an (Int) with an Easter-egg message. In this case, as the extra data is a different type, (Str), we can run-time mixin a role with a .Str method that returns the message if the return value is used in string context.
return $x * $x but "Suprise! Bet you weren't expecting that!"
Alternatively, if the extra data is of the same type we can explicitly mixin an anonymous role. Let's say we want to return an (Int) with a .size property;
return $x but role { has $.size = calculate_size() }
Finally, you can document your return type explicitly by declaring the role and then using a subset to define your own (Int) type that demands the role;
role Size { has UInt:D $.size = 0 }
subset MyInt of Int where Size;
sub sqr(Int:D $x, UInt:D :$size = 12) returns MyInt:D {
return $x * $x but Size($size)
}
my $square5 = sqr(5);
say "5 squared is $square5 with size $square5.size()."
# prints: 5 squared is 25 with size 12.
Details are in S14 and S12 - Anonymous mixin roles
For the following code:
inc = -> value = (value ? 0) + 1
dec = -> value = (value ? 0) - 1
print = -> console.log value ? 0
How can you make this work properly, so inc and dec close upon value instead of creating separate function-local variables, in the way other than explicitly assigning something to value?
In plain Javascript, you would just declare var value at outer scope:
var value;
function inc() { value = (value || 0) + 1; };
function dec() { value = (value || 0) - 1; };
function print() { console.log(value || 0); };
What is CoffeeScript way for exactly the same thing?
In CoffeeScript, the way to introduce a local variable is to assign to the variable in the appropriate scope.
This is simply the way that CoffeeScript was defined and as such is similar to Python or Ruby, which do not require a "variable declaration", except CoffeeScript also allows forward access. A side-effect is that one cannot shadow a lexical variable.
Just as with the placement of var in JavaScript, where this assignment is done (as long as it is in the correct scope) does not affect the scope of the variable.
Given
x = undefined
f = -> x
// JS
var f, x;
x = void 0;
f = function() {
return x;
};
Given
f = -> x
x = undefined
// JS
var f, x;
f = function() {
return x;
};
x = void 0;